http.go 4.6 KB

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