1
0

https.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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. conn.Accept(https.listener, func(c net.Conn) {
  33. serverName, rb := GetServerNameFromClientHello(c)
  34. var l *HttpsListener
  35. if v, ok := https.httpsListenerMap.Load(serverName); ok {
  36. l = v.(*HttpsListener)
  37. } else {
  38. r := buildHttpsRequest(serverName)
  39. if host, err := file.GetDb().GetInfoByHost(serverName, r); err != nil {
  40. c.Close()
  41. logs.Notice("the url %s can't be parsed!", serverName)
  42. return
  43. } else {
  44. if !common.FileExists(host.CertFilePath) || !common.FileExists(host.KeyFilePath) {
  45. c.Close()
  46. logs.Error("the key %s cert %s file is not exist", host.KeyFilePath, host.CertFilePath)
  47. return
  48. }
  49. l = NewHttpsListener(https.listener)
  50. https.NewHttps(l, host.CertFilePath, host.KeyFilePath)
  51. https.httpsListenerMap.Store(serverName, l)
  52. }
  53. }
  54. acceptConn := conn.NewConn(c)
  55. acceptConn.Rb = rb
  56. l.acceptConn <- acceptConn
  57. })
  58. }
  59. return nil
  60. }
  61. func (https *HttpsServer) Close() error {
  62. return https.listener.Close()
  63. }
  64. func (https *HttpsServer) NewHttps(l net.Listener, certFile string, keyFile string) {
  65. go func() {
  66. logs.Error(https.NewServer(0, "https").ServeTLS(l, certFile, keyFile))
  67. }()
  68. }
  69. func (https *HttpsServer) handleHttps(c net.Conn) {
  70. hostName, rb := GetServerNameFromClientHello(c)
  71. var targetAddr string
  72. r := buildHttpsRequest(hostName)
  73. var host *file.Host
  74. var err error
  75. if host, err = file.GetDb().GetInfoByHost(hostName, r); err != nil {
  76. c.Close()
  77. logs.Notice("the url %s can't be parsed!", hostName)
  78. return
  79. }
  80. if err := https.CheckFlowAndConnNum(host.Client); err != nil {
  81. logs.Warn("client id %d, host id %d, error %s, when https connection", host.Client.Id, host.Id, err.Error())
  82. c.Close()
  83. return
  84. }
  85. defer host.Client.AddConn()
  86. if err = https.auth(r, conn.NewConn(c), host.Client.Cnf.U, host.Client.Cnf.P); err != nil {
  87. logs.Warn("auth error", err, r.RemoteAddr)
  88. return
  89. }
  90. if targetAddr, err = host.Target.GetRandomTarget(); err != nil {
  91. logs.Warn(err.Error())
  92. }
  93. logs.Trace("new https connection,clientId %d,host %s,remote address %s", host.Client.Id, r.Host, c.RemoteAddr().String())
  94. https.DealClient(conn.NewConn(c), host.Client, targetAddr, rb, common.CONN_TCP, nil, host.Flow)
  95. }
  96. type HttpsListener struct {
  97. acceptConn chan *conn.Conn
  98. parentListener net.Listener
  99. }
  100. func NewHttpsListener(l net.Listener) *HttpsListener {
  101. return &HttpsListener{parentListener: l, acceptConn: make(chan *conn.Conn)}
  102. }
  103. func (httpsListener *HttpsListener) Accept() (net.Conn, error) {
  104. httpsConn := <-httpsListener.acceptConn
  105. if httpsConn == nil {
  106. return nil, errors.New("get connection error")
  107. }
  108. return httpsConn, nil
  109. }
  110. func (httpsListener *HttpsListener) Close() error {
  111. return nil
  112. }
  113. func (httpsListener *HttpsListener) Addr() net.Addr {
  114. return httpsListener.parentListener.Addr()
  115. }
  116. func GetServerNameFromClientHello(c net.Conn) (string, []byte) {
  117. buf := make([]byte, 4096)
  118. data := make([]byte, 4096)
  119. n, err := c.Read(buf)
  120. if err != nil {
  121. return "", nil
  122. }
  123. copy(data, buf[:n])
  124. clientHello := new(crypt.ClientHelloMsg)
  125. clientHello.Unmarshal(data[5:n])
  126. return clientHello.GetServerName(), buf[:n]
  127. }
  128. func buildHttpsRequest(hostName string) *http.Request {
  129. r := new(http.Request)
  130. r.RequestURI = "/"
  131. r.URL = new(url.URL)
  132. r.URL.Scheme = "https"
  133. r.Host = hostName
  134. return r
  135. }