Merge pull request #69 from bjdgyc/dev

Dev
This commit is contained in:
bjdgyc 2021-12-28 16:48:08 +08:00 committed by GitHub
commit f267891f19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 230 additions and 64 deletions

View File

@ -36,7 +36,9 @@ AnyLink 服务端仅在 CentOS 7、Ubuntu 18.04 测试通过,如需要安装
> https://github.com/bjdgyc/anylink/releases > https://github.com/bjdgyc/anylink/releases
### 使用问题 ### 使用问题
> 使用客户端前,必须申请安全的 https 证书,不支持私有证书连接 > 对于测试环境,可以使用 vpn.test.vqilu.cn 绑定host进行测试
>
> 对于线上环境,必须申请安全的 https 证书,不支持私有证书连接
> >
> 客户端请使用群共享文件的版本,其他版本没有测试过,不保证使用正常 > 客户端请使用群共享文件的版本,其他版本没有测试过,不保证使用正常
@ -109,7 +111,7 @@ sudo ./anylink
> 以下参数必须设置其中之一 > 以下参数必须设置其中之一
网络模式选择,需要配置 `link_mode` 参数,如 `link_mode="tun"`,`link_mode="macvtap"`,`link_mode="tap"` 等参数。 不同的参数需要对服务器做相应的设置。 网络模式选择,需要配置 `link_mode` 参数,如 `link_mode="tun"`,`link_mode="macvtap"`,`link_mode="tap"(不推荐)` 等参数。 不同的参数需要对服务器做相应的设置。
建议优先选择 tun 模式,其次选择 macvtap 模式,因客户端传输的是 IP 层数据,无须进行数据转换。 tap 模式是在用户态做的链路层到 IP 层的数据互相转换,性能会有所下降。 如果需要在虚拟机内开启 tap 模式,请确认虚拟机的网卡开启混杂模式。 建议优先选择 tun 模式,其次选择 macvtap 模式,因客户端传输的是 IP 层数据,无须进行数据转换。 tap 模式是在用户态做的链路层到 IP 层的数据互相转换,性能会有所下降。 如果需要在虚拟机内开启 tap 模式,请确认虚拟机的网卡开启混杂模式。
@ -158,7 +160,7 @@ ipv4_start = "192.168.10.100"
ipv4_end = "192.168.10.200" ipv4_end = "192.168.10.200"
``` ```
### tap 设置 ### ~~tap 设置~~
1. 创建桥接网卡 1. 创建桥接网卡
@ -246,7 +248,7 @@ sh bridge-init.sh
-p 443:443 -p 8800:8800 \ -p 443:443 -p 8800:8800 \
--restart=always \ --restart=always \
bjdgyc/anylink \ bjdgyc/anylink \
-c=/etc/server.toml --ip_lease = 1209600 \ # IP地址租约时长 -c=/etc/server.toml --ip_lease=1209600 # IP地址租约时长
``` ```
7. 构建镜像 7. 构建镜像

View File

@ -15,3 +15,6 @@
| 代码oo8 | | | 代码oo8 | |
| 甘磊 | https://github.com/ganlei333 | | 甘磊 | https://github.com/ganlei333 |
| Oo@ | https://github.com/chooop | | Oo@ | https://github.com/chooop |
| 虚极静笃 | |
| Ficapy | |

View File

@ -3,5 +3,5 @@ package base
const ( const (
APP_NAME = "AnyLink" APP_NAME = "AnyLink"
// 修复前端bug // 修复前端bug
APP_VER = "0.6.2" APP_VER = "0.7.1"
) )

View File

@ -101,7 +101,7 @@ func initCmd() {
_, err := os.Stat(conf) _, err := os.Stat(conf)
if errors.Is(err, os.ErrNotExist) { if errors.Is(err, os.ErrNotExist) {
// 没有配置文件,不做处理 // 没有配置文件,不做处理
return panic(err)
} }
linkViper.SetConfigFile(conf) linkViper.SetConfigFile(conf)

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<AnyConnectProfile xmlns="http://schemas.xmlsoap.org/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.xmlsoap.org/encoding/ AnyConnectProfile.xsd">
<ClientInitialization>
<UseStartBeforeLogon UserControllable="false">false</UseStartBeforeLogon>
<StrictCertificateTrust>false</StrictCertificateTrust>
<RestrictPreferenceCaching>false</RestrictPreferenceCaching>
<RestrictTunnelProtocols>IPSec</RestrictTunnelProtocols>
<BypassDownloader>true</BypassDownloader>
<WindowsVPNEstablishment>AllowRemoteUsers</WindowsVPNEstablishment>
<LinuxVPNEstablishment>AllowRemoteUsers</LinuxVPNEstablishment>
<CertEnrollmentPin>pinAllowed</CertEnrollmentPin>
<CertificateMatch>
<KeyUsage>
<MatchKey>Digital_Signature</MatchKey>
</KeyUsage>
<ExtendedKeyUsage>
<ExtendedMatchKey>ClientAuth</ExtendedMatchKey>
</ExtendedKeyUsage>
</CertificateMatch>
<BackupServerList>
<HostAddress>localhost</HostAddress>
</BackupServerList>
</ClientInitialization>
<ServerList>
<HostEntry>
<HostName>VPN Server</HostName>
<HostAddress>localhost</HostAddress>
</HostEntry>
</ServerList>
</AnyConnectProfile>

29
server/conf/server.toml Normal file
View File

@ -0,0 +1,29 @@
#示例配置信息
#其他配置文件,可以使用绝对路径
#或者相对于 anylink 二进制文件的路径
#数据文件
db_type = "sqlite3"
db_source = "./conf/anylink.db"
#证书文件
cert_file = "./conf/vpn_cert.pem"
cert_key = "./conf/vpn_cert.key"
files_path = "./conf/files"
#系统名称
issuer = "XX公司VPN"
#后台管理用户
admin_user = "admin"
#pass 123456
admin_pass = "$2a$10$UQ7C.EoPifDeJh6d8.31TeSPQU7hM/NOM2nixmBucJpAuXDQNqNke"
jwt_secret = "abcdef.0123456789.abcdef"
#服务监听地址
server_addr = ":443"
#后台服务监听地址
admin_addr = ":8800"

27
server/conf/vpn_cert.key Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEArZc7o1r/+LSwyJXScX5oNNsOJsaJMuv4sWWFMiLUpf0gBTZd
ujPUHxzEOujeD4LOCsaDRgwjgLEGJjnpRPeNROwtgE2lY+RuGUf6al/Qnt+Afb1X
UsBkqbapHbzL+Ssochtwat8wBteLqJWRUeFz5528YJ0CINLImBVJlthX+zQtcsXQ
HQGiRqDC28YjHuKTm4bh7G5EJQoTfPSfpFd03R5YG8oocWFYR5oEgbMeOgOADH/h
UnxexbS1zAHKJVGqkwVrV4bccsy+LfgzWovM2/t0Y8iSvXOO+W9OqEOmKZc6L0Lg
3lk59l80DJHzNTn60GpIK8HJq/EsnAL/8XtVBwIDAQABAoIBACXjPEELO5Ms3Ojq
ymO7E0N2DECqVIeouT7+yXOH5qHT/YkltI9PgJzJyoqRCOaZxh7T9RL000rjWFQ/
j4pd/ZdtdQDr8Y077kvWSfGtt/r1DTZkfQqys0XXeFHlQx+/K7S8CG1LCVB0+yZw
fqdAbeu/ob30huJjHyUSgF1MGufYvuII6x0CGORwzruWWFniXkg2z+9SP4x4RSfm
exMUE4T4tlzR63QaW02xWEDTWCSQw/FgjpCWwryDVCmnLf63UhI+4hITqZLL+ROd
sG/8Yp284q7BYBKk4/N1HD4W1vU+dls3glxZ22NCQKx+2RVtqTrRUd/d4AnxOmMR
dnfh4AECgYEA7cl9NIRrtQdW+KFcoSdyP2F+SU74nSAh6Uolzwr9lHB+NbMJ5g79
eU1zp3RAvSFg249L4cnceaFL1LTPcNN0xhpaJ7v5FQWk5tkddSmy2T3CAh8VwLXF
487pgakO1SpS6uz+BtwsAFOS8k/GjYeSbPR4e9F/FbYAvGYwOLNj2ocCgYEAuuL8
xnFnt95TwWptu4T97YXTeZRB17jiH1BhX+QawsSafagsWlSKihKMxYhfCHiwztS/
KsCnkS6cH9slU3y4gvCiT1S4z1Qkw93ljUQXCzRIVEd9SxXoQMeRi+/5c239Fhnu
aoxESAFWNXJZ5r9Jp3qukHvEtYn2FoE1Zkmu0YECgYApULgDdvqr4pGW85p/mbX9
Ezh5DlKeImYh/bMiDTvQHdegBvKyWWprOCzfLJDPC8yjeXtqyMMZExB07dGZPfRt
M0j03HFD2M41GgZHRC6CFnvuGG6UJEE0+s+Rqskb+pWbof/lOz4d9Gd02K2cC7FC
YxvID7dwE0Z/dZXtVCYGYwKBgQCjckPKtoIUcBBmV1NzLiP66REEAuL27Q5ufpk7
CT9SWioXfc6Ujd3AVeriE5uxyAQyUCSFGosy0UXgIoRpmOmyMwxxP1KGmTuyRc4u
l39j4Czl8MQmuBkxFpk3fwB2sJopCzLV4qkRJIImKkVwJpofLI+hc22dq/QayJRQ
Sl7ngQKBgQCkfcbQDvhkL6QKUC/K7MDGw9JMICLUpRyp6D3ibeL7i6WO6dkKde2t
O/oLz2XvG0NR0nulhThpWUdyUWco3FZ038jiuY8ZZum5wdVBDOcDcnuBisE3Kzh8
p7WycoWItAVxmyTKzHJIZ7pFQULYjap7gFSUPE9uBQZu09VKBtGPHA==
-----END RSA PRIVATE KEY-----

61
server/conf/vpn_cert.pem Normal file
View File

@ -0,0 +1,61 @@
-----BEGIN CERTIFICATE-----
MIIF9zCCBN+gAwIBAgIQBNH+cm5YH1O2NhfT+zB+ATANBgkqhkiG9w0BAQsFADBu
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMS0wKwYDVQQDEyRFbmNyeXB0aW9uIEV2ZXJ5d2hlcmUg
RFYgVExTIENBIC0gRzEwHhcNMjExMjEyMDAwMDAwWhcNMjIxMjEzMjM1OTU5WjAc
MRowGAYDVQQDExF2cG4udGVzdC52cWlsdS5jbjCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAK2XO6Na//i0sMiV0nF+aDTbDibGiTLr+LFlhTIi1KX9IAU2
Xboz1B8cxDro3g+CzgrGg0YMI4CxBiY56UT3jUTsLYBNpWPkbhlH+mpf0J7fgH29
V1LAZKm2qR28y/krKHIbcGrfMAbXi6iVkVHhc+edvGCdAiDSyJgVSZbYV/s0LXLF
0B0BokagwtvGIx7ik5uG4exuRCUKE3z0n6RXdN0eWBvKKHFhWEeaBIGzHjoDgAx/
4VJ8XsW0tcwByiVRqpMFa1eG3HLMvi34M1qLzNv7dGPIkr1zjvlvTqhDpimXOi9C
4N5ZOfZfNAyR8zU5+tBqSCvByavxLJwC//F7VQcCAwEAAaOCAuEwggLdMB8GA1Ud
IwQYMBaAFFV0T7JyT/VgulDR1+ZRXJoBhxrXMB0GA1UdDgQWBBQKyNOGPzBPyqY9
nxahHC+B6xT83TAcBgNVHREEFTATghF2cG4udGVzdC52cWlsdS5jbjAOBgNVHQ8B
Af8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMD4GA1UdIAQ3
MDUwMwYGZ4EMAQIBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQu
Y29tL0NQUzCBgAYIKwYBBQUHAQEEdDByMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
cC5kaWdpY2VydC5jb20wSgYIKwYBBQUHMAKGPmh0dHA6Ly9jYWNlcnRzLmRpZ2lj
ZXJ0LmNvbS9FbmNyeXB0aW9uRXZlcnl3aGVyZURWVExTQ0EtRzEuY3J0MAkGA1Ud
EwQCMAAwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB2ACl5vvCeOTkh8FZzn2Ol
d+W+V32cYAr4+U1dJlwlXceEAAABfa0lBgAAAAQDAEcwRQIgEQ4wS5gyLMK30aeD
xF3kWvsUhkd94HKIl13ckYnukGMCIQD1/6fFUAPjdw2k8f/ctJ7STUHeA1WoBy5H
O/iXBRCkWgB2AFGjsPX9AXmcVm24N3iPDKR6zBsny/eeiEKaDf7UiwXlAAABfa0l
BmYAAAQDAEcwRQIgOoguGrrlpwoxGiJHJNcEWbuH2AOJCDSDiun80DX9hUwCIQCJ
cFCOe5E5VbgHrTWbQ0OUFS0epDgUiG8y9kjfkN1M5QB2AEHIyrHfIkZKEMahOglC
h15OMYsbA+vrS8do8JBilgb2AAABfa0lBfoAAAQDAEcwRQIhAIHCUjXv+M3/jFOU
AzjjMCISczShjqQ5FKqsIYNTUN46AiAom+II914ifwdFiS2xWI0ncSj8cxH6f+WZ
UUQj9RczMDANBgkqhkiG9w0BAQsFAAOCAQEALj5oEwyU+gxVKhLFrBBtkoi9F0HQ
jjSQZvOcKApSXjKS11VdmLGKuy85FSocw7VvDtZ4o43OhO79GMAMiPXroTnPIS5O
ZNxfuusF6HpS+2Dq9UidnlxQmIaJ4A7PkX+NqAI4V6yr839SXKyHJROfXf9hNoJZ
PJeZ94oMwXdeNjFkOismFpvaZcYq7t51xi5tkH/NaJHV5FEU8Or4zk/OoaPe3r+b
2hpltIIaapoNVYLWLW7YS7hlvhjfwPypsR3ev4bTRWvT1tu9+AE+TG0OZqeWGucP
6MjZI5gecOnkQVmBovkRi2lr26PDWrwnAlyoMI3ioU1XaTftIrBL2YalfQ==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEqjCCA5KgAwIBAgIQAnmsRYvBskWr+YBTzSybsTANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0xNzExMjcxMjQ2MTBaFw0yNzExMjcxMjQ2MTBaMG4xCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xLTArBgNVBAMTJEVuY3J5cHRpb24gRXZlcnl3aGVyZSBEViBUTFMgQ0EgLSBH
MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALPeP6wkab41dyQh6mKc
oHqt3jRIxW5MDvf9QyiOR7VfFwK656es0UFiIb74N9pRntzF1UgYzDGu3ppZVMdo
lbxhm6dWS9OK/lFehKNT0OYI9aqk6F+U7cA6jxSC+iDBPXwdF4rs3KRyp3aQn6pj
pp1yr7IB6Y4zv72Ee/PlZ/6rK6InC6WpK0nPVOYR7n9iDuPe1E4IxUMBH/T33+3h
yuH3dvfgiWUOUkjdpMbyxX+XNle5uEIiyBsi4IvbcTCh8ruifCIi5mDXkZrnMT8n
wfYCV6v6kDdXkbgGRLKsR4pucbJtbKqIkUGxuZI2t7pfewKRc5nWecvDBZf3+p1M
pA8CAwEAAaOCAU8wggFLMB0GA1UdDgQWBBRVdE+yck/1YLpQ0dfmUVyaAYca1zAf
BgNVHSMEGDAWgBQD3lA1VtFMu2bwo+IbG8OXsj3RVTAOBgNVHQ8BAf8EBAMCAYYw
HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8C
AQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
Y2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQu
Y29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG
/WwBAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT
MAgGBmeBDAECATANBgkqhkiG9w0BAQsFAAOCAQEAK3Gp6/aGq7aBZsxf/oQ+TD/B
SwW3AU4ETK+GQf2kFzYZkby5SFrHdPomunx2HBzViUchGoofGgg7gHW0W3MlQAXW
M0r5LUvStcr82QDWYNPaUy4taCQmyaJ+VB+6wxHstSigOlSNF2a6vg4rgexixeiV
4YSB03Yqp2t3TeZHM9ESfkus74nQyW7pRGezj+TC44xCagCQQOzzNmzEAP2SnCrJ
sNE2DpRVMnL8J6xBRdjmOsC3N6cQuKuRXbzByVBjCqAA8t1L0I+9wXJerLPyErjy
rMKWaBFLmfK/AHNF4ZihwPGOc7w6UHczBZXH5RFzJNnww+WnKuTPI0HfnVH8lg==
-----END CERTIFICATE-----

View File

@ -19,7 +19,7 @@ func LinkAuth(w http.ResponseWriter, r *http.Request) {
userAgent := strings.ToLower(r.UserAgent()) userAgent := strings.ToLower(r.UserAgent())
xAggregateAuth := r.Header.Get("X-Aggregate-Auth") xAggregateAuth := r.Header.Get("X-Aggregate-Auth")
xTranscendVersion := r.Header.Get("X-Transcend-Version") xTranscendVersion := r.Header.Get("X-Transcend-Version")
if !(strings.Contains(userAgent, "anyconnect") && if !((strings.Contains(userAgent, "anyconnect") || strings.Contains(userAgent, "openconnect")) &&
xAggregateAuth == "1" && xTranscendVersion == "1") { xAggregateAuth == "1" && xTranscendVersion == "1") {
w.WriteHeader(http.StatusForbidden) w.WriteHeader(http.StatusForbidden)
fmt.Fprintf(w, "error request") fmt.Fprintf(w, "error request")
@ -176,7 +176,7 @@ var auth_complete = `<?xml version="1.0" encoding="UTF-8"?>
<vpn-profile-manifest> <vpn-profile-manifest>
<vpn rev="1.0"> <vpn rev="1.0">
<file type="profile" service-type="user"> <file type="profile" service-type="user">
<uri>/profile.xml</uri> <uri>/files/profile.xml</uri>
<hash type="sha1">A8B0B07FBA93D06E8501E40AB807AEE2464E73B7</hash> <hash type="sha1">A8B0B07FBA93D06E8501E40AB807AEE2464E73B7</hash>
</file> </file>
</vpn> </vpn>

View File

@ -15,7 +15,7 @@ func LinkHome(w http.ResponseWriter, r *http.Request) {
connection := strings.ToLower(r.Header.Get("Connection")) connection := strings.ToLower(r.Header.Get("Connection"))
userAgent := strings.ToLower(r.UserAgent()) userAgent := strings.ToLower(r.UserAgent())
if connection == "close" && strings.Contains(userAgent, "anyconnect") { if connection == "close" && (strings.Contains(userAgent, "anyconnect") || strings.Contains(userAgent, "openconnect")) {
w.Header().Set("Connection", "close") w.Header().Set("Connection", "close")
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
return return

View File

@ -22,6 +22,14 @@ func init() {
hn, _ = os.Hostname() hn, _ = os.Hostname()
} }
func HttpSetHeader(w http.ResponseWriter, key string, value string) {
w.Header()[key] = []string{value}
}
func HttpAddHeader(w http.ResponseWriter, key string, value string) {
w.Header()[key] = append(w.Header()[key], value)
}
func LinkTunnel(w http.ResponseWriter, r *http.Request) { func LinkTunnel(w http.ResponseWriter, r *http.Request) {
// TODO 调试信息输出 // TODO 调试信息输出
// hd, _ := httputil.DumpRequest(r, true) // hd, _ := httputil.DumpRequest(r, true)
@ -51,6 +59,7 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) {
// 客户端信息 // 客户端信息
cstpMtu := r.Header.Get("X-CSTP-MTU") cstpMtu := r.Header.Get("X-CSTP-MTU")
cstpBaseMtu := r.Header.Get("X-CSTP-Base-MTU")
masterSecret := r.Header.Get("X-DTLS-Master-Secret") masterSecret := r.Header.Get("X-DTLS-Master-Secret")
localIp := r.Header.Get("X-Cstp-Local-Address-Ip4") localIp := r.Header.Get("X-Cstp-Local-Address-Ip4")
mobile := r.Header.Get("X-Cstp-License") mobile := r.Header.Get("X-Cstp-License")
@ -79,68 +88,71 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) {
base.Debug(cSess.IpAddr, cSess.MacHw, sess.Username, mobile) base.Debug(cSess.IpAddr, cSess.MacHw, sess.Username, mobile)
// 返回客户端数据 // 返回客户端数据
w.Header().Set("Server", fmt.Sprintf("%s %s", base.APP_NAME, base.APP_VER)) HttpSetHeader(w, "Server", fmt.Sprintf("%s %s", base.APP_NAME, base.APP_VER))
w.Header().Set("X-CSTP-Version", "1") HttpSetHeader(w, "X-CSTP-Version", "1")
w.Header().Set("X-CSTP-Protocol", "Copyright (c) 2004 Cisco Systems, Inc.") HttpSetHeader(w, "X-CSTP-Server-Name", fmt.Sprintf("%s %s", base.APP_NAME, base.APP_VER))
w.Header().Set("X-CSTP-Address", cSess.IpAddr.String()) // 分配的ip地址 HttpSetHeader(w, "X-CSTP-Protocol", "Copyright (c) 2004 Cisco Systems, Inc.")
w.Header().Set("X-CSTP-Netmask", sessdata.IpPool.Ipv4Mask.String()) // 子网掩码 HttpSetHeader(w, "X-CSTP-Address", cSess.IpAddr.String()) // 分配的ip地址
w.Header().Set("X-CSTP-Hostname", hn) // 机器名称 HttpSetHeader(w, "X-CSTP-Netmask", sessdata.IpPool.Ipv4Mask.String()) // 子网掩码
HttpSetHeader(w, "X-CSTP-Hostname", hn) // 机器名称
//HttpSetHeader(w, "X-CSTP-Default-Domain", cSess.LocalIp)
HttpSetHeader(w, "X-CSTP-Base-MTU", cstpBaseMtu)
// 允许本地LAN访问vpn网络必须放在路由的第一个 // 允许本地LAN访问vpn网络必须放在路由的第一个
if cSess.Group.AllowLan { if cSess.Group.AllowLan {
w.Header().Set("X-CSTP-Split-Exclude", "0.0.0.0/255.255.255.255") HttpSetHeader(w, "X-CSTP-Split-Exclude", "0.0.0.0/255.255.255.255")
} }
// dns地址 // dns地址
for _, v := range cSess.Group.ClientDns { for _, v := range cSess.Group.ClientDns {
w.Header().Add("X-CSTP-DNS", v.Val) HttpAddHeader(w, "X-CSTP-DNS", v.Val)
} }
// 允许的路由 // 允许的路由
for _, v := range cSess.Group.RouteInclude { for _, v := range cSess.Group.RouteInclude {
if v.Val == "all" { if v.Val == "all" {
continue continue
} }
w.Header().Add("X-CSTP-Split-Include", v.IpMask) HttpAddHeader(w, "X-CSTP-Split-Include", v.IpMask)
} }
// 不允许的路由 // 不允许的路由
for _, v := range cSess.Group.RouteExclude { for _, v := range cSess.Group.RouteExclude {
w.Header().Add("X-CSTP-Split-Exclude", v.IpMask) HttpAddHeader(w, "X-CSTP-Split-Exclude", v.IpMask)
} }
w.Header().Set("X-CSTP-Lease-Duration", fmt.Sprintf("%d", base.Cfg.IpLease)) // ip地址租期 HttpSetHeader(w, "X-CSTP-Lease-Duration", fmt.Sprintf("%d", base.Cfg.IpLease)) // ip地址租期
w.Header().Set("X-CSTP-Session-Timeout", "none") HttpSetHeader(w, "X-CSTP-Session-Timeout", "none")
w.Header().Set("X-CSTP-Session-Timeout-Alert-Interval", "60") HttpSetHeader(w, "X-CSTP-Session-Timeout-Alert-Interval", "60")
w.Header().Set("X-CSTP-Session-Timeout-Remaining", "none") HttpSetHeader(w, "X-CSTP-Session-Timeout-Remaining", "none")
w.Header().Set("X-CSTP-Idle-Timeout", "18000") HttpSetHeader(w, "X-CSTP-Idle-Timeout", "18000")
w.Header().Set("X-CSTP-Disconnected-Timeout", "18000") HttpSetHeader(w, "X-CSTP-Disconnected-Timeout", "18000")
w.Header().Set("X-CSTP-Keep", "true") HttpSetHeader(w, "X-CSTP-Keep", "true")
w.Header().Set("X-CSTP-Tunnel-All-DNS", "false") HttpSetHeader(w, "X-CSTP-Tunnel-All-DNS", "false")
w.Header().Set("X-CSTP-Rekey-Time", "172800") HttpSetHeader(w, "X-CSTP-Rekey-Time", "172800")
w.Header().Set("X-CSTP-Rekey-Method", "new-tunnel") HttpSetHeader(w, "X-CSTP-Rekey-Method", "new-tunnel")
w.Header().Set("X-CSTP-DPD", fmt.Sprintf("%d", cstpDpd)) HttpSetHeader(w, "X-CSTP-DPD", fmt.Sprintf("%d", cstpDpd))
w.Header().Set("X-CSTP-Keepalive", fmt.Sprintf("%d", cstpKeepalive)) HttpSetHeader(w, "X-CSTP-Keepalive", fmt.Sprintf("%d", cstpKeepalive))
// w.Header().Set("X-CSTP-Banner", banner.Banner) // HttpSetHeader(w, "X-CSTP-Banner", banner.Banner)
w.Header().Set("X-CSTP-MSIE-Proxy-Lockdown", "true") HttpSetHeader(w, "X-CSTP-MSIE-Proxy-Lockdown", "true")
w.Header().Set("X-CSTP-Smartcard-Removal-Disconnect", "true") HttpSetHeader(w, "X-CSTP-Smartcard-Removal-Disconnect", "true")
w.Header().Set("X-CSTP-MTU", fmt.Sprintf("%d", cSess.Mtu)) // 1399 HttpSetHeader(w, "X-CSTP-MTU", fmt.Sprintf("%d", cSess.Mtu)) // 1399
w.Header().Set("X-DTLS-MTU", fmt.Sprintf("%d", cSess.Mtu)) HttpSetHeader(w, "X-DTLS-MTU", fmt.Sprintf("%d", cSess.Mtu))
w.Header().Set("X-DTLS-Session-ID", sess.DtlsSid) HttpSetHeader(w, "X-DTLS-Session-ID", sess.DtlsSid)
w.Header().Set("X-DTLS-Port", dtlsPort) HttpSetHeader(w, "X-DTLS-Port", dtlsPort)
w.Header().Set("X-DTLS-DPD", fmt.Sprintf("%d", cstpDpd)) HttpSetHeader(w, "X-DTLS-DPD", fmt.Sprintf("%d", cstpDpd))
w.Header().Set("X-DTLS-Keepalive", fmt.Sprintf("%d", cstpKeepalive)) HttpSetHeader(w, "X-DTLS-Keepalive", fmt.Sprintf("%d", cstpKeepalive))
w.Header().Set("X-DTLS-Rekey-Time", "5400") HttpSetHeader(w, "X-DTLS-Rekey-Time", "5400")
w.Header().Set("X-DTLS12-CipherSuite", "ECDHE-ECDSA-AES128-GCM-SHA256") HttpSetHeader(w, "X-DTLS12-CipherSuite", "ECDHE-ECDSA-AES128-GCM-SHA256")
w.Header().Set("X-CSTP-License", "accept") HttpSetHeader(w, "X-CSTP-License", "accept")
w.Header().Set("X-CSTP-Routing-Filtering-Ignore", "false") HttpSetHeader(w, "X-CSTP-Routing-Filtering-Ignore", "false")
w.Header().Set("X-CSTP-Quarantine", "false") HttpSetHeader(w, "X-CSTP-Quarantine", "false")
w.Header().Set("X-CSTP-Disable-Always-On-VPN", "false") HttpSetHeader(w, "X-CSTP-Disable-Always-On-VPN", "false")
w.Header().Set("X-CSTP-Client-Bypass-Protocol", "false") HttpSetHeader(w, "X-CSTP-Client-Bypass-Protocol", "false")
w.Header().Set("X-CSTP-TCP-Keepalive", "false") HttpSetHeader(w, "X-CSTP-TCP-Keepalive", "false")
// w.Header().Set("X-CSTP-Post-Auth-XML", ``) // HttpSetHeader(w, "X-CSTP-Post-Auth-XML", ``)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
hClone := w.Header().Clone() hClone := w.Header().Clone()

View File

@ -2,18 +2,15 @@ package handler
import ( import (
"crypto/tls" "crypto/tls"
"errors"
"fmt" "fmt"
"log" "log"
"net" "net"
"net/http" "net/http"
"os"
"time" "time"
"github.com/bjdgyc/anylink/base" "github.com/bjdgyc/anylink/base"
"github.com/bjdgyc/anylink/pkg/proxyproto" "github.com/bjdgyc/anylink/pkg/proxyproto"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/pion/dtls/v2/pkg/crypto/selfsign"
) )
func startTls() { func startTls() {
@ -29,15 +26,16 @@ func startTls() {
) )
// 判断证书文件 // 判断证书文件
_, err = os.Stat(certFile) //_, err = os.Stat(certFile)
if errors.Is(err, os.ErrNotExist) { //if errors.Is(err, os.ErrNotExist) {
// 自动生成证书 // // 自动生成证书
certs[0], err = selfsign.GenerateSelfSignedWithDNS("vpn.anylink") // certs[0], err = selfsign.GenerateSelfSignedWithDNS("vpn.anylink")
} else { //} else {
// 使用自定义证书 // // 使用自定义证书
certs[0], err = tls.LoadX509KeyPair(certFile, keyFile) // certs[0], err = tls.LoadX509KeyPair(certFile, keyFile)
} //}
certs[0], err = tls.LoadX509KeyPair(certFile, keyFile)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -79,9 +77,9 @@ func initRoute() http.Handler {
r.HandleFunc("/", LinkAuth).Methods(http.MethodPost) r.HandleFunc("/", LinkAuth).Methods(http.MethodPost)
r.HandleFunc("/CSCOSSLC/tunnel", LinkTunnel).Methods(http.MethodConnect) r.HandleFunc("/CSCOSSLC/tunnel", LinkTunnel).Methods(http.MethodConnect)
r.HandleFunc("/otp_qr", LinkOtpQr).Methods(http.MethodGet) r.HandleFunc("/otp_qr", LinkOtpQr).Methods(http.MethodGet)
r.HandleFunc("/profile.xml", func(w http.ResponseWriter, r *http.Request) { // r.HandleFunc("/profile.xml", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(auth_profile)) // w.Write([]byte(auth_profile))
}).Methods(http.MethodGet) // }).Methods(http.MethodGet)
r.PathPrefix("/files/").Handler( r.PathPrefix("/files/").Handler(
http.StripPrefix("/files/", http.StripPrefix("/files/",
http.FileServer(http.Dir(base.Cfg.FilesPath)), http.FileServer(http.Dir(base.Cfg.FilesPath)),

View File

@ -9,7 +9,7 @@ User=root
WorkingDirectory=/usr/local/anylink-deploy WorkingDirectory=/usr/local/anylink-deploy
Restart=on-failure Restart=on-failure
RestartSec=5s RestartSec=5s
ExecStart=/usr/local/anylink-deploy/anylink --conf=./conf/server.toml ExecStart=/usr/local/anylink-deploy/anylink --conf=/usr/local/anylink-deploy/conf/server.toml
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target