http.go 4.1 KB

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