link_tunnel.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. package handler
  2. import (
  3. "bytes"
  4. "fmt"
  5. "log"
  6. "net"
  7. "net/http"
  8. "net/http/httputil"
  9. "os"
  10. "strings"
  11. "text/template"
  12. "github.com/bjdgyc/anylink/base"
  13. "github.com/bjdgyc/anylink/dbdata"
  14. "github.com/bjdgyc/anylink/sessdata"
  15. )
  16. var (
  17. hn string
  18. )
  19. func init() {
  20. // 获取主机名称
  21. hn, _ = os.Hostname()
  22. }
  23. func HttpSetHeader(w http.ResponseWriter, key string, value string) {
  24. w.Header()[key] = []string{value}
  25. }
  26. func HttpAddHeader(w http.ResponseWriter, key string, value string) {
  27. w.Header()[key] = append(w.Header()[key], value)
  28. }
  29. func LinkTunnel(w http.ResponseWriter, r *http.Request) {
  30. // TODO 调试信息输出
  31. if base.GetLogLevel() == base.LogLevelTrace {
  32. hd, _ := httputil.DumpRequest(r, true)
  33. base.Trace("LinkTunnel: ", string(hd))
  34. }
  35. // 判断session-token的值
  36. cookie, err := r.Cookie("webvpn")
  37. if err != nil || cookie.Value == "" {
  38. w.WriteHeader(http.StatusBadRequest)
  39. return
  40. }
  41. sess := sessdata.SToken2Sess(cookie.Value)
  42. if sess == nil {
  43. w.WriteHeader(http.StatusBadRequest)
  44. return
  45. }
  46. // 开启link
  47. cSess := sess.NewConn()
  48. if cSess == nil {
  49. log.Println(err)
  50. w.WriteHeader(http.StatusBadRequest)
  51. return
  52. }
  53. // 客户端信息
  54. cstpMtu := r.Header.Get("X-CSTP-MTU")
  55. cstpBaseMtu := r.Header.Get("X-CSTP-Base-MTU")
  56. masterSecret := r.Header.Get("X-DTLS-Master-Secret")
  57. localIp := r.Header.Get("X-Cstp-Local-Address-Ip4")
  58. mobile := r.Header.Get("X-Cstp-License")
  59. cSess.SetMtu(cstpMtu)
  60. cSess.MasterSecret = masterSecret
  61. cSess.RemoteAddr = r.RemoteAddr
  62. cSess.UserAgent = strings.ToLower(r.UserAgent())
  63. cSess.LocalIp = net.ParseIP(localIp)
  64. cstpKeepalive := base.Cfg.CstpKeepalive
  65. cstpDpd := base.Cfg.CstpDpd
  66. cSess.Client = "pc"
  67. if mobile == "mobile" {
  68. // 手机客户端
  69. cstpKeepalive = base.Cfg.MobileKeepalive
  70. cstpDpd = base.Cfg.MobileDpd
  71. cSess.Client = "mobile"
  72. }
  73. cSess.CstpDpd = cstpDpd
  74. dtlsPort := "4433"
  75. if strings.Contains(base.Cfg.ServerDTLSAddr, ":") {
  76. ss := strings.Split(base.Cfg.ServerDTLSAddr, ":")
  77. dtlsPort = ss[1]
  78. }
  79. base.Debug(cSess.IpAddr, cSess.MacHw, sess.Username, mobile)
  80. // 压缩
  81. if cmpName, ok := cSess.SetPickCmp("cstp", r.Header.Get("X-Cstp-Accept-Encoding")); ok {
  82. HttpSetHeader(w, "X-CSTP-Content-Encoding", cmpName)
  83. }
  84. if cmpName, ok := cSess.SetPickCmp("dtls", r.Header.Get("X-Dtls-Accept-Encoding")); ok {
  85. HttpSetHeader(w, "X-DTLS-Content-Encoding", cmpName)
  86. }
  87. // 返回客户端数据
  88. HttpSetHeader(w, "Server", fmt.Sprintf("%s %s", base.APP_NAME, base.APP_VER))
  89. HttpSetHeader(w, "X-CSTP-Version", "1")
  90. HttpSetHeader(w, "X-CSTP-Server-Name", fmt.Sprintf("%s %s", base.APP_NAME, base.APP_VER))
  91. HttpSetHeader(w, "X-CSTP-Protocol", "Copyright (c) 2004 Cisco Systems, Inc.")
  92. HttpSetHeader(w, "X-CSTP-Address", cSess.IpAddr.String()) // 分配的ip地址
  93. HttpSetHeader(w, "X-CSTP-Netmask", sessdata.IpPool.Ipv4Mask.String()) // 子网掩码
  94. HttpSetHeader(w, "X-CSTP-Hostname", hn) // 机器名称
  95. HttpSetHeader(w, "X-CSTP-Base-MTU", cstpBaseMtu)
  96. // 要发布的默认域
  97. if base.Cfg.DefaultDomain != "" {
  98. HttpSetHeader(w, "X-CSTP-Default-Domain", base.Cfg.DefaultDomain)
  99. }
  100. // 设置用户策略
  101. SetUserPolicy(cSess.Username, cSess.Group)
  102. // 允许本地LAN访问vpn网络,必须放在路由的第一个
  103. if cSess.Group.AllowLan {
  104. HttpSetHeader(w, "X-CSTP-Split-Exclude", "0.0.0.0/255.255.255.255")
  105. }
  106. // dns地址
  107. for _, v := range cSess.Group.ClientDns {
  108. HttpAddHeader(w, "X-CSTP-DNS", v.Val)
  109. }
  110. // 允许的路由
  111. for _, v := range cSess.Group.RouteInclude {
  112. if v.Val == dbdata.All {
  113. continue
  114. }
  115. HttpAddHeader(w, "X-CSTP-Split-Include", v.IpMask)
  116. }
  117. // 不允许的路由
  118. for _, v := range cSess.Group.RouteExclude {
  119. HttpAddHeader(w, "X-CSTP-Split-Exclude", v.IpMask)
  120. }
  121. HttpSetHeader(w, "X-CSTP-Lease-Duration", "1209600") // ip地址租期
  122. HttpSetHeader(w, "X-CSTP-Session-Timeout", "none")
  123. HttpSetHeader(w, "X-CSTP-Session-Timeout-Alert-Interval", "60")
  124. HttpSetHeader(w, "X-CSTP-Session-Timeout-Remaining", "none")
  125. HttpSetHeader(w, "X-CSTP-Idle-Timeout", "18000")
  126. HttpSetHeader(w, "X-CSTP-Disconnected-Timeout", "18000")
  127. HttpSetHeader(w, "X-CSTP-Keep", "true")
  128. HttpSetHeader(w, "X-CSTP-Tunnel-All-DNS", "false")
  129. HttpSetHeader(w, "X-CSTP-Rekey-Time", "43200") // 172800
  130. HttpSetHeader(w, "X-CSTP-Rekey-Method", "new-tunnel")
  131. HttpSetHeader(w, "X-DTLS-Rekey-Time", "43200")
  132. HttpSetHeader(w, "X-DTLS-Rekey-Method", "new-tunnel")
  133. HttpSetHeader(w, "X-CSTP-DPD", fmt.Sprintf("%d", cstpDpd))
  134. HttpSetHeader(w, "X-CSTP-Keepalive", fmt.Sprintf("%d", cstpKeepalive))
  135. // HttpSetHeader(w, "X-CSTP-Banner", banner.Banner)
  136. HttpSetHeader(w, "X-CSTP-MSIE-Proxy-Lockdown", "true")
  137. HttpSetHeader(w, "X-CSTP-Smartcard-Removal-Disconnect", "true")
  138. HttpSetHeader(w, "X-CSTP-MTU", fmt.Sprintf("%d", cSess.Mtu)) // 1399
  139. HttpSetHeader(w, "X-DTLS-MTU", fmt.Sprintf("%d", cSess.Mtu))
  140. HttpSetHeader(w, "X-DTLS-Session-ID", sess.DtlsSid)
  141. HttpSetHeader(w, "X-DTLS-Port", dtlsPort)
  142. HttpSetHeader(w, "X-DTLS-DPD", fmt.Sprintf("%d", cstpDpd))
  143. HttpSetHeader(w, "X-DTLS-Keepalive", fmt.Sprintf("%d", cstpKeepalive))
  144. HttpSetHeader(w, "X-DTLS12-CipherSuite", "ECDHE-ECDSA-AES128-GCM-SHA256")
  145. HttpSetHeader(w, "X-CSTP-License", "accept")
  146. HttpSetHeader(w, "X-CSTP-Routing-Filtering-Ignore", "false")
  147. HttpSetHeader(w, "X-CSTP-Quarantine", "false")
  148. HttpSetHeader(w, "X-CSTP-Disable-Always-On-VPN", "false")
  149. HttpSetHeader(w, "X-CSTP-Client-Bypass-Protocol", "false")
  150. HttpSetHeader(w, "X-CSTP-TCP-Keepalive", "false")
  151. // 设置域名拆分隧道(移动端不支持)
  152. if mobile != "mobile" {
  153. SetPostAuthXml(cSess.Group, w)
  154. }
  155. w.WriteHeader(http.StatusOK)
  156. hClone := w.Header().Clone()
  157. headers := make([]byte, 0)
  158. buf := bytes.NewBuffer(headers)
  159. _ = hClone.Write(buf)
  160. base.Debug(buf.String())
  161. hj := w.(http.Hijacker)
  162. conn, bufRW, err := hj.Hijack()
  163. if err != nil {
  164. base.Error(err)
  165. w.WriteHeader(http.StatusInternalServerError)
  166. return
  167. }
  168. // 开始数据处理
  169. switch base.Cfg.LinkMode {
  170. case base.LinkModeTUN:
  171. err = LinkTun(cSess)
  172. case base.LinkModeTAP:
  173. err = LinkTap(cSess)
  174. case base.LinkModeMacvtap:
  175. err = LinkMacvtap(cSess)
  176. }
  177. if err != nil {
  178. conn.Close()
  179. base.Error(err)
  180. return
  181. }
  182. dbdata.UserActLogIns.Add(dbdata.UserActLog{
  183. Username: sess.Username,
  184. GroupName: sess.Group,
  185. IpAddr: cSess.IpAddr.String(),
  186. RemoteAddr: cSess.RemoteAddr,
  187. DeviceType: sess.DeviceType,
  188. PlatformVersion: sess.PlatformVersion,
  189. Status: dbdata.UserConnected,
  190. }, cSess.UserAgent)
  191. go LinkCstp(conn, bufRW, cSess)
  192. }
  193. // 设置域名拆分隧道
  194. func SetPostAuthXml(g *dbdata.Group, w http.ResponseWriter) error {
  195. if g.DsExcludeDomains == "" && g.DsIncludeDomains == "" {
  196. return nil
  197. }
  198. tmpl, err := template.New("post_auth_xml").Parse(ds_domains_xml)
  199. if err != nil {
  200. return err
  201. }
  202. var result bytes.Buffer
  203. err = tmpl.Execute(&result, g)
  204. if err != nil {
  205. return err
  206. }
  207. HttpSetHeader(w, "X-CSTP-Post-Auth-XML", result.String())
  208. return nil
  209. }
  210. // 设置用户策略, 覆盖Group的属性值
  211. func SetUserPolicy(username string, g *dbdata.Group) {
  212. userPolicy := dbdata.GetPolicy(username)
  213. if userPolicy.Id != 0 && userPolicy.Status == 1 {
  214. base.Debug(username + " use UserPolicy")
  215. g.AllowLan = userPolicy.AllowLan
  216. g.ClientDns = userPolicy.ClientDns
  217. g.RouteInclude = userPolicy.RouteInclude
  218. g.RouteExclude = userPolicy.RouteExclude
  219. g.DsExcludeDomains = userPolicy.DsExcludeDomains
  220. g.DsIncludeDomains = userPolicy.DsIncludeDomains
  221. }
  222. }