link_tunnel.go 6.6 KB

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