mirror of https://github.com/fatedier/frp.git
http_proxy: fix error using encryption or compression
This commit is contained in:
parent
70e2aee46d
commit
2a044c9d6d
|
@ -15,6 +15,7 @@
|
||||||
package plugin
|
package plugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -106,14 +107,26 @@ func (hp *HttpProxy) Name() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hp *HttpProxy) Handle(conn io.ReadWriteCloser) {
|
func (hp *HttpProxy) Handle(conn io.ReadWriteCloser) {
|
||||||
var wrapConn net.Conn
|
var wrapConn frpNet.Conn
|
||||||
if realConn, ok := conn.(net.Conn); ok {
|
if realConn, ok := conn.(frpNet.Conn); ok {
|
||||||
wrapConn = realConn
|
wrapConn = realConn
|
||||||
} else {
|
} else {
|
||||||
wrapConn = frpNet.WrapReadWriteCloserToConn(conn)
|
wrapConn = frpNet.WrapReadWriteCloserToConn(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
hp.l.PutConn(wrapConn)
|
sc, rd := frpNet.NewShareConn(wrapConn)
|
||||||
|
request, err := http.ReadRequest(bufio.NewReader(rd))
|
||||||
|
if err != nil {
|
||||||
|
wrapConn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if request.Method == http.MethodConnect {
|
||||||
|
hp.handleConnectReq(request, frpIo.WrapReadWriteCloser(rd, wrapConn, nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hp.l.PutConn(sc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,13 +137,15 @@ func (hp *HttpProxy) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hp *HttpProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (hp *HttpProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
if ok := hp.Auth(rw, req); !ok {
|
if ok := hp.Auth(req); !ok {
|
||||||
rw.Header().Set("Proxy-Authenticate", "Basic")
|
rw.Header().Set("Proxy-Authenticate", "Basic")
|
||||||
rw.WriteHeader(http.StatusProxyAuthRequired)
|
rw.WriteHeader(http.StatusProxyAuthRequired)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Method == "CONNECT" {
|
if req.Method == http.MethodConnect {
|
||||||
|
// deprecated
|
||||||
|
// Connect request is handled in Handle function.
|
||||||
hp.ConnectHandler(rw, req)
|
hp.ConnectHandler(rw, req)
|
||||||
} else {
|
} else {
|
||||||
hp.HttpHandler(rw, req)
|
hp.HttpHandler(rw, req)
|
||||||
|
@ -156,6 +171,9 @@ func (hp *HttpProxy) HttpHandler(rw http.ResponseWriter, req *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// deprecated
|
||||||
|
// Hijack needs to SetReadDeadline on the Conn of the request, but if we use stream compression here,
|
||||||
|
// we may always get i/o timeout error.
|
||||||
func (hp *HttpProxy) ConnectHandler(rw http.ResponseWriter, req *http.Request) {
|
func (hp *HttpProxy) ConnectHandler(rw http.ResponseWriter, req *http.Request) {
|
||||||
hj, ok := rw.(http.Hijacker)
|
hj, ok := rw.(http.Hijacker)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -180,7 +198,7 @@ func (hp *HttpProxy) ConnectHandler(rw http.ResponseWriter, req *http.Request) {
|
||||||
go frpIo.Join(remote, client)
|
go frpIo.Join(remote, client)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hp *HttpProxy) Auth(rw http.ResponseWriter, req *http.Request) bool {
|
func (hp *HttpProxy) Auth(req *http.Request) bool {
|
||||||
if hp.AuthUser == "" && hp.AuthPasswd == "" {
|
if hp.AuthUser == "" && hp.AuthPasswd == "" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -206,6 +224,30 @@ func (hp *HttpProxy) Auth(rw http.ResponseWriter, req *http.Request) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hp *HttpProxy) handleConnectReq(req *http.Request, rwc io.ReadWriteCloser) {
|
||||||
|
defer rwc.Close()
|
||||||
|
if ok := hp.Auth(req); !ok {
|
||||||
|
res := getBadResponse()
|
||||||
|
res.Write(rwc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
remote, err := net.Dial("tcp", req.URL.Host)
|
||||||
|
if err != nil {
|
||||||
|
res := &http.Response{
|
||||||
|
StatusCode: 400,
|
||||||
|
Proto: "HTTP/1.1",
|
||||||
|
ProtoMajor: 1,
|
||||||
|
ProtoMinor: 1,
|
||||||
|
}
|
||||||
|
res.Write(rwc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rwc.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
|
||||||
|
|
||||||
|
frpIo.Join(remote, rwc)
|
||||||
|
}
|
||||||
|
|
||||||
func copyHeaders(dst, src http.Header) {
|
func copyHeaders(dst, src http.Header) {
|
||||||
for key, values := range src {
|
for key, values := range src {
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
|
@ -225,3 +267,17 @@ func removeProxyHeaders(req *http.Request) {
|
||||||
req.Header.Del("Transfer-Encoding")
|
req.Header.Del("Transfer-Encoding")
|
||||||
req.Header.Del("Upgrade")
|
req.Header.Del("Upgrade")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getBadResponse() *http.Response {
|
||||||
|
header := make(map[string][]string)
|
||||||
|
header["Proxy-Authenticate"] = []string{"Basic"}
|
||||||
|
res := &http.Response{
|
||||||
|
Status: "407 Not authorized",
|
||||||
|
StatusCode: 407,
|
||||||
|
Proto: "HTTP/1.1",
|
||||||
|
ProtoMajor: 1,
|
||||||
|
ProtoMinor: 1,
|
||||||
|
Header: header,
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue