github.com/yaling888/clash@v1.53.0/listener/mitm/client.go (about)

     1  package mitm
     2  
     3  import (
     4  	"context"
     5  	"crypto/tls"
     6  	"net"
     7  	"net/http"
     8  
     9  	"github.com/yaling888/clash/adapter/inbound"
    10  	N "github.com/yaling888/clash/common/net"
    11  	C "github.com/yaling888/clash/constant"
    12  	"github.com/yaling888/clash/transport/socks5"
    13  )
    14  
    15  func getServerConn(serverConn *N.BufferedConn, request *http.Request, srcAddr net.Addr, originTarget net.Addr, in chan<- C.ConnContext) (*N.BufferedConn, error) {
    16  	if serverConn != nil {
    17  		return serverConn, nil
    18  	}
    19  
    20  	address := request.URL.Host
    21  	if _, _, err := net.SplitHostPort(address); err != nil {
    22  		port := "80"
    23  		if request.TLS != nil {
    24  			port = "443"
    25  		}
    26  		address = net.JoinHostPort(address, port)
    27  	}
    28  
    29  	dstAddr := socks5.ParseAddr(address)
    30  	if dstAddr == nil {
    31  		return nil, socks5.ErrAddressNotSupported
    32  	}
    33  
    34  	specialProxy := request.Header.Get("Origin-Request-Special-Proxy")
    35  	request.Header.Del("Origin-Request-Special-Proxy")
    36  
    37  	left, right := net.Pipe()
    38  
    39  	in <- inbound.NewMitm(dstAddr, srcAddr, originTarget, request.Header.Get("User-Agent"), specialProxy, right)
    40  
    41  	if request.TLS != nil {
    42  		tlsConn := tls.Client(left, &tls.Config{
    43  			ServerName: request.TLS.ServerName,
    44  		})
    45  
    46  		ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
    47  		defer cancel()
    48  		if err := tlsConn.HandshakeContext(ctx); err != nil {
    49  			return nil, err
    50  		}
    51  
    52  		serverConn = N.NewBufferedConn(tlsConn)
    53  	} else {
    54  		serverConn = N.NewBufferedConn(left)
    55  	}
    56  
    57  	return serverConn, nil
    58  }