Chore: http

This commit is contained in:
yaling888
2022-04-27 05:14:03 +08:00
committed by Meta Gowork
parent cca3a1a934
commit 564a6fdf35
4 changed files with 56 additions and 50 deletions

View File

@ -62,9 +62,9 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache[string,
request.RequestURI = ""
if isUpgradeRequest(request) {
handleUpgrade(conn, request, in)
return // hijack connection
if resp = handleUpgrade(conn, conn.RemoteAddr(), request, in); resp == nil {
return // hijack connection
}
}
removeHopByHopHeaders(request.Header)
@ -96,7 +96,7 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache[string,
}
}
conn.Close()
_ = conn.Close()
}
func authenticate(request *http.Request, cache *cache.Cache[string, bool]) *http.Response {

View File

@ -1,9 +1,12 @@
package http
import (
"context"
"crypto/tls"
"net"
"net/http"
"strings"
"time"
"github.com/Dreamacro/clash/adapter/inbound"
N "github.com/Dreamacro/clash/common/net"
@ -15,15 +18,17 @@ func isUpgradeRequest(req *http.Request) bool {
return strings.EqualFold(req.Header.Get("Connection"), "Upgrade")
}
func handleUpgrade(conn net.Conn, request *http.Request, in chan<- C.ConnContext) {
defer conn.Close()
func handleUpgrade(conn net.Conn, request *http.Request, in chan<- C.ConnContext) (resp *http.Response) {
removeProxyHeaders(request.Header)
removeExtraHTTPHostPort(request)
address := request.Host
if _, _, err := net.SplitHostPort(address); err != nil {
address = net.JoinHostPort(address, "80")
port := "80"
if request.TLS != nil {
port = "443"
}
address = net.JoinHostPort(address, port)
}
dstAddr := socks5.ParseAddr(address)
@ -35,27 +40,56 @@ func handleUpgrade(conn net.Conn, request *http.Request, in chan<- C.ConnContext
in <- inbound.NewHTTP(dstAddr, conn.RemoteAddr(), right)
bufferedLeft := N.NewBufferedConn(left)
defer bufferedLeft.Close()
var remoteServer *N.BufferedConn
if request.TLS != nil {
tlsConn := tls.Client(left, &tls.Config{
ServerName: request.URL.Hostname(),
})
err := request.Write(bufferedLeft)
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
defer cancel()
if tlsConn.HandshakeContext(ctx) != nil {
_ = localConn.Close()
_ = left.Close()
return
}
remoteServer = N.NewBufferedConn(tlsConn)
} else {
remoteServer = N.NewBufferedConn(left)
}
defer func() {
_ = remoteServer.Close()
}()
err := request.Write(remoteServer)
if err != nil {
_ = localConn.Close()
return
}
resp, err := http.ReadResponse(bufferedLeft.Reader(), request)
if err != nil {
return
}
removeProxyHeaders(resp.Header)
err = resp.Write(conn)
resp, err = http.ReadResponse(remoteServer.Reader(), request)
if err != nil {
_ = localConn.Close()
return
}
if resp.StatusCode == http.StatusSwitchingProtocols {
N.Relay(bufferedLeft, conn)
removeProxyHeaders(resp.Header)
err = localConn.SetReadDeadline(time.Time{}) // set to not time out
if err != nil {
return
}
err = resp.Write(localConn)
if err != nil {
return
}
N.Relay(remoteServer, localConn) // blocking here
_ = localConn.Close()
resp = nil
}
return
}