1
0

http_proxy.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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/utils/errors"
  24. frpIo "github.com/fatedier/frp/utils/io"
  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. l.closed = true
  60. }
  61. return nil
  62. }
  63. func (l *Listener) Addr() net.Addr {
  64. return (*net.TCPAddr)(nil)
  65. }
  66. type HttpProxy struct {
  67. l *Listener
  68. s *http.Server
  69. AuthUser string
  70. AuthPasswd string
  71. }
  72. func NewHttpProxyPlugin(params map[string]string) (Plugin, error) {
  73. user := params["plugin_http_user"]
  74. passwd := params["plugin_http_passwd"]
  75. listener := NewProxyListener()
  76. hp := &HttpProxy{
  77. l: listener,
  78. AuthUser: user,
  79. AuthPasswd: passwd,
  80. }
  81. hp.s = &http.Server{
  82. Handler: hp,
  83. }
  84. go hp.s.Serve(listener)
  85. return hp, nil
  86. }
  87. func (hp *HttpProxy) Name() string {
  88. return PluginHttpProxy
  89. }
  90. func (hp *HttpProxy) Handle(conn io.ReadWriteCloser) {
  91. var wrapConn net.Conn
  92. if realConn, ok := conn.(net.Conn); ok {
  93. wrapConn = realConn
  94. } else {
  95. wrapConn = frpNet.WrapReadWriteCloserToConn(conn)
  96. }
  97. hp.l.PutConn(wrapConn)
  98. return
  99. }
  100. func (hp *HttpProxy) Close() error {
  101. hp.s.Close()
  102. hp.l.Close()
  103. return nil
  104. }
  105. func (hp *HttpProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
  106. if ok := hp.Auth(rw, req); !ok {
  107. rw.Header().Set("Proxy-Authenticate", "Basic")
  108. rw.WriteHeader(http.StatusProxyAuthRequired)
  109. return
  110. }
  111. if req.Method == "CONNECT" {
  112. hp.ConnectHandler(rw, req)
  113. } else {
  114. hp.HttpHandler(rw, req)
  115. }
  116. }
  117. func (hp *HttpProxy) HttpHandler(rw http.ResponseWriter, req *http.Request) {
  118. removeProxyHeaders(req)
  119. resp, err := http.DefaultTransport.RoundTrip(req)
  120. if err != nil {
  121. http.Error(rw, err.Error(), http.StatusInternalServerError)
  122. return
  123. }
  124. defer resp.Body.Close()
  125. copyHeaders(rw.Header(), resp.Header)
  126. rw.WriteHeader(resp.StatusCode)
  127. _, err = io.Copy(rw, resp.Body)
  128. if err != nil && err != io.EOF {
  129. return
  130. }
  131. }
  132. func (hp *HttpProxy) ConnectHandler(rw http.ResponseWriter, req *http.Request) {
  133. hj, ok := rw.(http.Hijacker)
  134. if !ok {
  135. rw.WriteHeader(http.StatusInternalServerError)
  136. return
  137. }
  138. client, _, err := hj.Hijack()
  139. if err != nil {
  140. rw.WriteHeader(http.StatusInternalServerError)
  141. return
  142. }
  143. remote, err := net.Dial("tcp", req.URL.Host)
  144. if err != nil {
  145. http.Error(rw, "Failed", http.StatusBadRequest)
  146. client.Close()
  147. return
  148. }
  149. client.Write([]byte("HTTP/1.0 200 OK\r\n\r\n"))
  150. go frpIo.Join(remote, client)
  151. }
  152. func (hp *HttpProxy) Auth(rw http.ResponseWriter, req *http.Request) bool {
  153. if hp.AuthUser == "" && hp.AuthPasswd == "" {
  154. return true
  155. }
  156. s := strings.SplitN(req.Header.Get("Proxy-Authorization"), " ", 2)
  157. if len(s) != 2 {
  158. return false
  159. }
  160. b, err := base64.StdEncoding.DecodeString(s[1])
  161. if err != nil {
  162. return false
  163. }
  164. pair := strings.SplitN(string(b), ":", 2)
  165. if len(pair) != 2 {
  166. return false
  167. }
  168. if pair[0] != hp.AuthUser || pair[1] != hp.AuthPasswd {
  169. return false
  170. }
  171. return true
  172. }
  173. func copyHeaders(dst, src http.Header) {
  174. for key, values := range src {
  175. for _, value := range values {
  176. dst.Add(key, value)
  177. }
  178. }
  179. }
  180. func removeProxyHeaders(req *http.Request) {
  181. req.RequestURI = ""
  182. req.Header.Del("Proxy-Connection")
  183. req.Header.Del("Connection")
  184. req.Header.Del("Proxy-Authenticate")
  185. req.Header.Del("Proxy-Authorization")
  186. req.Header.Del("TE")
  187. req.Header.Del("Trailers")
  188. req.Header.Del("Transfer-Encoding")
  189. req.Header.Del("Upgrade")
  190. }