https.go 4.8 KB

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