http_proxy.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // Copyright 2017 frp team
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package plugin
  15. import (
  16. "encoding/base64"
  17. "fmt"
  18. "io"
  19. "net"
  20. "net/http"
  21. "strings"
  22. "sync"
  23. "github.com/fatedier/frp/models/proto/tcp"
  24. "github.com/fatedier/frp/utils/errors"
  25. frpNet "github.com/fatedier/frp/utils/net"
  26. )
  27. const PluginHttpProxy = "http_proxy"
  28. func init() {
  29. Register(PluginHttpProxy, NewHttpProxyPlugin)
  30. }
  31. type Listener struct {
  32. conns chan net.Conn
  33. closed bool
  34. mu sync.Mutex
  35. }
  36. func NewProxyListener() *Listener {
  37. return &Listener{
  38. conns: make(chan net.Conn, 64),
  39. }
  40. }
  41. func (l *Listener) Accept() (net.Conn, error) {
  42. conn, ok := <-l.conns
  43. if !ok {
  44. return nil, fmt.Errorf("listener closed")
  45. }
  46. return conn, nil
  47. }
  48. func (l *Listener) PutConn(conn net.Conn) error {
  49. err := errors.PanicToError(func() {
  50. l.conns <- conn
  51. })
  52. return err
  53. }
  54. func (l *Listener) Close() error {
  55. l.mu.Lock()
  56. defer l.mu.Unlock()
  57. if !l.closed {
  58. close(l.conns)
  59. }
  60. return nil
  61. }
  62. func (l *Listener) Addr() net.Addr {
  63. return (*net.TCPAddr)(nil)
  64. }
  65. type HttpProxy struct {
  66. l *Listener
  67. s *http.Server
  68. AuthUser string
  69. AuthPasswd string
  70. }
  71. func NewHttpProxyPlugin(params map[string]string) (Plugin, error) {
  72. user := params["plugin_http_user"]
  73. passwd := params["plugin_http_passwd"]
  74. listener := NewProxyListener()
  75. hp := &HttpProxy{
  76. l: listener,
  77. AuthUser: user,
  78. AuthPasswd: passwd,
  79. }
  80. hp.s = &http.Server{
  81. Handler: hp,
  82. }
  83. go hp.s.Serve(listener)
  84. return hp, nil
  85. }
  86. func (hp *HttpProxy) Name() string {
  87. return PluginHttpProxy
  88. }
  89. func (hp *HttpProxy) Handle(conn io.ReadWriteCloser) {
  90. var wrapConn net.Conn
  91. if realConn, ok := conn.(net.Conn); ok {
  92. wrapConn = realConn
  93. } else {
  94. wrapConn = frpNet.WrapReadWriteCloserToConn(conn)
  95. }
  96. hp.l.PutConn(wrapConn)
  97. return
  98. }
  99. func (hp *HttpProxy) Close() error {
  100. hp.s.Close()
  101. hp.l.Close()
  102. return nil
  103. }
  104. func (hp *HttpProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
  105. if ok := hp.Auth(rw, req); !ok {
  106. rw.Header().Set("Proxy-Authenticate", "Basic")
  107. rw.WriteHeader(http.StatusProxyAuthRequired)
  108. return
  109. }
  110. if req.Method == "CONNECT" {
  111. hp.ConnectHandler(rw, req)
  112. } else {
  113. hp.HttpHandler(rw, req)
  114. }
  115. }
  116. func (hp *HttpProxy) HttpHandler(rw http.ResponseWriter, req *http.Request) {
  117. removeProxyHeaders(req)
  118. resp, err := http.DefaultTransport.RoundTrip(req)
  119. if err != nil {
  120. http.Error(rw, err.Error(), http.StatusInternalServerError)
  121. return
  122. }
  123. defer resp.Body.Close()
  124. copyHeaders(rw.Header(), resp.Header)
  125. rw.WriteHeader(resp.StatusCode)
  126. _, err = io.Copy(rw, resp.Body)
  127. if err != nil && err != io.EOF {
  128. return
  129. }
  130. }
  131. func (hp *HttpProxy) ConnectHandler(rw http.ResponseWriter, req *http.Request) {
  132. hj, ok := rw.(http.Hijacker)
  133. if !ok {
  134. rw.WriteHeader(http.StatusInternalServerError)
  135. return
  136. }
  137. client, _, err := hj.Hijack()
  138. if err != nil {
  139. rw.WriteHeader(http.StatusInternalServerError)
  140. return
  141. }
  142. remote, err := net.Dial("tcp", req.URL.Host)
  143. if err != nil {
  144. http.Error(rw, "Failed", http.StatusBadRequest)
  145. client.Close()
  146. return
  147. }
  148. client.Write([]byte("HTTP/1.0 200 OK\r\n\r\n"))
  149. go tcp.Join(remote, client)
  150. }
  151. func (hp *HttpProxy) Auth(rw http.ResponseWriter, req *http.Request) bool {
  152. if hp.AuthUser == "" && hp.AuthPasswd == "" {
  153. return true
  154. }
  155. s := strings.SplitN(req.Header.Get("Proxy-Authorization"), " ", 2)
  156. if len(s) != 2 {
  157. return false
  158. }
  159. b, err := base64.StdEncoding.DecodeString(s[1])
  160. if err != nil {
  161. return false
  162. }
  163. pair := strings.SplitN(string(b), ":", 2)
  164. if len(pair) != 2 {
  165. return false
  166. }
  167. if pair[0] != hp.AuthUser || pair[1] != hp.AuthPasswd {
  168. return false
  169. }
  170. return true
  171. }
  172. func copyHeaders(dst, src http.Header) {
  173. for key, values := range src {
  174. for _, value := range values {
  175. dst.Add(key, value)
  176. }
  177. }
  178. }
  179. func removeProxyHeaders(req *http.Request) {
  180. req.RequestURI = ""
  181. req.Header.Del("Proxy-Connection")
  182. req.Header.Del("Connection")
  183. req.Header.Del("Proxy-Authenticate")
  184. req.Header.Del("Proxy-Authorization")
  185. req.Header.Del("TE")
  186. req.Header.Del("Trailers")
  187. req.Header.Del("Transfer-Encoding")
  188. req.Header.Del("Upgrade")
  189. }