http.go 5.3 KB

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