diff --git a/common/tls/reality_client.go b/common/tls/reality_client.go index 13f88e385..be4806fe6 100644 --- a/common/tls/reality_client.go +++ b/common/tls/reality_client.go @@ -34,6 +34,7 @@ import ( "github.com/sagernet/sing/common/debug" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/logger" + M "github.com/sagernet/sing/common/metadata" "github.com/sagernet/sing/common/ntp" aTLS "github.com/sagernet/sing/common/tls" @@ -254,7 +255,15 @@ func realityClientFallback(ctx context.Context, uConn net.Conn, serverName strin }, }, } - request, _ := http.NewRequest("GET", "https://"+serverName, nil) + serverAddress := M.ParseSocksaddrHostPort(serverName, 0) + host := serverAddress.AddrString() + if serverAddress.IsIPv6() { + host = "[" + host + "]" + } + request, err := http.NewRequest("GET", "https://"+host, nil) + if err != nil { + return + } request.Header.Set("User-Agent", fingerprint.Client) request.AddCookie(&http.Cookie{Name: "padding", Value: strings.Repeat("0", mRand.Intn(32)+30)}) response, err := client.Do(request) diff --git a/dns/transport/https.go b/dns/transport/https.go index 4d5d3fb21..9325886aa 100644 --- a/dns/transport/https.go +++ b/dns/transport/https.go @@ -5,10 +5,8 @@ import ( "context" "errors" "io" - "net" "net/http" "net/url" - "strconv" "sync" "sync/atomic" "time" @@ -82,15 +80,14 @@ func NewHTTPS(ctx context.Context, logger log.ContextLogger, tag string, options host = options.Server } } - destinationURL := url.URL{ - Scheme: "https", - Host: host, - } - if destinationURL.Host == "" { - destinationURL.Host = options.Server - } + destinationAddress := M.ParseSocksaddrHostPort(host, options.ServerPort) + destinationURL := url.URL{Scheme: "https"} if options.ServerPort != 0 && options.ServerPort != 443 { - destinationURL.Host = net.JoinHostPort(destinationURL.Host, strconv.Itoa(int(options.ServerPort))) + destinationURL.Host = destinationAddress.String() + } else if destinationAddress.IsIPv6() { + destinationURL.Host = "[" + destinationAddress.AddrString() + "]" + } else { + destinationURL.Host = destinationAddress.AddrString() } path := options.Path if path == "" { diff --git a/dns/transport/quic/http3.go b/dns/transport/quic/http3.go index e50d47c08..92d23894c 100644 --- a/dns/transport/quic/http3.go +++ b/dns/transport/quic/http3.go @@ -4,10 +4,8 @@ import ( "bytes" "context" "io" - "net" "net/http" "net/url" - "strconv" "sync" "github.com/sagernet/quic-go" @@ -60,6 +58,7 @@ func NewHTTP3(ctx context.Context, logger log.ContextLogger, tag string, options if err != nil { return nil, err } + tlsConfig.SetNextProtos([]string{http3.NextProtoH3}) stdConfig, err := tlsConfig.STDConfig() if err != nil { return nil, err @@ -75,15 +74,14 @@ func NewHTTP3(ctx context.Context, logger log.ContextLogger, tag string, options host = options.Server } } - destinationURL := url.URL{ - Scheme: "https", - Host: host, - } - if destinationURL.Host == "" { - destinationURL.Host = options.Server - } + destinationAddress := M.ParseSocksaddrHostPort(host, options.ServerPort) + destinationURL := url.URL{Scheme: "https"} if options.ServerPort != 0 && options.ServerPort != 443 { - destinationURL.Host = net.JoinHostPort(destinationURL.Host, strconv.Itoa(int(options.ServerPort))) + destinationURL.Host = destinationAddress.String() + } else if destinationAddress.IsIPv6() { + destinationURL.Host = "[" + destinationAddress.AddrString() + "]" + } else { + destinationURL.Host = destinationAddress.AddrString() } path := options.Path if path == "" { @@ -115,12 +113,12 @@ func NewHTTP3(ctx context.Context, logger log.ContextLogger, tag string, options func (t *HTTP3Transport) newTransport() *http3.Transport { return &http3.Transport{ - Dial: func(ctx context.Context, addr string, tlsCfg *tls.STDConfig, cfg *quic.Config) (*quic.Conn, error) { + Dial: func(ctx context.Context, _ string, _ *tls.STDConfig, cfg *quic.Config) (*quic.Conn, error) { conn, dialErr := t.dialer.DialContext(ctx, N.NetworkUDP, t.serverAddr) if dialErr != nil { return nil, dialErr } - quicConn, dialErr := quic.DialEarlyConn(ctx, conn, tlsCfg, cfg) + quicConn, dialErr := quic.DialEarlyConn(ctx, conn, t.tlsConfig, cfg) if dialErr != nil { conn.Close() return nil, dialErr @@ -133,7 +131,6 @@ func (t *HTTP3Transport) newTransport() *http3.Transport { }() return quicConn, nil }, - TLSClientConfig: t.tlsConfig, } } diff --git a/service/derp/service.go b/service/derp/service.go index 73fa2d7f1..923fbf7fc 100644 --- a/service/derp/service.go +++ b/service/derp/service.go @@ -308,11 +308,14 @@ func (d *Service) startMeshWithHost(derpServer *derpserver.Server, server *optio logf := func(format string, args ...any) { d.logger.Debug(F.ToString("mesh(", hostname, "): ", fmt.Sprintf(format, args...))) } + meshAddress := M.ParseSocksaddrHostPort(hostname, server.ServerPort) var meshHost string - if server.ServerPort == 0 || server.ServerPort == 443 { - meshHost = hostname + if server.ServerPort != 0 && server.ServerPort != 443 { + meshHost = meshAddress.String() + } else if meshAddress.IsIPv6() { + meshHost = "[" + meshAddress.AddrString() + "]" } else { - meshHost = M.ParseSocksaddrHostPort(hostname, server.ServerPort).String() + meshHost = meshAddress.AddrString() } var serverURL string if stdConfig != nil { @@ -328,7 +331,7 @@ func (d *Service) startMeshWithHost(derpServer *derpserver.Server, server *optio meshClient.MeshKey = derpServer.MeshKey() meshClient.WatchConnectionChanges = true meshClient.SetURLDialer(func(ctx context.Context, network, addr string) (net.Conn, error) { - return meshDialer.DialContext(ctx, network, M.ParseSocksaddr(addr)) + return meshDialer.DialContext(ctx, network, M.ParseSocksaddrHostPort(server.Server, M.ParseSocksaddr(addr).Port)) }) add := func(m derp.PeerPresentMessage) { derpServer.AddPacketForwarder(m.Key, meshClient) } remove := func(m derp.PeerGoneMessage) { derpServer.RemovePacketForwarder(m.Peer, meshClient) } diff --git a/transport/v2rayhttp/client.go b/transport/v2rayhttp/client.go index 9d21d91fe..21554e6a6 100644 --- a/transport/v2rayhttp/client.go +++ b/transport/v2rayhttp/client.go @@ -114,7 +114,11 @@ func (c *Client) dialHTTP(ctx context.Context) (net.Conn, error) { } switch hostLen := len(c.host); hostLen { case 0: - request.Host = c.serverAddr.AddrString() + if c.serverAddr.IsIPv6() { + request.Host = "[" + c.serverAddr.AddrString() + "]" + } else { + request.Host = c.serverAddr.AddrString() + } case 1: request.Host = c.host[0] default: diff --git a/transport/v2rayhttpupgrade/client.go b/transport/v2rayhttpupgrade/client.go index ea4c425bc..207c4ebe6 100644 --- a/transport/v2rayhttpupgrade/client.go +++ b/transport/v2rayhttpupgrade/client.go @@ -40,7 +40,12 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt if options.Host != "" { host = options.Host } else if tlsConfig != nil && tlsConfig.ServerName() != "" { - host = tlsConfig.ServerName() + serverName := M.ParseSocksaddrHostPort(tlsConfig.ServerName(), 0) + if serverName.IsIPv6() { + host = "[" + serverName.AddrString() + "]" + } else { + host = serverName.AddrString() + } } else { host = serverAddr.String() }