1
0

https.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package proxy
  2. import (
  3. "github.com/cnlh/nps/bridge"
  4. "github.com/cnlh/nps/lib/cache"
  5. "github.com/cnlh/nps/lib/common"
  6. "github.com/cnlh/nps/lib/conn"
  7. "github.com/cnlh/nps/lib/crypt"
  8. "github.com/cnlh/nps/lib/file"
  9. "github.com/cnlh/nps/vender/github.com/astaxie/beego"
  10. "github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
  11. "github.com/pkg/errors"
  12. "net"
  13. "net/http"
  14. "net/url"
  15. "sync"
  16. )
  17. type HttpsServer struct {
  18. httpServer
  19. listener net.Listener
  20. httpsListenerMap sync.Map
  21. }
  22. func NewHttpsServer(l net.Listener, bridge *bridge.Bridge, useCache bool, cacheLen int) *HttpsServer {
  23. https := &HttpsServer{listener: l}
  24. https.bridge = bridge
  25. https.useCache = useCache
  26. if useCache {
  27. https.cache = cache.New(cacheLen)
  28. }
  29. return https
  30. }
  31. func (https *HttpsServer) Start() error {
  32. if b, err := beego.AppConfig.Bool("https_just_proxy"); err == nil && b {
  33. conn.Accept(https.listener, func(c net.Conn) {
  34. https.handleHttps(c)
  35. })
  36. } else {
  37. //start the default listener
  38. certFile := beego.AppConfig.String("https_default_cert_file")
  39. keyFile := beego.AppConfig.String("https_default_key_file")
  40. if common.FileExists(certFile) && common.FileExists(keyFile) {
  41. l := NewHttpsListener(https.listener)
  42. https.NewHttps(l, certFile, keyFile)
  43. https.httpsListenerMap.Store("default", l)
  44. }
  45. conn.Accept(https.listener, func(c net.Conn) {
  46. serverName, rb := GetServerNameFromClientHello(c)
  47. //if the clientHello does not contains sni ,use the default ssl certificate
  48. if serverName == "" {
  49. serverName = "default"
  50. }
  51. var l *HttpsListener
  52. if v, ok := https.httpsListenerMap.Load(serverName); ok {
  53. l = v.(*HttpsListener)
  54. } else {
  55. r := buildHttpsRequest(serverName)
  56. if host, err := file.GetDb().GetInfoByHost(serverName, r); err != nil {
  57. c.Close()
  58. logs.Notice("the url %s can't be parsed!,remote addr %s", serverName, c.RemoteAddr().String())
  59. return
  60. } else {
  61. if !common.FileExists(host.CertFilePath) || !common.FileExists(host.KeyFilePath) {
  62. //if the host cert file or key file is not set ,use the default file
  63. if v, ok := https.httpsListenerMap.Load("default"); ok {
  64. l = v.(*HttpsListener)
  65. } else {
  66. c.Close()
  67. logs.Error("the key %s cert %s file is not exist", host.KeyFilePath, host.CertFilePath)
  68. return
  69. }
  70. } else {
  71. l = NewHttpsListener(https.listener)
  72. https.NewHttps(l, host.CertFilePath, host.KeyFilePath)
  73. https.httpsListenerMap.Store(serverName, l)
  74. }
  75. }
  76. }
  77. acceptConn := conn.NewConn(c)
  78. acceptConn.Rb = rb
  79. l.acceptConn <- acceptConn
  80. })
  81. }
  82. return nil
  83. }
  84. func (https *HttpsServer) Close() error {
  85. return https.listener.Close()
  86. }
  87. func (https *HttpsServer) NewHttps(l net.Listener, certFile string, keyFile string) {
  88. go func() {
  89. logs.Error(https.NewServer(0, "https").ServeTLS(l, certFile, keyFile))
  90. }()
  91. }
  92. func (https *HttpsServer) handleHttps(c net.Conn) {
  93. hostName, rb := GetServerNameFromClientHello(c)
  94. var targetAddr string
  95. r := buildHttpsRequest(hostName)
  96. var host *file.Host
  97. var err error
  98. if host, err = file.GetDb().GetInfoByHost(hostName, r); err != nil {
  99. c.Close()
  100. logs.Notice("the url %s can't be parsed!", hostName)
  101. return
  102. }
  103. if err := https.CheckFlowAndConnNum(host.Client); err != nil {
  104. logs.Warn("client id %d, host id %d, error %s, when https connection", host.Client.Id, host.Id, err.Error())
  105. c.Close()
  106. return
  107. }
  108. defer host.Client.AddConn()
  109. if err = https.auth(r, conn.NewConn(c), host.Client.Cnf.U, host.Client.Cnf.P); err != nil {
  110. logs.Warn("auth error", err, r.RemoteAddr)
  111. return
  112. }
  113. if targetAddr, err = host.Target.GetRandomTarget(); err != nil {
  114. logs.Warn(err.Error())
  115. }
  116. logs.Trace("new https connection,clientId %d,host %s,remote address %s", host.Client.Id, r.Host, c.RemoteAddr().String())
  117. https.DealClient(conn.NewConn(c), host.Client, targetAddr, rb, common.CONN_TCP, nil, host.Flow, host.Target.LocalProxy)
  118. }
  119. type HttpsListener struct {
  120. acceptConn chan *conn.Conn
  121. parentListener net.Listener
  122. }
  123. func NewHttpsListener(l net.Listener) *HttpsListener {
  124. return &HttpsListener{parentListener: l, acceptConn: make(chan *conn.Conn)}
  125. }
  126. func (httpsListener *HttpsListener) Accept() (net.Conn, error) {
  127. httpsConn := <-httpsListener.acceptConn
  128. if httpsConn == nil {
  129. return nil, errors.New("get connection error")
  130. }
  131. return httpsConn, nil
  132. }
  133. func (httpsListener *HttpsListener) Close() error {
  134. return nil
  135. }
  136. func (httpsListener *HttpsListener) Addr() net.Addr {
  137. return httpsListener.parentListener.Addr()
  138. }
  139. func GetServerNameFromClientHello(c net.Conn) (string, []byte) {
  140. buf := make([]byte, 4096)
  141. data := make([]byte, 4096)
  142. n, err := c.Read(buf)
  143. if err != nil {
  144. return "", nil
  145. }
  146. copy(data, buf[:n])
  147. clientHello := new(crypt.ClientHelloMsg)
  148. clientHello.Unmarshal(data[5:n])
  149. return clientHello.GetServerName(), buf[:n]
  150. }
  151. func buildHttpsRequest(hostName string) *http.Request {
  152. r := new(http.Request)
  153. r.RequestURI = "/"
  154. r.URL = new(url.URL)
  155. r.URL.Scheme = "https"
  156. r.Host = hostName
  157. return r
  158. }