http.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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 //http端口
  24. httpsPort int //https监听端口
  25. pemPath string
  26. keyPath string
  27. stop chan bool
  28. httpslistener net.Listener
  29. }
  30. func NewHttp(bridge *bridge.Bridge, c *file.Tunnel) *httpServer {
  31. httpPort, _ := beego.AppConfig.Int("http_proxy_port")
  32. httpsPort, _ := beego.AppConfig.Int("https_proxy_port")
  33. pemPath := beego.AppConfig.String("pem_path")
  34. keyPath := beego.AppConfig.String("key_path")
  35. return &httpServer{
  36. BaseServer: BaseServer{
  37. task: c,
  38. bridge: bridge,
  39. Mutex: sync.Mutex{},
  40. },
  41. httpPort: httpPort,
  42. httpsPort: httpsPort,
  43. pemPath: pemPath,
  44. keyPath: keyPath,
  45. stop: make(chan bool),
  46. }
  47. }
  48. func (s *httpServer) Start() error {
  49. var err error
  50. var httpSrv, httpsSrv *http.Server
  51. if s.errorContent, err = common.ReadAllFromFile(filepath.Join(common.GetRunPath(), "web", "static", "page", "error.html")); err != nil {
  52. s.errorContent = []byte("easyProxy 404")
  53. }
  54. if s.httpPort > 0 {
  55. httpSrv = s.NewServer(s.httpPort, "http")
  56. go func() {
  57. l, err := connection.GetHttpListener()
  58. if err != nil {
  59. logs.Error(err)
  60. os.Exit(0)
  61. }
  62. err = httpSrv.Serve(l)
  63. if err != nil {
  64. logs.Error(err)
  65. os.Exit(0)
  66. }
  67. }()
  68. }
  69. if s.httpsPort > 0 {
  70. if !common.FileExists(s.pemPath) {
  71. os.Exit(0)
  72. }
  73. if !common.FileExists(s.keyPath) {
  74. logs.Error("ssl keyFile %s exist", s.keyPath)
  75. os.Exit(0)
  76. }
  77. httpsSrv = s.NewServer(s.httpsPort, "https")
  78. go func() {
  79. logs.Info("Start https listener, port is", s.httpsPort)
  80. l, err := connection.GetHttpsListener()
  81. if err != nil {
  82. logs.Error(err)
  83. os.Exit(0)
  84. }
  85. err = httpsSrv.ServeTLS(l, s.pemPath, s.keyPath)
  86. if err != nil {
  87. logs.Error(err)
  88. os.Exit(0)
  89. }
  90. }()
  91. }
  92. select {
  93. case <-s.stop:
  94. if httpSrv != nil {
  95. httpsSrv.Close()
  96. }
  97. if httpsSrv != nil {
  98. httpsSrv.Close()
  99. }
  100. }
  101. return nil
  102. }
  103. func (s *httpServer) Close() error {
  104. s.stop <- true
  105. return nil
  106. }
  107. func (s *httpServer) handleTunneling(w http.ResponseWriter, r *http.Request) {
  108. hijacker, ok := w.(http.Hijacker)
  109. if !ok {
  110. http.Error(w, "Hijacking not supported", http.StatusInternalServerError)
  111. return
  112. }
  113. c, _, err := hijacker.Hijack()
  114. if err != nil {
  115. http.Error(w, err.Error(), http.StatusServiceUnavailable)
  116. }
  117. s.process(conn.NewConn(c), r)
  118. }
  119. func (s *httpServer) process(c *conn.Conn, r *http.Request) {
  120. //多客户端域名代理
  121. var (
  122. isConn = true
  123. host *file.Host
  124. target net.Conn
  125. lastHost *file.Host
  126. err error
  127. connClient io.ReadWriteCloser
  128. scheme = r.URL.Scheme
  129. lk *conn.Link
  130. targetAddr string
  131. wg sync.WaitGroup
  132. )
  133. if host, err = file.GetCsvDb().GetInfoByHost(r.Host, r); err != nil {
  134. logs.Notice("the url %s %s %s can't be parsed!", r.URL.Scheme, r.Host, r.RequestURI)
  135. goto end
  136. } else if !host.Client.GetConn() { //conn num limit
  137. logs.Notice("connections exceed the current client %d limit %d ,now connection num %d", host.Client.Id, host.Client.MaxConn, host.Client.NowConn)
  138. c.Close()
  139. return
  140. } else {
  141. 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)
  142. lastHost = host
  143. }
  144. for {
  145. start:
  146. if isConn {
  147. //流量限制
  148. if host.Client.Flow.FlowLimit > 0 && (host.Client.Flow.FlowLimit<<20) < (host.Client.Flow.ExportFlow+host.Client.Flow.InletFlow) {
  149. logs.Warn("Traffic exceeded client id %s", host.Client.Id)
  150. break
  151. }
  152. //权限控制
  153. if err = s.auth(r, c, host.Client.Cnf.U, host.Client.Cnf.P); err != nil {
  154. logs.Warn("auth error", err, r.RemoteAddr)
  155. break
  156. }
  157. if targetAddr, err = host.GetRandomTarget(); err != nil {
  158. logs.Warn(err.Error())
  159. break
  160. }
  161. lk = conn.NewLink(common.CONN_TCP, targetAddr, host.Client.Cnf.Crypt, host.Client.Cnf.Compress, r.RemoteAddr)
  162. if target, err = s.bridge.SendLinkInfo(host.Client.Id, lk, c.Conn.RemoteAddr().String(), nil); err != nil {
  163. logs.Notice("connect to target %s error %s", lk.Host, err)
  164. break
  165. }
  166. connClient = conn.GetConn(target, lk.Crypt, lk.Compress, host.Client.Rate, true)
  167. isConn = false
  168. go func() {
  169. wg.Add(1)
  170. w, _ := common.CopyBuffer(c, connClient)
  171. host.Flow.Add(0, w)
  172. c.Close()
  173. target.Close()
  174. wg.Done()
  175. }()
  176. } else {
  177. r, err = http.ReadRequest(bufio.NewReader(c))
  178. if err != nil {
  179. break
  180. }
  181. r.URL.Scheme = scheme
  182. //What happened ,Why one character less???
  183. if r.Method == "ET" {
  184. r.Method = "GET"
  185. }
  186. if r.Method == "OST" {
  187. r.Method = "POST"
  188. }
  189. 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)
  190. if hostTmp, err := file.GetCsvDb().GetInfoByHost(r.Host, r); err != nil {
  191. logs.Notice("the url %s %s %s can't be parsed!", r.URL.Scheme, r.Host, r.RequestURI)
  192. break
  193. } else if host != lastHost {
  194. host.Client.AddConn()
  195. if !hostTmp.Client.GetConn() {
  196. break
  197. }
  198. host = hostTmp
  199. lastHost = host
  200. isConn = true
  201. goto start
  202. }
  203. }
  204. //根据设定,修改header和host
  205. common.ChangeHostAndHeader(r, host.HostChange, host.HeaderChange, c.Conn.RemoteAddr().String())
  206. b, err := httputil.DumpRequest(r, true)
  207. if err != nil {
  208. break
  209. }
  210. host.Flow.Add(int64(len(b)), 0)
  211. 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)
  212. //write
  213. connClient.Write(b)
  214. }
  215. end:
  216. if isConn {
  217. s.writeConnFail(c.Conn)
  218. }
  219. c.Close()
  220. if target != nil {
  221. target.Close()
  222. }
  223. wg.Wait()
  224. if host != nil {
  225. host.Client.AddConn()
  226. }
  227. }
  228. func (s *httpServer) NewServer(port int, scheme string) *http.Server {
  229. return &http.Server{
  230. Addr: ":" + strconv.Itoa(port),
  231. Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  232. r.URL.Scheme = scheme
  233. s.handleTunneling(w, r)
  234. }),
  235. // Disable HTTP/2.
  236. TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)),
  237. }
  238. }