http.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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/server/connection"
  10. "github.com/cnlh/nps/vender/github.com/astaxie/beego"
  11. "github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
  12. "io"
  13. "net"
  14. "net/http"
  15. "net/http/httputil"
  16. "os"
  17. "path/filepath"
  18. "strconv"
  19. "sync"
  20. )
  21. type httpServer struct {
  22. BaseServer
  23. httpPort int
  24. httpsPort int
  25. httpServer *http.Server
  26. httpsServer *http.Server
  27. httpsListener net.Listener
  28. }
  29. func NewHttp(bridge *bridge.Bridge, c *file.Tunnel) *httpServer {
  30. httpPort, _ := beego.AppConfig.Int("http_proxy_port")
  31. httpsPort, _ := beego.AppConfig.Int("https_proxy_port")
  32. return &httpServer{
  33. BaseServer: BaseServer{
  34. task: c,
  35. bridge: bridge,
  36. Mutex: sync.Mutex{},
  37. },
  38. httpPort: httpPort,
  39. httpsPort: httpsPort,
  40. }
  41. }
  42. func (s *httpServer) Start() error {
  43. var err error
  44. if s.errorContent, err = common.ReadAllFromFile(filepath.Join(common.GetRunPath(), "web", "static", "page", "error.html")); err != nil {
  45. s.errorContent = []byte("easyProxy 404")
  46. }
  47. if s.httpPort > 0 {
  48. s.httpServer = s.NewServer(s.httpPort, "http")
  49. go func() {
  50. l, err := connection.GetHttpListener()
  51. if err != nil {
  52. logs.Error(err)
  53. os.Exit(0)
  54. }
  55. err = s.httpServer.Serve(l)
  56. if err != nil {
  57. logs.Error(err)
  58. os.Exit(0)
  59. }
  60. }()
  61. }
  62. if s.httpsPort > 0 {
  63. s.httpsServer = s.NewServer(s.httpsPort, "https")
  64. go func() {
  65. s.httpsListener, err = connection.GetHttpsListener()
  66. if err != nil {
  67. logs.Error(err)
  68. os.Exit(0)
  69. }
  70. logs.Error(NewHttpsServer(s.httpsListener, s.bridge).Start())
  71. }()
  72. }
  73. return nil
  74. }
  75. func (s *httpServer) Close() error {
  76. if s.httpsListener != nil {
  77. s.httpsListener.Close()
  78. }
  79. if s.httpsServer != nil {
  80. s.httpsServer.Close()
  81. }
  82. if s.httpServer != nil {
  83. s.httpServer.Close()
  84. }
  85. return nil
  86. }
  87. func (s *httpServer) handleTunneling(w http.ResponseWriter, r *http.Request) {
  88. hijacker, ok := w.(http.Hijacker)
  89. if !ok {
  90. http.Error(w, "Hijacking not supported", http.StatusInternalServerError)
  91. return
  92. }
  93. c, _, err := hijacker.Hijack()
  94. if err != nil {
  95. http.Error(w, err.Error(), http.StatusServiceUnavailable)
  96. }
  97. s.process(conn.NewConn(c), r)
  98. }
  99. func (s *httpServer) process(c *conn.Conn, r *http.Request) {
  100. var (
  101. isConn = true
  102. host *file.Host
  103. target net.Conn
  104. lastHost *file.Host
  105. err error
  106. connClient io.ReadWriteCloser
  107. scheme = r.URL.Scheme
  108. lk *conn.Link
  109. targetAddr string
  110. wg sync.WaitGroup
  111. )
  112. if host, err = file.GetDb().GetInfoByHost(r.Host, r); err != nil {
  113. logs.Notice("the url %s %s %s can't be parsed!", r.URL.Scheme, r.Host, r.RequestURI)
  114. goto end
  115. }
  116. if err := s.CheckFlowAndConnNum(host.Client); err != nil {
  117. logs.Warn("client id %d, host id %d, error %s, when https connection", host.Client.Id, host.Id, err.Error())
  118. c.Close()
  119. return
  120. }
  121. defer host.Client.AddConn()
  122. logs.Trace("new %s connection,clientId %d,host %s,url %s,remote address %s", r.URL.Scheme, host.Client.Id, r.Host, r.URL, r.RemoteAddr)
  123. lastHost = host
  124. for {
  125. start:
  126. if isConn {
  127. if err = s.auth(r, c, host.Client.Cnf.U, host.Client.Cnf.P); err != nil {
  128. logs.Warn("auth error", err, r.RemoteAddr)
  129. break
  130. }
  131. if targetAddr, err = host.Target.GetRandomTarget(); err != nil {
  132. logs.Warn(err.Error())
  133. break
  134. }
  135. lk = conn.NewLink(common.CONN_TCP, targetAddr, host.Client.Cnf.Crypt, host.Client.Cnf.Compress, r.RemoteAddr)
  136. if target, err = s.bridge.SendLinkInfo(host.Client.Id, lk, c.Conn.RemoteAddr().String(), nil); err != nil {
  137. logs.Notice("connect to target %s error %s", lk.Host, err)
  138. break
  139. }
  140. connClient = conn.GetConn(target, lk.Crypt, lk.Compress, host.Client.Rate, true)
  141. isConn = false
  142. go func() {
  143. wg.Add(1)
  144. w, _ := common.CopyBuffer(c, connClient)
  145. host.Flow.Add(0, w)
  146. c.Close()
  147. target.Close()
  148. wg.Done()
  149. }()
  150. } else {
  151. r, err = http.ReadRequest(bufio.NewReader(c))
  152. if err != nil {
  153. break
  154. }
  155. r.URL.Scheme = scheme
  156. //What happened ,Why one character less???
  157. if r.Method == "ET" {
  158. r.Method = "GET"
  159. }
  160. if r.Method == "OST" {
  161. r.Method = "POST"
  162. }
  163. logs.Trace("new %s connection,clientId %d,host %s,url %s,remote address %s", r.URL.Scheme, host.Client.Id, r.Host, r.URL, r.RemoteAddr)
  164. if hostTmp, err := file.GetDb().GetInfoByHost(r.Host, r); err != nil {
  165. logs.Notice("the url %s %s %s can't be parsed!", r.URL.Scheme, r.Host, r.RequestURI)
  166. break
  167. } else if host != lastHost {
  168. host = hostTmp
  169. lastHost = host
  170. isConn = true
  171. goto start
  172. }
  173. }
  174. //change the host and header and set proxy setting
  175. common.ChangeHostAndHeader(r, host.HostChange, host.HeaderChange, c.Conn.RemoteAddr().String())
  176. b, err := httputil.DumpRequest(r, false)
  177. if err != nil {
  178. break
  179. }
  180. logs.Trace("%s request, method %s, host %s, url %s, remote address %s, target %s", r.URL.Scheme, r.Method, r.Host, r.RequestURI, r.RemoteAddr, lk.Host)
  181. //write
  182. connClient.Write(b)
  183. if bodyLen, err := common.CopyBuffer(connClient, r.Body); err != nil {
  184. break
  185. } else {
  186. host.Flow.Add(int64(len(b))+bodyLen, 0)
  187. }
  188. }
  189. end:
  190. if isConn {
  191. s.writeConnFail(c.Conn)
  192. }
  193. c.Close()
  194. if target != nil {
  195. target.Close()
  196. }
  197. wg.Wait()
  198. }
  199. func (s *httpServer) NewServer(port int, scheme string) *http.Server {
  200. return &http.Server{
  201. Addr: ":" + strconv.Itoa(port),
  202. Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  203. r.URL.Scheme = scheme
  204. s.handleTunneling(w, r)
  205. }),
  206. // Disable HTTP/2.
  207. TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)),
  208. }
  209. }