mirror of https://github.com/bjdgyc/anylink.git
commit
f267891f19
10
README.md
10
README.md
|
@ -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. 构建镜像
|
||||||
|
|
|
@ -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 | |
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
)
|
)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>
|
|
@ -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"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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-----
|
|
@ -0,0 +1,61 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
-----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-----
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue