http.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. package proxy
  2. import (
  3. "bufio"
  4. "crypto/tls"
  5. "github.com/cnlh/nps/bridge"
  6. "github.com/cnlh/nps/lib/common"
  7. "github.com/cnlh/nps/lib/conn"
  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. "net/http"
  12. "net/http/httputil"
  13. "os"
  14. "path/filepath"
  15. "strconv"
  16. "sync"
  17. )
  18. type httpServer struct {
  19. BaseServer
  20. httpPort int //http端口
  21. httpsPort int //https监听端口
  22. pemPath string
  23. keyPath string
  24. stop chan bool
  25. }
  26. func NewHttp(bridge *bridge.Bridge, c *file.Tunnel) *httpServer {
  27. httpPort, _ := beego.AppConfig.Int("httpProxyPort")
  28. httpsPort, _ := beego.AppConfig.Int("httpsProxyPort")
  29. pemPath := beego.AppConfig.String("pemPath")
  30. keyPath := beego.AppConfig.String("keyPath")
  31. return &httpServer{
  32. BaseServer: BaseServer{
  33. task: c,
  34. bridge: bridge,
  35. Mutex: sync.Mutex{},
  36. },
  37. httpPort: httpPort,
  38. httpsPort: httpsPort,
  39. pemPath: pemPath,
  40. keyPath: keyPath,
  41. stop: make(chan bool),
  42. }
  43. }
  44. func (s *httpServer) Start() error {
  45. var err error
  46. var http, https *http.Server
  47. if s.errorContent, err = common.ReadAllFromFile(filepath.Join(common.GetRunPath(), "web", "static", "page", "error.html")); err != nil {
  48. s.errorContent = []byte("easyProxy 404")
  49. }
  50. if s.httpPort > 0 {
  51. http = s.NewServer(s.httpPort)
  52. go func() {
  53. logs.Info("Start http listener, port is", s.httpPort)
  54. err := http.ListenAndServe()
  55. if err != nil {
  56. logs.Error(err)
  57. os.Exit(0)
  58. }
  59. }()
  60. }
  61. if s.httpsPort > 0 {
  62. if !common.FileExists(s.pemPath) {
  63. logs.Error("ssl certFile %s is not exist", s.pemPath)
  64. os.Exit(0)
  65. }
  66. if !common.FileExists(s.keyPath) {
  67. logs.Error("ssl keyFile %s exist", s.keyPath)
  68. os.Exit(0)
  69. }
  70. https = s.NewServer(s.httpsPort)
  71. go func() {
  72. logs.Info("Start https listener, port is", s.httpsPort)
  73. err := https.ListenAndServeTLS(s.pemPath, s.keyPath)
  74. if err != nil {
  75. logs.Error(err)
  76. os.Exit(0)
  77. }
  78. }()
  79. }
  80. select {
  81. case <-s.stop:
  82. if http != nil {
  83. http.Close()
  84. }
  85. if https != nil {
  86. https.Close()
  87. }
  88. }
  89. return nil
  90. }
  91. func (s *httpServer) Close() error {
  92. s.stop <- true
  93. return nil
  94. }
  95. func (s *httpServer) handleTunneling(w http.ResponseWriter, r *http.Request) {
  96. hijacker, ok := w.(http.Hijacker)
  97. if !ok {
  98. http.Error(w, "Hijacking not supported", http.StatusInternalServerError)
  99. return
  100. }
  101. c, _, err := hijacker.Hijack()
  102. if err != nil {
  103. http.Error(w, err.Error(), http.StatusServiceUnavailable)
  104. }
  105. s.process(conn.NewConn(c), r)
  106. }
  107. func (s *httpServer) process(c *conn.Conn, r *http.Request) {
  108. //多客户端域名代理
  109. var (
  110. isConn = true
  111. lk *conn.Link
  112. host *file.Host
  113. tunnel *conn.Conn
  114. lastHost *file.Host
  115. err error
  116. )
  117. if host, err = file.GetCsvDb().GetInfoByHost(r.Host, r); err != nil {
  118. logs.Notice("the url %s %s can't be parsed!", r.Host, r.RequestURI)
  119. goto end
  120. } else if !host.Client.GetConn() {
  121. logs.Notice("Connections exceed the current client %d limit", host.Client.Id)
  122. c.Close()
  123. return
  124. } else {
  125. logs.Trace("New http(s) connection,clientId %d,host %s,url %s,remote address %s", host.Client.Id, r.Host, r.URL, r.RemoteAddr)
  126. lastHost = host
  127. }
  128. for {
  129. start:
  130. if isConn {
  131. //流量限制
  132. if host.Client.Flow.FlowLimit > 0 && (host.Client.Flow.FlowLimit<<20) < (host.Client.Flow.ExportFlow+host.Client.Flow.InletFlow) {
  133. break
  134. }
  135. host.Client.Cnf.CompressDecode, host.Client.Cnf.CompressEncode = common.GetCompressType(host.Client.Cnf.Compress)
  136. //权限控制
  137. if err = s.auth(r, c, host.Client.Cnf.U, host.Client.Cnf.P); err != nil {
  138. break
  139. }
  140. lk = conn.NewLink(host.Client.GetId(), common.CONN_TCP, host.GetRandomTarget(), host.Client.Cnf.CompressEncode, host.Client.Cnf.CompressDecode, host.Client.Cnf.Crypt, c, host.Flow, nil, host.Client.Rate, nil)
  141. if tunnel, err = s.bridge.SendLinkInfo(host.Client.Id, lk, c.Conn.RemoteAddr().String()); err != nil {
  142. logs.Notice(err)
  143. break
  144. }
  145. lk.Run(true)
  146. isConn = false
  147. } else {
  148. r, err = http.ReadRequest(bufio.NewReader(c))
  149. if err != nil {
  150. break
  151. }
  152. logs.Trace("New http(s) connection,clientId %d,host %s,url %s,remote address %s", host.Client.Id, r.Host, r.URL, r.RemoteAddr)
  153. if host, err = file.GetCsvDb().GetInfoByHost(r.Host, r); err != nil {
  154. logs.Notice("the url %s %s can't be parsed!", r.Host, r.RequestURI)
  155. break
  156. } else if host != lastHost {
  157. lastHost = host
  158. isConn = true
  159. host.Client.AddConn()
  160. goto start
  161. }
  162. }
  163. //根据设定,修改header和host
  164. common.ChangeHostAndHeader(r, host.HostChange, host.HeaderChange, c.Conn.RemoteAddr().String())
  165. b, err := httputil.DumpRequest(r, true)
  166. if err != nil {
  167. break
  168. }
  169. host.Flow.Add(len(b), 0)
  170. if _, err := tunnel.SendMsg(b, lk); err != nil {
  171. c.Close()
  172. break
  173. }
  174. <-lk.StatusCh
  175. }
  176. end:
  177. if isConn {
  178. s.writeConnFail(c.Conn)
  179. } else {
  180. tunnel.SendMsg([]byte(common.IO_EOF), lk)
  181. }
  182. c.Close()
  183. if host != nil {
  184. host.Client.AddConn()
  185. }
  186. }
  187. func (s *httpServer) NewServer(port int) *http.Server {
  188. return &http.Server{
  189. Addr: ":" + strconv.Itoa(port),
  190. Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  191. s.handleTunneling(w, r)
  192. }),
  193. // Disable HTTP/2.
  194. TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)),
  195. }
  196. }