Fix XHTTP TLS

This commit is contained in:
Sergei Maklagin
2025-12-08 22:30:58 +03:00
parent 6e4b7ed744
commit 984fc295b3
3 changed files with 14 additions and 28 deletions

View File

@@ -48,7 +48,6 @@
"h_keep_alive_period": 60 "h_keep_alive_period": 60
}, },
"download": { "download": {
"mode": "",
"host": "example.com", "host": "example.com",
"path": "/xhttp", "path": "/xhttp",
"domain_strategy": "prefer_ipv4", "domain_strategy": "prefer_ipv4",

View File

@@ -110,7 +110,6 @@ type V2RayHTTPUpgradeOptions struct {
} }
type V2RayXHTTPBaseOptions struct { type V2RayXHTTPBaseOptions struct {
Mode string `json:"mode"`
Host string `json:"host,omitempty"` Host string `json:"host,omitempty"`
Path string `json:"path,omitempty"` Path string `json:"path,omitempty"`
Headers map[string]string `json:"headers,omitempty"` Headers map[string]string `json:"headers,omitempty"`
@@ -126,6 +125,7 @@ type V2RayXHTTPBaseOptions struct {
} }
type V2RayXHTTPOptions struct { type V2RayXHTTPOptions struct {
Mode string `json:"mode"`
V2RayXHTTPBaseOptions V2RayXHTTPBaseOptions
Download *V2RayXHTTPDownloadOptions `json:"download"` Download *V2RayXHTTPDownloadOptions `json:"download"`
} }

View File

@@ -13,8 +13,8 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/quic-go/quic-go" "github.com/sagernet/quic-go"
"github.com/quic-go/quic-go/http3" "github.com/sagernet/quic-go/http3"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/tls" "github.com/sagernet/sing-box/common/tls"
"github.com/sagernet/sing-box/common/xray/buf" "github.com/sagernet/sing-box/common/xray/buf"
@@ -23,6 +23,7 @@ import (
"github.com/sagernet/sing-box/common/xray/signal/done" "github.com/sagernet/sing-box/common/xray/signal/done"
"github.com/sagernet/sing-box/common/xray/uuid" "github.com/sagernet/sing-box/common/xray/uuid"
"github.com/sagernet/sing-box/option" "github.com/sagernet/sing-box/option"
qtls "github.com/sagernet/sing-quic"
"github.com/sagernet/sing/common" "github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/bufio" "github.com/sagernet/sing/common/bufio"
E "github.com/sagernet/sing/common/exceptions" E "github.com/sagernet/sing/common/exceptions"
@@ -47,14 +48,6 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
return nil, E.New("mode is not set") return nil, E.New("mode is not set")
} }
dest := serverAddr dest := serverAddr
var gotlsConfig *gotls.Config
if tlsConfig != nil {
var err error
gotlsConfig, err = tlsConfig.Config()
if err != nil {
return nil, err
}
}
baseRequestURL, err := getBaseRequestURL( baseRequestURL, err := getBaseRequestURL(
&options.V2RayXHTTPBaseOptions, dest, tlsConfig, &options.V2RayXHTTPBaseOptions, dest, tlsConfig,
) )
@@ -71,7 +64,7 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
xmuxOptions = *options.Xmux xmuxOptions = *options.Xmux
} }
xmuxManager := NewXmuxManager(xmuxOptions, func() XmuxConn { xmuxManager := NewXmuxManager(xmuxOptions, func() XmuxConn {
return createHTTPClient(dest, dialer, &options.V2RayXHTTPBaseOptions, tlsConfig, gotlsConfig) return createHTTPClient(dest, dialer, &options.V2RayXHTTPBaseOptions, tlsConfig)
}) })
getHTTPClient := func() (DialerClient, *XmuxClient) { getHTTPClient := func() (DialerClient, *XmuxClient) {
xmuxClient := xmuxManager.GetXmuxClient(ctx) xmuxClient := xmuxManager.GetXmuxClient(ctx)
@@ -91,16 +84,11 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
} }
dest2 := options2.ServerOptions.Build() dest2 := options2.ServerOptions.Build()
var tlsConfig2 tls.Config var tlsConfig2 tls.Config
var gotlsConfig2 *gotls.Config
if options2.TLS != nil { if options2.TLS != nil {
tlsConfig2, err = tls.NewClient(ctx, options2.Server, common.PtrValueOrDefault(options2.TLS)) tlsConfig2, err = tls.NewClient(ctx, options2.Server, common.PtrValueOrDefault(options2.TLS))
if err != nil { if err != nil {
return nil, err return nil, err
} }
gotlsConfig2, err = tlsConfig2.Config()
if err != nil {
return nil, err
}
} }
baseRequestURL2, err := getBaseRequestURL(&options2.V2RayXHTTPBaseOptions, dest2, tlsConfig2) baseRequestURL2, err := getBaseRequestURL(&options2.V2RayXHTTPBaseOptions, dest2, tlsConfig2)
if err != nil { if err != nil {
@@ -116,7 +104,7 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
xmuxOptions2 = *options2.Xmux xmuxOptions2 = *options2.Xmux
} }
xmuxManager2 := NewXmuxManager(xmuxOptions2, func() XmuxConn { xmuxManager2 := NewXmuxManager(xmuxOptions2, func() XmuxConn {
return createHTTPClient(dest2, dialer2, &options2.V2RayXHTTPBaseOptions, tlsConfig2, gotlsConfig2) return createHTTPClient(dest2, dialer2, &options2.V2RayXHTTPBaseOptions, tlsConfig2)
}) })
getHTTPClient2 = func() (DialerClient, *XmuxClient) { getHTTPClient2 = func() (DialerClient, *XmuxClient) {
xmuxClient2 := xmuxManager2.GetXmuxClient(ctx) xmuxClient2 := xmuxManager2.GetXmuxClient(ctx)
@@ -262,11 +250,11 @@ func (c *Client) Close() error {
return nil return nil
} }
func decideHTTPVersion(gotlsConfig *gotls.Config) string { func decideHTTPVersion(tlsConfig tls.Config) string {
if gotlsConfig == nil || len(gotlsConfig.NextProtos) == 0 || gotlsConfig.NextProtos[0] == "http/1.1" { if tlsConfig == nil || len(tlsConfig.NextProtos()) == 0 || tlsConfig.NextProtos()[0] == "http/1.1" {
return "1.1" return "1.1"
} }
if gotlsConfig.NextProtos[0] == "h3" { if tlsConfig.NextProtos()[0] == "h3" {
return "3" return "3"
} }
return "2" return "2"
@@ -298,8 +286,8 @@ func getBaseRequestURL(options *option.V2RayXHTTPBaseOptions, dest M.Socksaddr,
return requestURL, nil return requestURL, nil
} }
func createHTTPClient(dest M.Socksaddr, dialer N.Dialer, options *option.V2RayXHTTPBaseOptions, tlsConfig tls.Config, gotlsConfig *gotls.Config) DialerClient { func createHTTPClient(dest M.Socksaddr, dialer N.Dialer, options *option.V2RayXHTTPBaseOptions, tlsConfig tls.Config) DialerClient {
httpVersion := decideHTTPVersion(gotlsConfig) httpVersion := decideHTTPVersion(tlsConfig)
dialContext := func(ctxInner context.Context) (net.Conn, error) { dialContext := func(ctxInner context.Context) (net.Conn, error) {
conn, err := dialer.DialContext(ctxInner, "tcp", dest) conn, err := dialer.DialContext(ctxInner, "tcp", dest)
if err != nil { if err != nil {
@@ -332,14 +320,13 @@ func createHTTPClient(dest M.Socksaddr, dialer N.Dialer, options *option.V2RayXH
KeepAlivePeriod: keepAlivePeriod, KeepAlivePeriod: keepAlivePeriod,
} }
transport = &http3.Transport{ transport = &http3.Transport{
QUICConfig: quicConfig, QUICConfig: quicConfig,
TLSClientConfig: gotlsConfig.Clone(), Dial: func(ctx context.Context, addr string, tlsCfg *gotls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
Dial: func(ctx context.Context, addr string, tlsCfg *gotls.Config, cfg *quic.Config) (*quic.Conn, error) {
udpConn, dErr := dialer.DialContext(ctx, N.NetworkUDP, dest) udpConn, dErr := dialer.DialContext(ctx, N.NetworkUDP, dest)
if dErr != nil { if dErr != nil {
return nil, dErr return nil, dErr
} }
return quic.DialEarly(ctx, bufio.NewUnbindPacketConn(udpConn), udpConn.RemoteAddr(), tlsCfg, cfg) return qtls.DialEarly(ctx, bufio.NewUnbindPacketConn(udpConn), udpConn.RemoteAddr(), tlsConfig, cfg)
}, },
} }
case "2": case "2":