From e118600b2138929ce8eef26b664f189d22f8e3ec Mon Sep 17 00:00:00 2001 From: dyhkwong <50692134+dyhkwong@users.noreply.github.com> Date: Mon, 18 Nov 2024 13:47:21 +0800 Subject: [PATCH] Handle Basic Auth before HTTP RoundTrip --- quic/transport_http3.go | 16 ++++++++++------ transport_https.go | 27 ++++++++++++++++++--------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/quic/transport_http3.go b/quic/transport_http3.go index b00f0c1..00d3208 100644 --- a/quic/transport_http3.go +++ b/quic/transport_http3.go @@ -31,9 +31,9 @@ func init() { } type HTTP3Transport struct { - name string - destination string - transport *http3.RoundTripper + name string + serverURL *url.URL + transport *http3.RoundTripper } func NewHTTP3Transport(options dns.TransportOptions) (*HTTP3Transport, error) { @@ -43,8 +43,8 @@ func NewHTTP3Transport(options dns.TransportOptions) (*HTTP3Transport, error) { } serverURL.Scheme = "https" return &HTTP3Transport{ - name: options.Name, - destination: serverURL.String(), + name: options.Name, + serverURL: serverURL, transport: &http3.RoundTripper{ Dial: func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) { destinationAddr := M.ParseSocksaddr(addr) @@ -91,13 +91,17 @@ func (t *HTTP3Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS requestBuffer.Release() return nil, err } - request, err := http.NewRequestWithContext(ctx, http.MethodPost, t.destination, bytes.NewReader(rawMessage)) + request, err := http.NewRequestWithContext(ctx, http.MethodPost, t.serverURL.String(), bytes.NewReader(rawMessage)) if err != nil { requestBuffer.Release() return nil, err } request.Header.Set("Content-Type", dns.MimeType) request.Header.Set("Accept", dns.MimeType) + if t.serverURL.User != nil { + password, _ := t.serverURL.User.Password() + request.SetBasicAuth(t.serverURL.User.Username(), password) + } response, err := t.transport.RoundTrip(request) requestBuffer.Release() if err != nil { diff --git a/transport_https.go b/transport_https.go index eb680ab..bf9b4d7 100644 --- a/transport_https.go +++ b/transport_https.go @@ -8,6 +8,7 @@ import ( "net" "net/http" "net/netip" + "net/url" "os" "github.com/sagernet/sing/common/buf" @@ -22,21 +23,25 @@ const MimeType = "application/dns-message" var _ Transport = (*HTTPSTransport)(nil) type HTTPSTransport struct { - name string - destination string - transport *http.Transport + name string + serverURL *url.URL + transport *http.Transport } func init() { RegisterTransport([]string{"https"}, func(options TransportOptions) (Transport, error) { - return NewHTTPSTransport(options), nil + return NewHTTPSTransport(options) }) } -func NewHTTPSTransport(options TransportOptions) *HTTPSTransport { +func NewHTTPSTransport(options TransportOptions) (*HTTPSTransport, error) { + serverURL, err := url.Parse(options.Address) + if err != nil { + return nil, err + } return &HTTPSTransport{ - name: options.Name, - destination: options.Address, + name: options.Name, + serverURL: serverURL, transport: &http.Transport{ ForceAttemptHTTP2: true, DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { @@ -46,7 +51,7 @@ func NewHTTPSTransport(options TransportOptions) *HTTPSTransport { NextProtos: []string{"dns"}, }, }, - } + }, nil } func (t *HTTPSTransport) Name() string { @@ -81,13 +86,17 @@ func (t *HTTPSTransport) Exchange(ctx context.Context, message *dns.Msg) (*dns.M requestBuffer.Release() return nil, err } - request, err := http.NewRequestWithContext(ctx, http.MethodPost, t.destination, bytes.NewReader(rawMessage)) + request, err := http.NewRequestWithContext(ctx, http.MethodPost, t.serverURL.String(), bytes.NewReader(rawMessage)) if err != nil { requestBuffer.Release() return nil, err } request.Header.Set("Content-Type", MimeType) request.Header.Set("Accept", MimeType) + if t.serverURL.User != nil { + password, _ := t.serverURL.User.Password() + request.SetBasicAuth(t.serverURL.User.Username(), password) + } response, err := t.transport.RoundTrip(request) requestBuffer.Release() if err != nil {