chore: update quic-go to 0.57.1

This commit is contained in:
wwqgtxx 2025-12-17 16:13:12 +08:00
parent a06097c2c4
commit 1cab34d257
80 changed files with 383 additions and 543 deletions

View File

@ -5,7 +5,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net" "net"
"net/http"
"net/url" "net/url"
"strings" "strings"
"time" "time"
@ -17,6 +16,8 @@ import (
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/http"
) )
var UnifiedDelay = atomic.NewBool(false) var UnifiedDelay = atomic.NewBool(false)

View File

@ -2,9 +2,10 @@ package inbound
import ( import (
"net" "net"
"net/http"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/http"
) )
// NewHTTPS receive CONNECT request and return ConnContext // NewHTTPS receive CONNECT request and return ConnContext

View File

@ -2,12 +2,13 @@ package inbound
import ( import (
"net" "net"
"net/http"
"net/netip" "net/netip"
"strings" "strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/transport/socks5" "github.com/metacubex/mihomo/transport/socks5"
"github.com/metacubex/http"
) )
func parseSocksAddr(target socks5.Addr) *C.Metadata { func parseSocksAddr(target socks5.Addr) *C.Metadata {

View File

@ -3,17 +3,18 @@ package outbound
import ( import (
"bufio" "bufio"
"context" "context"
"crypto/tls"
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/http"
"strconv" "strconv"
N "github.com/metacubex/mihomo/common/net" N "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/http"
"github.com/metacubex/tls"
) )
type Http struct { type Http struct {

View File

@ -2,7 +2,6 @@ package outbound
import ( import (
"context" "context"
"crypto/tls"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"net" "net"
@ -13,7 +12,6 @@ import (
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/dialer" "github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
hyCongestion "github.com/metacubex/mihomo/transport/hysteria/congestion" hyCongestion "github.com/metacubex/mihomo/transport/hysteria/congestion"
@ -23,6 +21,8 @@ import (
"github.com/metacubex/mihomo/transport/hysteria/transport" "github.com/metacubex/mihomo/transport/hysteria/transport"
"github.com/metacubex/mihomo/transport/hysteria/utils" "github.com/metacubex/mihomo/transport/hysteria/utils"
"github.com/metacubex/tls"
"github.com/metacubex/quic-go" "github.com/metacubex/quic-go"
"github.com/metacubex/quic-go/congestion" "github.com/metacubex/quic-go/congestion"
M "github.com/metacubex/sing/common/metadata" M "github.com/metacubex/sing/common/metadata"
@ -45,7 +45,7 @@ type Hysteria struct {
option *HysteriaOption option *HysteriaOption
client *core.Client client *core.Client
tlsConfig *tlsC.Config tlsConfig *tls.Config
echConfig *ech.Config echConfig *ech.Config
} }
@ -175,7 +175,7 @@ func NewHysteria(option HysteriaOption) (*Hysteria, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
tlsClientConfig := tlsC.UConfig(tlsConfig) tlsClientConfig := tlsConfig
quicConfig := &quic.Config{ quicConfig := &quic.Config{
InitialStreamReceiveWindow: uint64(option.ReceiveWindowConn), InitialStreamReceiveWindow: uint64(option.ReceiveWindowConn),

View File

@ -2,7 +2,6 @@ package outbound
import ( import (
"context" "context"
"crypto/tls"
"errors" "errors"
"fmt" "fmt"
"net" "net"
@ -13,7 +12,6 @@ import (
"github.com/metacubex/mihomo/common/utils" "github.com/metacubex/mihomo/common/utils"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/proxydialer" "github.com/metacubex/mihomo/component/proxydialer"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
tuicCommon "github.com/metacubex/mihomo/transport/tuic/common" tuicCommon "github.com/metacubex/mihomo/transport/tuic/common"
@ -21,6 +19,7 @@ import (
"github.com/metacubex/quic-go" "github.com/metacubex/quic-go"
"github.com/metacubex/sing-quic/hysteria2" "github.com/metacubex/sing-quic/hysteria2"
M "github.com/metacubex/sing/common/metadata" M "github.com/metacubex/sing/common/metadata"
"github.com/metacubex/tls"
) )
func init() { func init() {
@ -157,7 +156,7 @@ func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) {
tlsConfig.NextProtos = option.ALPN tlsConfig.NextProtos = option.ALPN
} }
tlsClientConfig := tlsC.UConfig(tlsConfig) tlsClientConfig := tlsConfig
echConfig, err := option.ECHOpts.Parse() echConfig, err := option.ECHOpts.Parse()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -2,7 +2,6 @@ package outbound
import ( import (
"context" "context"
"crypto/tls"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@ -14,6 +13,8 @@ import (
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/transport/socks5" "github.com/metacubex/mihomo/transport/socks5"
"github.com/metacubex/tls"
) )
type Socks5 struct { type Socks5 struct {

View File

@ -2,11 +2,9 @@ package outbound
import ( import (
"context" "context"
"crypto/tls"
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/http"
"strconv" "strconv"
N "github.com/metacubex/mihomo/common/net" N "github.com/metacubex/mihomo/common/net"
@ -18,6 +16,9 @@ import (
"github.com/metacubex/mihomo/transport/shadowsocks/core" "github.com/metacubex/mihomo/transport/shadowsocks/core"
"github.com/metacubex/mihomo/transport/trojan" "github.com/metacubex/mihomo/transport/trojan"
"github.com/metacubex/mihomo/transport/vmess" "github.com/metacubex/mihomo/transport/vmess"
"github.com/metacubex/http"
"github.com/metacubex/tls"
) )
type Trojan struct { type Trojan struct {

View File

@ -2,7 +2,6 @@ package outbound
import ( import (
"context" "context"
"crypto/tls"
"fmt" "fmt"
"math" "math"
"net" "net"
@ -11,7 +10,6 @@ import (
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/transport/tuic" "github.com/metacubex/mihomo/transport/tuic"
@ -19,6 +17,7 @@ import (
"github.com/metacubex/quic-go" "github.com/metacubex/quic-go"
M "github.com/metacubex/sing/common/metadata" M "github.com/metacubex/sing/common/metadata"
"github.com/metacubex/sing/common/uot" "github.com/metacubex/sing/common/uot"
"github.com/metacubex/tls"
) )
type Tuic struct { type Tuic struct {
@ -26,7 +25,7 @@ type Tuic struct {
option *TuicOption option *TuicOption
client *tuic.PoolClient client *tuic.PoolClient
tlsConfig *tlsC.Config tlsConfig *tls.Config
echConfig *ech.Config echConfig *ech.Config
} }
@ -233,7 +232,7 @@ func NewTuic(option TuicOption) (*Tuic, error) {
tlsConfig.InsecureSkipVerify = true // tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config tlsConfig.InsecureSkipVerify = true // tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config
} }
tlsClientConfig := tlsC.UConfig(tlsConfig) tlsClientConfig := tlsConfig
echConfig, err := option.ECHOpts.Parse() echConfig, err := option.ECHOpts.Parse()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -2,10 +2,8 @@ package outbound
import ( import (
"context" "context"
"crypto/tls"
"fmt" "fmt"
"net" "net"
"net/http"
"strconv" "strconv"
"github.com/metacubex/mihomo/common/convert" "github.com/metacubex/mihomo/common/convert"
@ -20,9 +18,11 @@ import (
"github.com/metacubex/mihomo/transport/vless/encryption" "github.com/metacubex/mihomo/transport/vless/encryption"
"github.com/metacubex/mihomo/transport/vmess" "github.com/metacubex/mihomo/transport/vmess"
"github.com/metacubex/http"
vmessSing "github.com/metacubex/sing-vmess" vmessSing "github.com/metacubex/sing-vmess"
"github.com/metacubex/sing-vmess/packetaddr" "github.com/metacubex/sing-vmess/packetaddr"
M "github.com/metacubex/sing/common/metadata" M "github.com/metacubex/sing/common/metadata"
"github.com/metacubex/tls"
) )
type Vless struct { type Vless struct {

View File

@ -2,11 +2,9 @@ package outbound
import ( import (
"context" "context"
"crypto/tls"
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/http"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -21,9 +19,11 @@ import (
"github.com/metacubex/mihomo/transport/gun" "github.com/metacubex/mihomo/transport/gun"
mihomoVMess "github.com/metacubex/mihomo/transport/vmess" mihomoVMess "github.com/metacubex/mihomo/transport/vmess"
"github.com/metacubex/http"
vmess "github.com/metacubex/sing-vmess" vmess "github.com/metacubex/sing-vmess"
"github.com/metacubex/sing-vmess/packetaddr" "github.com/metacubex/sing-vmess/packetaddr"
M "github.com/metacubex/sing/common/metadata" M "github.com/metacubex/sing/common/metadata"
"github.com/metacubex/tls"
) )
var ErrUDPRemoteAddrMismatch = errors.New("udp packet dropped due to mismatched remote address") var ErrUDPRemoteAddrMismatch = errors.New("udp packet dropped due to mismatched remote address")

View File

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"net/http"
"reflect" "reflect"
"runtime" "runtime"
"strings" "strings"
@ -21,6 +20,7 @@ import (
"github.com/metacubex/mihomo/tunnel/statistic" "github.com/metacubex/mihomo/tunnel/statistic"
"github.com/dlclark/regexp2" "github.com/dlclark/regexp2"
"github.com/metacubex/http"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )

View File

@ -2,12 +2,12 @@ package convert
import ( import (
"encoding/base64" "encoding/base64"
"net/http"
"strings" "strings"
"time" "time"
"github.com/metacubex/mihomo/common/utils" "github.com/metacubex/mihomo/common/utils"
"github.com/metacubex/http"
"github.com/metacubex/randv2" "github.com/metacubex/randv2"
"github.com/metacubex/sing-shadowsocks/shadowimpl" "github.com/metacubex/sing-shadowsocks/shadowimpl"
) )

View File

@ -1,17 +1,17 @@
package tls package ca
import ( import (
utls "github.com/metacubex/utls" "github.com/metacubex/tls"
) )
type ClientAuthType = utls.ClientAuthType type ClientAuthType = tls.ClientAuthType
const ( const (
NoClientCert = utls.NoClientCert NoClientCert = tls.NoClientCert
RequestClientCert = utls.RequestClientCert RequestClientCert = tls.RequestClientCert
RequireAnyClientCert = utls.RequireAnyClientCert RequireAnyClientCert = tls.RequireAnyClientCert
VerifyClientCertIfGiven = utls.VerifyClientCertIfGiven VerifyClientCertIfGiven = tls.VerifyClientCertIfGiven
RequireAndVerifyClientCert = utls.RequireAndVerifyClientCert RequireAndVerifyClientCert = tls.RequireAndVerifyClientCert
) )
func ClientAuthTypeFromString(s string) ClientAuthType { func ClientAuthTypeFromString(s string) ClientAuthType {

View File

@ -1,7 +1,6 @@
package ca package ca
import ( import (
"crypto/tls"
"crypto/x509" "crypto/x509"
_ "embed" _ "embed"
"errors" "errors"
@ -13,6 +12,8 @@ import (
"github.com/metacubex/mihomo/common/once" "github.com/metacubex/mihomo/common/once"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/ntp" "github.com/metacubex/mihomo/ntp"
"github.com/metacubex/tls"
) )
var globalCertPool *x509.CertPool var globalCertPool *x509.CertPool

View File

@ -7,13 +7,14 @@ import (
"crypto/elliptic" "crypto/elliptic"
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/pem" "encoding/pem"
"fmt" "fmt"
"math/big" "math/big"
"os" "os"
"time" "time"
"github.com/metacubex/tls"
) )
type Path interface { type Path interface {

View File

@ -5,13 +5,33 @@ import (
"fmt" "fmt"
tlsC "github.com/metacubex/mihomo/component/tls" tlsC "github.com/metacubex/mihomo/component/tls"
"github.com/metacubex/tls"
) )
type Config struct { type Config struct {
GetEncryptedClientHelloConfigList func(ctx context.Context, serverName string) ([]byte, error) GetEncryptedClientHelloConfigList func(ctx context.Context, serverName string) ([]byte, error)
} }
func (cfg *Config) ClientHandle(ctx context.Context, tlsConfig *tlsC.Config) (err error) { func (cfg *Config) ClientHandle(ctx context.Context, tlsConfig *tls.Config) (err error) {
if cfg == nil {
return nil
}
echConfigList, err := cfg.GetEncryptedClientHelloConfigList(ctx, tlsConfig.ServerName)
if err != nil {
return fmt.Errorf("resolve ECH config error: %w", err)
}
tlsConfig.EncryptedClientHelloConfigList = echConfigList
if tlsConfig.MinVersion != 0 && tlsConfig.MinVersion < tls.VersionTLS13 {
tlsConfig.MinVersion = tls.VersionTLS13
}
if tlsConfig.MaxVersion != 0 && tlsConfig.MaxVersion < tls.VersionTLS13 {
tlsConfig.MaxVersion = tls.VersionTLS13
}
return nil
}
func (cfg *Config) ClientHandleUTLS(ctx context.Context, tlsConfig *tlsC.Config) (err error) {
if cfg == nil { if cfg == nil {
return nil return nil
} }

View File

@ -10,8 +10,8 @@ import (
"os" "os"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
tlsC "github.com/metacubex/mihomo/component/tls"
"github.com/metacubex/tls"
"golang.org/x/crypto/cryptobyte" "golang.org/x/crypto/cryptobyte"
) )
@ -85,11 +85,11 @@ func GenECHConfig(publicName string) (configBase64 string, keyPem string, err er
return return
} }
func UnmarshalECHKeys(raw []byte) ([]tlsC.EncryptedClientHelloKey, error) { func UnmarshalECHKeys(raw []byte) ([]tls.EncryptedClientHelloKey, error) {
var keys []tlsC.EncryptedClientHelloKey var keys []tls.EncryptedClientHelloKey
rawString := cryptobyte.String(raw) rawString := cryptobyte.String(raw)
for !rawString.Empty() { for !rawString.Empty() {
var key tlsC.EncryptedClientHelloKey var key tls.EncryptedClientHelloKey
if !rawString.ReadUint16LengthPrefixed((*cryptobyte.String)(&key.PrivateKey)) { if !rawString.ReadUint16LengthPrefixed((*cryptobyte.String)(&key.PrivateKey)) {
return nil, errors.New("error parsing private key") return nil, errors.New("error parsing private key")
} }
@ -104,7 +104,7 @@ func UnmarshalECHKeys(raw []byte) ([]tlsC.EncryptedClientHelloKey, error) {
return keys, nil return keys, nil
} }
func LoadECHKey(key string, tlsConfig *tlsC.Config, path ca.Path) error { func LoadECHKey(key string, tlsConfig *tls.Config, path ca.Path) error {
if key == "" { if key == "" {
return nil return nil
} }
@ -129,7 +129,7 @@ func LoadECHKey(key string, tlsConfig *tlsC.Config, path ca.Path) error {
return nil return nil
} }
func loadECHKey(echKey []byte, tlsConfig *tlsC.Config) error { func loadECHKey(echKey []byte, tlsConfig *tls.Config) error {
block, rest := pem.Decode(echKey) block, rest := pem.Decode(echKey)
if block == nil || block.Type != "ECH KEYS" || len(rest) > 0 { if block == nil || block.Type != "ECH KEYS" || len(rest) > 0 {
return errors.New("invalid ECH keys pem") return errors.New("invalid ECH keys pem")

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"fmt" "fmt"
"io" "io"
"net/http"
"os" "os"
"sync" "sync"
"time" "time"
@ -14,6 +13,8 @@ import (
"github.com/metacubex/mihomo/component/mmdb" "github.com/metacubex/mihomo/component/mmdb"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/http"
) )
var ( var (

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"io" "io"
"net" "net"
"net/http"
URL "net/url" URL "net/url"
"runtime" "runtime"
"strings" "strings"
@ -13,6 +12,8 @@ import (
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/dialer" "github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/listener/inner" "github.com/metacubex/mihomo/listener/inner"
"github.com/metacubex/http"
) )
var ( var (

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"errors" "errors"
"io" "io"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"time" "time"
@ -13,6 +12,8 @@ import (
mihomoHttp "github.com/metacubex/mihomo/component/http" mihomoHttp "github.com/metacubex/mihomo/component/http"
"github.com/metacubex/mihomo/component/profile/cachefile" "github.com/metacubex/mihomo/component/profile/cachefile"
P "github.com/metacubex/mihomo/constant/provider" P "github.com/metacubex/mihomo/constant/provider"
"github.com/metacubex/http"
) )
const ( const (

View File

@ -3,14 +3,13 @@ package tls
import ( import (
"context" "context"
"net" "net"
"net/http"
"runtime/debug" "runtime/debug"
"time" "time"
N "github.com/metacubex/mihomo/common/net" N "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"golang.org/x/net/http2" "github.com/metacubex/http"
) )
func extractTlsHandshakeTimeoutFromServer(s *http.Server) time.Duration { func extractTlsHandshakeTimeoutFromServer(s *http.Server) time.Duration {
@ -35,8 +34,8 @@ func extractTlsHandshakeTimeoutFromServer(s *http.Server) time.Duration {
// only do tls handshake and check NegotiatedProtocol with std's *tls.Conn // only do tls handshake and check NegotiatedProtocol with std's *tls.Conn
// so we do the same logic to let http2 (not h2c) work fine // so we do the same logic to let http2 (not h2c) work fine
func NewListenerForHttps(l net.Listener, httpServer *http.Server, tlsConfig *Config) net.Listener { func NewListenerForHttps(l net.Listener, httpServer *http.Server, tlsConfig *Config) net.Listener {
http2Server := &http2.Server{} http2Server := &http.Http2Server{}
_ = http2.ConfigureServer(httpServer, http2Server) _ = http.Http2ConfigureServer(httpServer, http2Server)
return N.NewHandleContextListener(context.Background(), l, func(ctx context.Context, conn net.Conn) (net.Conn, error) { return N.NewHandleContextListener(context.Background(), l, func(ctx context.Context, conn net.Conn) (net.Conn, error) {
c := Server(conn, tlsConfig) c := Server(conn, tlsConfig)
@ -58,8 +57,8 @@ func NewListenerForHttps(l net.Listener, httpServer *http.Server, tlsConfig *Con
_ = conn.SetWriteDeadline(time.Time{}) _ = conn.SetWriteDeadline(time.Time{})
} }
if c.ConnectionState().NegotiatedProtocol == http2.NextProtoTLS { if c.ConnectionState().NegotiatedProtocol == http.Http2NextProtoTLS {
http2Server.ServeConn(c, &http2.ServeConnOpts{BaseConfig: httpServer}) http2Server.ServeConn(c, &http.Http2ServeConnOpts{BaseConfig: httpServer})
return nil, net.ErrClosed return nil, net.ErrClosed
} }
return c, nil return c, nil

View File

@ -10,22 +10,21 @@ import (
"crypto/hmac" "crypto/hmac"
"crypto/sha256" "crypto/sha256"
"crypto/sha512" "crypto/sha512"
"crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/binary" "encoding/binary"
"errors" "errors"
"net" "net"
"net/http"
"strings" "strings"
"time" "time"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/mihomo/ntp" "github.com/metacubex/mihomo/ntp"
"github.com/metacubex/http"
"github.com/metacubex/randv2" "github.com/metacubex/randv2"
"github.com/metacubex/tls"
utls "github.com/metacubex/utls" utls "github.com/metacubex/utls"
"golang.org/x/crypto/hkdf" "golang.org/x/crypto/hkdf"
"golang.org/x/net/http2"
) )
const RealityMaxShortIDLen = 8 const RealityMaxShortIDLen = 8
@ -132,7 +131,7 @@ func GetRealityConn(ctx context.Context, conn net.Conn, fingerprint UClientHello
func realityClientFallback(uConn net.Conn, serverName string, fingerprint utls.ClientHelloID) { func realityClientFallback(uConn net.Conn, serverName string, fingerprint utls.ClientHelloID) {
defer uConn.Close() defer uConn.Close()
client := http.Client{ client := http.Client{
Transport: &http2.Transport{ Transport: &http.Http2Transport{
DialTLSContext: func(ctx context.Context, network, addr string, config *tls.Config) (net.Conn, error) { DialTLSContext: func(ctx context.Context, network, addr string, config *tls.Config) (net.Conn, error) {
return uConn, nil return uConn, nil
}, },

View File

@ -1,13 +1,13 @@
package tls package tls
import ( import (
"crypto/tls"
"net" "net"
"github.com/metacubex/mihomo/common/once" "github.com/metacubex/mihomo/common/once"
"github.com/metacubex/mihomo/common/utils" "github.com/metacubex/mihomo/common/utils"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/tls"
utls "github.com/metacubex/utls" utls "github.com/metacubex/utls"
"github.com/mroth/weightedrand/v2" "github.com/mroth/weightedrand/v2"
) )

View File

@ -6,7 +6,6 @@ import (
"context" "context"
"fmt" "fmt"
"io" "io"
"net/http"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@ -20,6 +19,8 @@ import (
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/constant/features" "github.com/metacubex/mihomo/constant/features"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/http"
) )
const ( const (

View File

@ -3,11 +3,12 @@ package updater
import ( import (
"context" "context"
"io" "io"
"net/http"
"os" "os"
"time" "time"
mihomoHttp "github.com/metacubex/mihomo/component/http" mihomoHttp "github.com/metacubex/mihomo/component/http"
"github.com/metacubex/http"
) )
const defaultHttpTimeout = time.Second * 90 const defaultHttpTimeout = time.Second * 90

View File

@ -2,7 +2,6 @@ package dns
import ( import (
"context" "context"
"crypto/tls"
"fmt" "fmt"
"net" "net"
"strings" "strings"
@ -12,6 +11,7 @@ import (
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/tls"
D "github.com/miekg/dns" D "github.com/miekg/dns"
) )

View File

@ -2,13 +2,11 @@ package dns
import ( import (
"context" "context"
"crypto/tls"
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"net" "net"
"net/http"
"net/url" "net/url"
"runtime" "runtime"
"strconv" "strconv"
@ -16,15 +14,15 @@ import (
"time" "time"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/http"
"github.com/metacubex/quic-go" "github.com/metacubex/quic-go"
"github.com/metacubex/quic-go/http3" "github.com/metacubex/quic-go/http3"
"github.com/metacubex/tls"
D "github.com/miekg/dns" D "github.com/miekg/dns"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"golang.org/x/net/http2"
) )
// Values to configure HTTP and HTTP/2 transport. // Values to configure HTTP and HTTP/2 transport.
@ -439,8 +437,8 @@ func (doh *dnsOverHTTPS) createTransport(ctx context.Context) (t http.RoundTripp
// Explicitly configure transport to use HTTP/2. // Explicitly configure transport to use HTTP/2.
// //
// See https://github.com/AdguardTeam/dnsproxy/issues/11. // See https://github.com/AdguardTeam/dnsproxy/issues/11.
var transportH2 *http2.Transport var transportH2 *http.Http2Transport
transportH2, err = http2.ConfigureTransports(transport) transportH2, err = http.Http2ConfigureTransports(transport)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -530,20 +528,20 @@ func (doh *dnsOverHTTPS) createTransportH3(
// Ignore the address and always connect to the one that we got // Ignore the address and always connect to the one that we got
// from the bootstrapper. // from the bootstrapper.
_ string, _ string,
tlsCfg *tlsC.Config, tlsCfg *tls.Config,
cfg *quic.Config, cfg *quic.Config,
) (c *quic.Conn, err error) { ) (c *quic.Conn, err error) {
return doh.dialQuic(ctx, addr, tlsCfg, cfg) return doh.dialQuic(ctx, addr, tlsCfg, cfg)
}, },
DisableCompression: true, DisableCompression: true,
TLSClientConfig: tlsC.UConfig(tlsConfig), TLSClientConfig: tlsConfig,
QUICConfig: doh.getQUICConfig(), QUICConfig: doh.getQUICConfig(),
} }
return &http3Transport{baseTransport: rt}, nil return &http3Transport{baseTransport: rt}, nil
} }
func (doh *dnsOverHTTPS) dialQuic(ctx context.Context, addr string, tlsCfg *tlsC.Config, cfg *quic.Config) (*quic.Conn, error) { func (doh *dnsOverHTTPS) dialQuic(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (*quic.Conn, error) {
ip, port, err := net.SplitHostPort(addr) ip, port, err := net.SplitHostPort(addr)
if err != nil { if err != nil {
return nil, err return nil, err
@ -612,7 +610,7 @@ func (doh *dnsOverHTTPS) probeH3(
// Run probeQUIC and probeTLS in parallel and see which one is faster. // Run probeQUIC and probeTLS in parallel and see which one is faster.
chQuic := make(chan error, 1) chQuic := make(chan error, 1)
chTLS := make(chan error, 1) chTLS := make(chan error, 1)
go doh.probeQUIC(ctx, addr, tlsC.UConfig(probeTLSCfg), chQuic) go doh.probeQUIC(ctx, addr, probeTLSCfg, chQuic)
go doh.probeTLS(ctx, probeTLSCfg, chTLS) go doh.probeTLS(ctx, probeTLSCfg, chTLS)
select { select {
@ -637,7 +635,7 @@ func (doh *dnsOverHTTPS) probeH3(
// probeQUIC attempts to establish a QUIC connection to the specified address. // probeQUIC attempts to establish a QUIC connection to the specified address.
// We run probeQUIC and probeTLS in parallel and see which one is faster. // We run probeQUIC and probeTLS in parallel and see which one is faster.
func (doh *dnsOverHTTPS) probeQUIC(ctx context.Context, addr string, tlsConfig *tlsC.Config, ch chan error) { func (doh *dnsOverHTTPS) probeQUIC(ctx context.Context, addr string, tlsConfig *tls.Config, ch chan error) {
startTime := time.Now() startTime := time.Now()
conn, err := doh.dialQuic(ctx, addr, tlsConfig, doh.getQUICConfig()) conn, err := doh.dialQuic(ctx, addr, tlsConfig, doh.getQUICConfig())
if err != nil { if err != nil {

View File

@ -2,7 +2,6 @@ package dns
import ( import (
"context" "context"
"crypto/tls"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
@ -13,11 +12,11 @@ import (
"time" "time"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/quic-go" "github.com/metacubex/quic-go"
"github.com/metacubex/tls"
D "github.com/miekg/dns" D "github.com/miekg/dns"
) )
@ -348,7 +347,7 @@ func (doq *dnsOverQUIC) openConnection(ctx context.Context) (conn *quic.Conn, er
transport := quic.Transport{Conn: udp} transport := quic.Transport{Conn: udp}
transport.SetCreatedConn(true) // auto close conn transport.SetCreatedConn(true) // auto close conn
transport.SetSingleUse(true) // auto close transport transport.SetSingleUse(true) // auto close transport
conn, err = transport.Dial(ctx, &udpAddr, tlsC.UConfig(tlsConfig), doq.getQUICConfig()) conn, err = transport.Dial(ctx, &udpAddr, tlsConfig, doq.getQUICConfig())
if err != nil { if err != nil {
return nil, fmt.Errorf("opening quic connection to %s: %w", doq.addr, err) return nil, fmt.Errorf("opening quic connection to %s: %w", doq.addr, err)
} }

22
go.mod
View File

@ -7,8 +7,6 @@ require (
github.com/coreos/go-iptables v0.8.0 github.com/coreos/go-iptables v0.8.0
github.com/dlclark/regexp2 v1.11.5 github.com/dlclark/regexp2 v1.11.5
github.com/enfein/mieru/v3 v3.26.0 github.com/enfein/mieru/v3 v3.26.0
github.com/go-chi/chi/v5 v5.2.3
github.com/go-chi/render v1.0.3
github.com/gobwas/ws v1.4.0 github.com/gobwas/ws v1.4.0
github.com/gofrs/uuid/v5 v5.4.0 github.com/gofrs/uuid/v5 v5.4.0
github.com/golang/snappy v1.0.0 github.com/golang/snappy v1.0.0
@ -20,15 +18,17 @@ require (
github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b
github.com/metacubex/blake3 v0.1.0 github.com/metacubex/blake3 v0.1.0
github.com/metacubex/chacha v0.1.5 github.com/metacubex/chacha v0.1.5
github.com/metacubex/chi v0.1.0
github.com/metacubex/fswatch v0.1.1 github.com/metacubex/fswatch v0.1.1
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
github.com/metacubex/http v0.1.0
github.com/metacubex/kcp-go v0.0.0-20251111012849-7455698490e9 github.com/metacubex/kcp-go v0.0.0-20251111012849-7455698490e9
github.com/metacubex/quic-go v0.55.1-0.20251203073212-6940cac967c2 github.com/metacubex/quic-go v0.57.1-0.20251217071004-e89f497a2e72
github.com/metacubex/randv2 v0.2.0 github.com/metacubex/randv2 v0.2.0
github.com/metacubex/restls-client-go v0.1.7 github.com/metacubex/restls-client-go v0.1.7
github.com/metacubex/sing v0.5.6 github.com/metacubex/sing v0.5.6
github.com/metacubex/sing-mux v0.3.4 github.com/metacubex/sing-mux v0.3.4
github.com/metacubex/sing-quic v0.0.0-20251004051927-c45ee18473bb github.com/metacubex/sing-quic v0.0.0-20251217080445-b15217cb57f3
github.com/metacubex/sing-shadowsocks v0.2.12 github.com/metacubex/sing-shadowsocks v0.2.12
github.com/metacubex/sing-shadowsocks2 v0.2.7 github.com/metacubex/sing-shadowsocks2 v0.2.7
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2
@ -37,6 +37,7 @@ require (
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f
github.com/metacubex/smux v0.0.0-20251111013112-03f8d12dafc1 github.com/metacubex/smux v0.0.0-20251111013112-03f8d12dafc1
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443 github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443
github.com/metacubex/tls v0.1.0
github.com/metacubex/utls v1.8.3 github.com/metacubex/utls v1.8.3
github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f
github.com/miekg/dns v1.1.63 // lastest version compatible with golang1.20 github.com/miekg/dns v1.1.63 // lastest version compatible with golang1.20
@ -44,7 +45,6 @@ require (
github.com/openacid/low v0.1.21 github.com/openacid/low v0.1.21
github.com/oschwald/maxminddb-golang v1.12.0 // lastest version compatible with golang1.20 github.com/oschwald/maxminddb-golang v1.12.0 // lastest version compatible with golang1.20
github.com/saba-futai/sudoku v0.0.2-d github.com/saba-futai/sudoku v0.0.2-d
github.com/sagernet/cors v1.2.1
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a
github.com/samber/lo v1.52.0 github.com/samber/lo v1.52.0
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
@ -78,12 +78,11 @@ require (
github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/gaukas/godicttls v0.0.4 // indirect github.com/gaukas/godicttls v0.0.4 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect github.com/gobwas/pool v0.2.1 // indirect
github.com/google/btree v1.1.3 // indirect github.com/google/btree v1.1.3 // indirect
github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
github.com/josharian/native v1.1.0 // indirect github.com/josharian/native v1.1.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/klauspost/reedsolomon v1.12.3 // indirect github.com/klauspost/reedsolomon v1.12.3 // indirect
@ -91,14 +90,17 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/mdlayher/socket v0.4.1 // indirect github.com/mdlayher/socket v0.4.1 // indirect
github.com/metacubex/ascon v0.1.0 // indirect github.com/metacubex/ascon v0.1.0 // indirect
github.com/metacubex/cpu v0.1.0 // indirect
github.com/metacubex/gvisor v0.0.0-20250919004547-6122b699a301 // indirect github.com/metacubex/gvisor v0.0.0-20250919004547-6122b699a301 // indirect
github.com/metacubex/hkdf v0.1.0 // indirect
github.com/metacubex/hpke v0.1.0 // indirect
github.com/metacubex/mlkem v0.1.0 // indirect
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect
github.com/metacubex/qpack v0.6.0 // indirect
github.com/metacubex/yamux v0.0.0-20250918083631-dd5f17c0be49 // indirect github.com/metacubex/yamux v0.0.0-20250918083631-dd5f17c0be49 // indirect
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
github.com/pierrec/lz4/v4 v4.1.14 // indirect github.com/pierrec/lz4/v4 v4.1.14 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect
github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c // indirect github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c // indirect
github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e // indirect github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e // indirect
@ -108,6 +110,6 @@ require (
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect
golang.org/x/mod v0.20.0 // indirect golang.org/x/mod v0.20.0 // indirect
golang.org/x/text v0.22.0 // indirect golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.7.0 // indirect golang.org/x/time v0.10.0 // indirect
golang.org/x/tools v0.24.0 // indirect golang.org/x/tools v0.24.0 // indirect
) )

52
go.sum
View File

@ -14,9 +14,6 @@ github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xW
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/coreos/go-iptables v0.8.0 h1:MPc2P89IhuVpLI7ETL/2tx3XZ61VeICZjYqDEgNsPRc= github.com/coreos/go-iptables v0.8.0 h1:MPc2P89IhuVpLI7ETL/2tx3XZ61VeICZjYqDEgNsPRc=
github.com/coreos/go-iptables v0.8.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= github.com/coreos/go-iptables v0.8.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@ -40,15 +37,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
@ -58,17 +48,15 @@ github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakr
github.com/gofrs/uuid/v5 v5.4.0 h1:EfbpCTjqMuGyq5ZJwxqzn3Cbr2d0rUZU7v5ycAk/e/0= github.com/gofrs/uuid/v5 v5.4.0 h1:EfbpCTjqMuGyq5ZJwxqzn3Cbr2d0rUZU7v5ycAk/e/0=
github.com/gofrs/uuid/v5 v5.4.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/gofrs/uuid/v5 v5.4.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I= github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 h1:q3OEI9RaN/wwcx+qgGo6ZaoJkCiDYe/gjDLfq7lQQF4= github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 h1:q3OEI9RaN/wwcx+qgGo6ZaoJkCiDYe/gjDLfq7lQQF4=
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905/go.mod h1:VvGYjkZoJyKqlmT1yzakUs4mfKMNB0XdODP0+rdml6k= github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905/go.mod h1:VvGYjkZoJyKqlmT1yzakUs4mfKMNB0XdODP0+rdml6k=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
@ -102,18 +90,32 @@ github.com/metacubex/blake3 v0.1.0 h1:KGnjh/56REO7U+cgZA8dnBhxdP7jByrG7hTP+bu6cq
github.com/metacubex/blake3 v0.1.0/go.mod h1:CCkLdzFrqf7xmxCdhQFvJsRRV2mwOLDoSPg6vUTB9Uk= github.com/metacubex/blake3 v0.1.0/go.mod h1:CCkLdzFrqf7xmxCdhQFvJsRRV2mwOLDoSPg6vUTB9Uk=
github.com/metacubex/chacha v0.1.5 h1:fKWMb/5c7ZrY8Uoqi79PPFxl+qwR7X/q0OrsAubyX2M= github.com/metacubex/chacha v0.1.5 h1:fKWMb/5c7ZrY8Uoqi79PPFxl+qwR7X/q0OrsAubyX2M=
github.com/metacubex/chacha v0.1.5/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8= github.com/metacubex/chacha v0.1.5/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
github.com/metacubex/chi v0.1.0 h1:rjNDyDj50nRpicG43CNkIw4ssiCbmDL8d7wJXKlUCsg=
github.com/metacubex/chi v0.1.0/go.mod h1:zM5u5oMQt8b2DjvDHvzadKrP6B2ztmasL1YHRMbVV+g=
github.com/metacubex/cpu v0.1.0 h1:8PeTdV9j6UKbN1K5Jvtbi/Jock7dknvzyYuLb8Conmk=
github.com/metacubex/cpu v0.1.0/go.mod h1:09VEt4dSRLR+bOA8l4w4NDuzGZ8n5dkMv7e8axgEeTU=
github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQuxhU= github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQuxhU=
github.com/metacubex/fswatch v0.1.1/go.mod h1:czrTT7Zlbz7vWft8RQu9Qqh+JoX+Nnb+UabuyN1YsgI= github.com/metacubex/fswatch v0.1.1/go.mod h1:czrTT7Zlbz7vWft8RQu9Qqh+JoX+Nnb+UabuyN1YsgI=
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI=
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88=
github.com/metacubex/gvisor v0.0.0-20250919004547-6122b699a301 h1:N5GExQJqYAH3gOCshpp2u/J3CtNYzMctmlb0xK9wtbQ= github.com/metacubex/gvisor v0.0.0-20250919004547-6122b699a301 h1:N5GExQJqYAH3gOCshpp2u/J3CtNYzMctmlb0xK9wtbQ=
github.com/metacubex/gvisor v0.0.0-20250919004547-6122b699a301/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU= github.com/metacubex/gvisor v0.0.0-20250919004547-6122b699a301/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU=
github.com/metacubex/hkdf v0.1.0 h1:fPA6VzXK8cU1foc/TOmGCDmSa7pZbxlnqhl3RNsthaA=
github.com/metacubex/hkdf v0.1.0/go.mod h1:3seEfds3smgTAXqUGn+tgEJH3uXdsUjOiduG/2EtvZ4=
github.com/metacubex/hpke v0.1.0 h1:gu2jUNhraehWi0P/z5HX2md3d7L1FhPQE6/Q0E9r9xQ=
github.com/metacubex/hpke v0.1.0/go.mod h1:vfDm6gfgrwlXUxKDkWbcE44hXtmc1uxLDm2BcR11b3U=
github.com/metacubex/http v0.1.0 h1:Jcy0I9zKjYijSUaksZU34XEe2xNdoFkgUTB7z7K5q0o=
github.com/metacubex/http v0.1.0/go.mod h1:Nxx0zZAo2AhRfanyL+fmmK6ACMtVsfpwIl1aFAik2Eg=
github.com/metacubex/kcp-go v0.0.0-20251111012849-7455698490e9 h1:7m3tRPrLpKOLOvZ/Lp4XCxz0t7rg9t9K35x6TahjR8o= github.com/metacubex/kcp-go v0.0.0-20251111012849-7455698490e9 h1:7m3tRPrLpKOLOvZ/Lp4XCxz0t7rg9t9K35x6TahjR8o=
github.com/metacubex/kcp-go v0.0.0-20251111012849-7455698490e9/go.mod h1:HIJZW4QMhbBqXuqC1ly6Hn0TEYT2SzRw58ns1yGhXTs= github.com/metacubex/kcp-go v0.0.0-20251111012849-7455698490e9/go.mod h1:HIJZW4QMhbBqXuqC1ly6Hn0TEYT2SzRw58ns1yGhXTs=
github.com/metacubex/mlkem v0.1.0 h1:wFClitonSFcmipzzQvax75beLQU+D7JuC+VK1RzSL8I=
github.com/metacubex/mlkem v0.1.0/go.mod h1:amhaXZVeYNShuy9BILcR7P0gbeo/QLZsnqCdL8U2PDQ=
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo=
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA=
github.com/metacubex/quic-go v0.55.1-0.20251203073212-6940cac967c2 h1:21KrRBqF5en0yXwwb5Vpptbeiiu3p7gD0G+RqNYvsvw= github.com/metacubex/qpack v0.6.0 h1:YqClGIMOpiRYLjV1qOs483Od08MdPgRnHjt90FuaAKw=
github.com/metacubex/quic-go v0.55.1-0.20251203073212-6940cac967c2/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c= github.com/metacubex/qpack v0.6.0/go.mod h1:lKGSi7Xk94IMvHGOmxS9eIei3bvIqpOAImEBsaOwTkA=
github.com/metacubex/quic-go v0.57.1-0.20251217071004-e89f497a2e72 h1:kNlYHZ75itJwkerDiySpixX+dKsv/K0TYQsKvuxogNM=
github.com/metacubex/quic-go v0.57.1-0.20251217071004-e89f497a2e72/go.mod h1:N071X2oW2+kIhLlHW3mfcD2QP+zWu2bEs1EEAm66bvI=
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs= github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY= github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k= github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k=
@ -123,8 +125,8 @@ github.com/metacubex/sing v0.5.6 h1:mEPDCadsCj3DB8gn+t/EtposlYuALEkExa/LUguw6/c=
github.com/metacubex/sing v0.5.6/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= github.com/metacubex/sing v0.5.6/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=
github.com/metacubex/sing-mux v0.3.4 h1:tf4r27CIkzaxq9kBlAXQkgMXq2HPp5Mta60Kb4RCZF0= github.com/metacubex/sing-mux v0.3.4 h1:tf4r27CIkzaxq9kBlAXQkgMXq2HPp5Mta60Kb4RCZF0=
github.com/metacubex/sing-mux v0.3.4/go.mod h1:SEJfAuykNj/ozbPqngEYqyggwSr81+L7Nu09NRD5mh4= github.com/metacubex/sing-mux v0.3.4/go.mod h1:SEJfAuykNj/ozbPqngEYqyggwSr81+L7Nu09NRD5mh4=
github.com/metacubex/sing-quic v0.0.0-20251004051927-c45ee18473bb h1:gxrJmnxuEAel+kh3V7ntqkHjURif0xKDu76nzr/BF5Y= github.com/metacubex/sing-quic v0.0.0-20251217080445-b15217cb57f3 h1:3LlkguIRAzyBWLxP5xrETi1AMIt3McZcDlXNgiyXMsE=
github.com/metacubex/sing-quic v0.0.0-20251004051927-c45ee18473bb/go.mod h1:JK4+PYUKps6pnlicKjsSUAjAcvIUjhorIjdNZGg930M= github.com/metacubex/sing-quic v0.0.0-20251217080445-b15217cb57f3/go.mod h1:fAyoc/8IFK1yJp8meJvPNyGk7ZnKG1vmNaTwYx6NHA4=
github.com/metacubex/sing-shadowsocks v0.2.12 h1:Wqzo8bYXrK5aWqxu/TjlTnYZzAKtKsaFQBdr6IHFaBE= github.com/metacubex/sing-shadowsocks v0.2.12 h1:Wqzo8bYXrK5aWqxu/TjlTnYZzAKtKsaFQBdr6IHFaBE=
github.com/metacubex/sing-shadowsocks v0.2.12/go.mod h1:2e5EIaw0rxKrm1YTRmiMnDulwbGxH9hAFlrwQLQMQkU= github.com/metacubex/sing-shadowsocks v0.2.12/go.mod h1:2e5EIaw0rxKrm1YTRmiMnDulwbGxH9hAFlrwQLQMQkU=
github.com/metacubex/sing-shadowsocks2 v0.2.7 h1:hSuuc0YpsfiqYqt1o+fP4m34BQz4e6wVj3PPBVhor3A= github.com/metacubex/sing-shadowsocks2 v0.2.7 h1:hSuuc0YpsfiqYqt1o+fP4m34BQz4e6wVj3PPBVhor3A=
@ -141,6 +143,8 @@ github.com/metacubex/smux v0.0.0-20251111013112-03f8d12dafc1 h1:a6DF0ze9miXes+rd
github.com/metacubex/smux v0.0.0-20251111013112-03f8d12dafc1/go.mod h1:4bPD8HWx9jPJ9aE4uadgyN7D1/Wz3KmPy+vale8sKLE= github.com/metacubex/smux v0.0.0-20251111013112-03f8d12dafc1/go.mod h1:4bPD8HWx9jPJ9aE4uadgyN7D1/Wz3KmPy+vale8sKLE=
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443 h1:H6TnfM12tOoTizYE/qBHH3nEuibIelmHI+BVSxVJr8o= github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443 h1:H6TnfM12tOoTizYE/qBHH3nEuibIelmHI+BVSxVJr8o=
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
github.com/metacubex/tls v0.1.0 h1:1kjR/1q2uU1cZIwiHYEnWzS4L+0Cu1/X3yfIQ76BzNY=
github.com/metacubex/tls v0.1.0/go.mod h1:0XeVdL0cBw+8i5Hqy3lVeP9IyD/LFTq02ExvHM6rzEM=
github.com/metacubex/utls v1.8.3 h1:0m/yCxm3SK6kWve2lKiFb1pue1wHitJ8sQQD4Ikqde4= github.com/metacubex/utls v1.8.3 h1:0m/yCxm3SK6kWve2lKiFb1pue1wHitJ8sQQD4Ikqde4=
github.com/metacubex/utls v1.8.3/go.mod h1:kncGGVhFaoGn5M3pFe3SXhZCzsbCJayNOH4UEqTKTko= github.com/metacubex/utls v1.8.3/go.mod h1:kncGGVhFaoGn5M3pFe3SXhZCzsbCJayNOH4UEqTKTko=
github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f h1:FGBPRb1zUabhPhDrlKEjQ9lgIwQ6cHL4x8M9lrERhbk= github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f h1:FGBPRb1zUabhPhDrlKEjQ9lgIwQ6cHL4x8M9lrERhbk=
@ -153,9 +157,6 @@ github.com/mroth/weightedrand/v2 v2.1.0 h1:o1ascnB1CIVzsqlfArQQjeMy1U0NcIbBO5rfd
github.com/mroth/weightedrand/v2 v2.1.0/go.mod h1:f2faGsfOGOwc1p94wzHKKZyTpcJUW7OJ/9U4yfiNAOU= github.com/mroth/weightedrand/v2 v2.1.0/go.mod h1:f2faGsfOGOwc1p94wzHKKZyTpcJUW7OJ/9U4yfiNAOU=
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 h1:1102pQc2SEPp5+xrS26wEaeb26sZy6k9/ZXlZN+eXE4= github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 h1:1102pQc2SEPp5+xrS26wEaeb26sZy6k9/ZXlZN+eXE4=
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7/go.mod h1:UqoUn6cHESlliMhOnKLWr+CBH+e3bazUPvFj1XZwAjs= github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7/go.mod h1:UqoUn6cHESlliMhOnKLWr+CBH+e3bazUPvFj1XZwAjs=
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/openacid/errors v0.8.1/go.mod h1:GUQEJJOJE3W9skHm8E8Y4phdl2LLEN8iD7c5gcGgdx0= github.com/openacid/errors v0.8.1/go.mod h1:GUQEJJOJE3W9skHm8E8Y4phdl2LLEN8iD7c5gcGgdx0=
github.com/openacid/low v0.1.21 h1:Tr2GNu4N/+rGRYdOsEHOE89cxUIaDViZbVmKz29uKGo= github.com/openacid/low v0.1.21 h1:Tr2GNu4N/+rGRYdOsEHOE89cxUIaDViZbVmKz29uKGo=
github.com/openacid/low v0.1.21/go.mod h1:q+MsKI6Pz2xsCkzV4BLj7NR5M4EX0sGz5AqotpZDVh0= github.com/openacid/low v0.1.21/go.mod h1:q+MsKI6Pz2xsCkzV4BLj7NR5M4EX0sGz5AqotpZDVh0=
@ -169,12 +170,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/saba-futai/sudoku v0.0.2-d h1:HW/gIyNUFcDchpMN+ZhluM86U/HGkWkkRV+9Km6WZM8= github.com/saba-futai/sudoku v0.0.2-d h1:HW/gIyNUFcDchpMN+ZhluM86U/HGkWkkRV+9Km6WZM8=
github.com/saba-futai/sudoku v0.0.2-d/go.mod h1:Rvggsoprp7HQM7bMIZUd1M27bPj8THRsZdY1dGbIAvo= github.com/saba-futai/sudoku v0.0.2-d/go.mod h1:Rvggsoprp7HQM7bMIZUd1M27bPj8THRsZdY1dGbIAvo=
github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ=
github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI=
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis= github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis=
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw=
@ -244,7 +241,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -258,8 +254,8 @@ golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=

View File

@ -1,12 +1,11 @@
package route package route
import ( import (
"net/http"
"github.com/metacubex/mihomo/component/resolver" "github.com/metacubex/mihomo/component/resolver"
"github.com/go-chi/chi/v5" "github.com/metacubex/chi"
"github.com/go-chi/render" "github.com/metacubex/chi/render"
"github.com/metacubex/http"
) )
func cacheRouter() http.Handler { func cacheRouter() http.Handler {

View File

@ -6,14 +6,15 @@ import (
"errors" "errors"
"io" "io"
"net" "net"
"net/http"
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/go-chi/chi/v5"
N "github.com/metacubex/mihomo/common/net" N "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/chi"
"github.com/metacubex/http"
) )
// When name is composed of a partial escape string, Golang does not unescape it // When name is composed of a partial escape string, Golang does not unescape it

View File

@ -1,7 +1,6 @@
package route package route
import ( import (
"net/http"
"net/netip" "net/netip"
"path/filepath" "path/filepath"
@ -18,8 +17,9 @@ import (
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/mihomo/tunnel" "github.com/metacubex/mihomo/tunnel"
"github.com/go-chi/chi/v5" "github.com/metacubex/chi"
"github.com/go-chi/render" "github.com/metacubex/chi/render"
"github.com/metacubex/http"
) )
func configRouter() http.Handler { func configRouter() http.Handler {

View File

@ -3,14 +3,14 @@ package route
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"net/http"
"strconv" "strconv"
"time" "time"
"github.com/metacubex/mihomo/tunnel/statistic" "github.com/metacubex/mihomo/tunnel/statistic"
"github.com/go-chi/chi/v5" "github.com/metacubex/chi"
"github.com/go-chi/render" "github.com/metacubex/chi/render"
"github.com/metacubex/http"
) )
func connectionRouter() http.Handler { func connectionRouter() http.Handler {

View File

@ -3,12 +3,12 @@ package route
import ( import (
"context" "context"
"math" "math"
"net/http"
"github.com/metacubex/mihomo/component/resolver" "github.com/metacubex/mihomo/component/resolver"
"github.com/go-chi/chi/v5" "github.com/metacubex/chi"
"github.com/go-chi/render" "github.com/metacubex/chi/render"
"github.com/metacubex/http"
"github.com/miekg/dns" "github.com/miekg/dns"
"github.com/samber/lo" "github.com/samber/lo"
) )

View File

@ -4,11 +4,11 @@ import (
"context" "context"
"encoding/base64" "encoding/base64"
"io" "io"
"net/http"
"github.com/metacubex/mihomo/component/resolver" "github.com/metacubex/mihomo/component/resolver"
"github.com/go-chi/render" "github.com/metacubex/chi/render"
"github.com/metacubex/http"
) )
func dohRouter() http.Handler { func dohRouter() http.Handler {

View File

@ -1,6 +1,6 @@
package route package route
import "github.com/go-chi/chi/v5" import "github.com/metacubex/chi"
type externalRouter func(r chi.Router) type externalRouter func(r chi.Router)

View File

@ -2,18 +2,18 @@ package route
import ( import (
"context" "context"
"net/http"
"strconv" "strconv"
"time" "time"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"github.com/metacubex/mihomo/adapter/outboundgroup" "github.com/metacubex/mihomo/adapter/outboundgroup"
"github.com/metacubex/mihomo/common/utils" "github.com/metacubex/mihomo/common/utils"
"github.com/metacubex/mihomo/component/profile/cachefile" "github.com/metacubex/mihomo/component/profile/cachefile"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/tunnel" "github.com/metacubex/mihomo/tunnel"
"github.com/metacubex/chi"
"github.com/metacubex/chi/render"
"github.com/metacubex/http"
) )
func groupRouter() http.Handler { func groupRouter() http.Handler {

View File

@ -2,14 +2,14 @@ package route
import ( import (
"context" "context"
"net/http"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
P "github.com/metacubex/mihomo/constant/provider" P "github.com/metacubex/mihomo/constant/provider"
"github.com/metacubex/mihomo/tunnel" "github.com/metacubex/mihomo/tunnel"
"github.com/go-chi/chi/v5" "github.com/metacubex/chi"
"github.com/go-chi/render" "github.com/metacubex/chi/render"
"github.com/metacubex/http"
"github.com/samber/lo" "github.com/samber/lo"
) )

View File

@ -3,7 +3,6 @@ package route
import ( import (
"context" "context"
"fmt" "fmt"
"net/http"
"strconv" "strconv"
"time" "time"
@ -13,8 +12,9 @@ import (
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/tunnel" "github.com/metacubex/mihomo/tunnel"
"github.com/go-chi/chi/v5" "github.com/metacubex/chi"
"github.com/go-chi/render" "github.com/metacubex/chi/render"
"github.com/metacubex/http"
) )
var ( var (

View File

@ -2,7 +2,6 @@ package route
import ( import (
"fmt" "fmt"
"net/http"
"os" "os"
"os/exec" "os/exec"
"runtime" "runtime"
@ -11,8 +10,9 @@ import (
"github.com/metacubex/mihomo/hub/executor" "github.com/metacubex/mihomo/hub/executor"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/go-chi/chi/v5" "github.com/metacubex/chi"
"github.com/go-chi/render" "github.com/metacubex/chi/render"
"github.com/metacubex/http"
) )
func restartRouter() http.Handler { func restartRouter() http.Handler {

View File

@ -2,12 +2,11 @@ package route
import ( import (
"github.com/metacubex/mihomo/constant" "github.com/metacubex/mihomo/constant"
"net/http"
"github.com/metacubex/mihomo/tunnel" "github.com/metacubex/mihomo/tunnel"
"github.com/go-chi/chi/v5" "github.com/metacubex/chi"
"github.com/go-chi/render" "github.com/metacubex/chi/render"
"github.com/metacubex/http"
) )
func ruleRouter() http.Handler { func ruleRouter() http.Handler {

View File

@ -5,7 +5,6 @@ import (
"crypto/subtle" "crypto/subtle"
"encoding/json" "encoding/json"
"net" "net"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"runtime/debug" "runtime/debug"
@ -17,16 +16,17 @@ import (
"github.com/metacubex/mihomo/common/utils" "github.com/metacubex/mihomo/common/utils"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/mihomo/ntp" "github.com/metacubex/mihomo/ntp"
"github.com/metacubex/mihomo/tunnel/statistic" "github.com/metacubex/mihomo/tunnel/statistic"
"github.com/go-chi/chi/v5" "github.com/metacubex/chi"
"github.com/go-chi/chi/v5/middleware" "github.com/metacubex/chi/cors"
"github.com/go-chi/render" "github.com/metacubex/chi/middleware"
"github.com/sagernet/cors" "github.com/metacubex/chi/render"
"github.com/metacubex/http"
"github.com/metacubex/tls"
) )
var ( var (
@ -204,16 +204,16 @@ func startTLS(cfg *Config) {
} }
log.Infoln("RESTful API tls listening at: %s", l.Addr().String()) log.Infoln("RESTful API tls listening at: %s", l.Addr().String())
tlsConfig := &tlsC.Config{Time: ntp.Now} tlsConfig := &tls.Config{Time: ntp.Now}
tlsConfig.NextProtos = []string{"h2", "http/1.1"} tlsConfig.NextProtos = []string{"h2", "http/1.1"}
tlsConfig.Certificates = []tlsC.Certificate{tlsC.UCertificate(cert)} tlsConfig.Certificates = []tls.Certificate{cert}
tlsConfig.ClientAuth = tlsC.ClientAuthTypeFromString(cfg.ClientAuthType) tlsConfig.ClientAuth = ca.ClientAuthTypeFromString(cfg.ClientAuthType)
if len(cfg.ClientAuthCert) > 0 { if len(cfg.ClientAuthCert) > 0 {
if tlsConfig.ClientAuth == tlsC.NoClientCert { if tlsConfig.ClientAuth == tls.NoClientCert {
tlsConfig.ClientAuth = tlsC.RequireAndVerifyClientCert tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
} }
} }
if tlsConfig.ClientAuth == tlsC.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tlsC.RequireAndVerifyClientCert { if tlsConfig.ClientAuth == tls.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tls.RequireAndVerifyClientCert {
pool, err := ca.LoadCertificates(cfg.ClientAuthCert, C.Path) pool, err := ca.LoadCertificates(cfg.ClientAuthCert, C.Path)
if err != nil { if err != nil {
log.Errorln("External controller tls listen error: %s", err) log.Errorln("External controller tls listen error: %s", err)
@ -233,7 +233,7 @@ func startTLS(cfg *Config) {
Handler: router(cfg.IsDebug, cfg.Secret, cfg.DohServer, cfg.Cors), Handler: router(cfg.IsDebug, cfg.Secret, cfg.DohServer, cfg.Cors),
} }
tlsServer = server tlsServer = server
if err = server.Serve(tlsC.NewListenerForHttps(l, server, tlsConfig)); err != nil { if err = server.Serve(tls.NewListener(l, tlsConfig)); err != nil {
log.Errorln("External controller tls serve error: %s", err) log.Errorln("External controller tls serve error: %s", err)
} }
} }

View File

@ -2,14 +2,14 @@ package route
import ( import (
"fmt" "fmt"
"net/http"
"os" "os"
"github.com/metacubex/mihomo/component/updater" "github.com/metacubex/mihomo/component/updater"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/go-chi/chi/v5" "github.com/metacubex/chi"
"github.com/go-chi/render" "github.com/metacubex/chi/render"
"github.com/metacubex/http"
) )
func upgradeRouter() http.Handler { func upgradeRouter() http.Handler {

View File

@ -13,7 +13,6 @@ import (
"github.com/metacubex/mihomo/common/buf" "github.com/metacubex/mihomo/common/buf"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/sing" "github.com/metacubex/mihomo/listener/sing"
@ -24,13 +23,14 @@ import (
"github.com/metacubex/sing/common/auth" "github.com/metacubex/sing/common/auth"
"github.com/metacubex/sing/common/bufio" "github.com/metacubex/sing/common/bufio"
M "github.com/metacubex/sing/common/metadata" M "github.com/metacubex/sing/common/metadata"
"github.com/metacubex/tls"
) )
type Listener struct { type Listener struct {
closed bool closed bool
config LC.AnyTLSServer config LC.AnyTLSServer
listeners []net.Listener listeners []net.Listener
tlsConfig *tlsC.Config tlsConfig *tls.Config
userMap map[[32]byte]string userMap map[[32]byte]string
padding atomic.Pointer[padding.PaddingFactory] padding atomic.Pointer[padding.PaddingFactory]
} }
@ -43,13 +43,13 @@ func New(config LC.AnyTLSServer, tunnel C.Tunnel, additions ...inbound.Addition)
} }
} }
tlsConfig := &tlsC.Config{Time: ntp.Now} tlsConfig := &tls.Config{Time: ntp.Now}
if config.Certificate != "" && config.PrivateKey != "" { if config.Certificate != "" && config.PrivateKey != "" {
cert, err := ca.LoadTLSKeyPair(config.Certificate, config.PrivateKey, C.Path) cert, err := ca.LoadTLSKeyPair(config.Certificate, config.PrivateKey, C.Path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
tlsConfig.Certificates = []tlsC.Certificate{tlsC.UCertificate(cert)} tlsConfig.Certificates = []tls.Certificate{cert}
if config.EchKey != "" { if config.EchKey != "" {
err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path) err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path)
@ -58,13 +58,13 @@ func New(config LC.AnyTLSServer, tunnel C.Tunnel, additions ...inbound.Addition)
} }
} }
} }
tlsConfig.ClientAuth = tlsC.ClientAuthTypeFromString(config.ClientAuthType) tlsConfig.ClientAuth = ca.ClientAuthTypeFromString(config.ClientAuthType)
if len(config.ClientAuthCert) > 0 { if len(config.ClientAuthCert) > 0 {
if tlsConfig.ClientAuth == tlsC.NoClientCert { if tlsConfig.ClientAuth == tls.NoClientCert {
tlsConfig.ClientAuth = tlsC.RequireAndVerifyClientCert tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
} }
} }
if tlsConfig.ClientAuth == tlsC.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tlsC.RequireAndVerifyClientCert { if tlsConfig.ClientAuth == tls.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tls.RequireAndVerifyClientCert {
pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path) pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -109,7 +109,7 @@ func New(config LC.AnyTLSServer, tunnel C.Tunnel, additions ...inbound.Addition)
return nil, err return nil, err
} }
if len(tlsConfig.Certificates) > 0 { if len(tlsConfig.Certificates) > 0 {
l = tlsC.NewListener(l, tlsConfig) l = tls.NewListener(l, tlsConfig)
} else { } else {
return nil, errors.New("disallow using AnyTLS without certificates config") return nil, errors.New("disallow using AnyTLS without certificates config")
} }

View File

@ -4,13 +4,14 @@ import (
"context" "context"
"errors" "errors"
"net" "net"
"net/http"
"time" "time"
"github.com/metacubex/mihomo/adapter/inbound" "github.com/metacubex/mihomo/adapter/inbound"
N "github.com/metacubex/mihomo/common/net" N "github.com/metacubex/mihomo/common/net"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/transport/socks5" "github.com/metacubex/mihomo/transport/socks5"
"github.com/metacubex/http"
) )
func newClient(srcConn net.Conn, tunnel C.Tunnel, additions []inbound.Addition) *http.Client { // additions using slice let caller can change its value (without size) after newClient return func newClient(srcConn net.Conn, tunnel C.Tunnel, additions []inbound.Addition) *http.Client { // additions using slice let caller can change its value (without size) after newClient return

View File

@ -2,9 +2,10 @@ package http
import ( import (
"bufio" "bufio"
"net/http"
_ "unsafe" _ "unsafe"
"github.com/metacubex/http"
) )
//go:linkname ReadRequest net/http.readRequest //go:linkname ReadRequest github.com/metacubex/http.readRequest
func ReadRequest(b *bufio.Reader) (req *http.Request, err error) func ReadRequest(b *bufio.Reader) (req *http.Request, err error)

View File

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"io" "io"
"net" "net"
"net/http"
"strings" "strings"
"sync" "sync"
@ -14,6 +13,8 @@ import (
"github.com/metacubex/mihomo/component/auth" "github.com/metacubex/mihomo/component/auth"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/http"
) )
type bodyWrapper struct { type bodyWrapper struct {

View File

@ -7,12 +7,13 @@ import (
"github.com/metacubex/mihomo/adapter/inbound" "github.com/metacubex/mihomo/adapter/inbound"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
authStore "github.com/metacubex/mihomo/listener/auth" authStore "github.com/metacubex/mihomo/listener/auth"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/reality" "github.com/metacubex/mihomo/listener/reality"
"github.com/metacubex/mihomo/ntp" "github.com/metacubex/mihomo/ntp"
"github.com/metacubex/tls"
) )
type Listener struct { type Listener struct {
@ -66,7 +67,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
return nil, err return nil, err
} }
tlsConfig := &tlsC.Config{Time: ntp.Now} tlsConfig := &tls.Config{Time: ntp.Now}
var realityBuilder *reality.Builder var realityBuilder *reality.Builder
if config.Certificate != "" && config.PrivateKey != "" { if config.Certificate != "" && config.PrivateKey != "" {
@ -74,7 +75,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
if err != nil { if err != nil {
return nil, err return nil, err
} }
tlsConfig.Certificates = []tlsC.Certificate{tlsC.UCertificate(cert)} tlsConfig.Certificates = []tls.Certificate{cert}
if config.EchKey != "" { if config.EchKey != "" {
err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path) err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path)
@ -83,13 +84,13 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
} }
} }
} }
tlsConfig.ClientAuth = tlsC.ClientAuthTypeFromString(config.ClientAuthType) tlsConfig.ClientAuth = ca.ClientAuthTypeFromString(config.ClientAuthType)
if len(config.ClientAuthCert) > 0 { if len(config.ClientAuthCert) > 0 {
if tlsConfig.ClientAuth == tlsC.NoClientCert { if tlsConfig.ClientAuth == tls.NoClientCert {
tlsConfig.ClientAuth = tlsC.RequireAndVerifyClientCert tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
} }
} }
if tlsConfig.ClientAuth == tlsC.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tlsC.RequireAndVerifyClientCert { if tlsConfig.ClientAuth == tls.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tls.RequireAndVerifyClientCert {
pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path) pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -100,7 +101,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
if tlsConfig.Certificates != nil { if tlsConfig.Certificates != nil {
return nil, errors.New("certificate is unavailable in reality") return nil, errors.New("certificate is unavailable in reality")
} }
if tlsConfig.ClientAuth != tlsC.NoClientCert { if tlsConfig.ClientAuth != tls.NoClientCert {
return nil, errors.New("client-auth is unavailable in reality") return nil, errors.New("client-auth is unavailable in reality")
} }
realityBuilder, err = config.RealityConfig.Build(tunnel) realityBuilder, err = config.RealityConfig.Build(tunnel)
@ -112,7 +113,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
if realityBuilder != nil { if realityBuilder != nil {
l = realityBuilder.NewListener(l) l = realityBuilder.NewListener(l)
} else if len(tlsConfig.Certificates) > 0 { } else if len(tlsConfig.Certificates) > 0 {
l = tlsC.NewListener(l, tlsConfig) l = tls.NewListener(l, tlsConfig)
} }
hl := &Listener{ hl := &Listener{

View File

@ -2,15 +2,16 @@ package http
import ( import (
"context" "context"
"crypto/tls"
"net" "net"
"net/http"
"strings" "strings"
"github.com/metacubex/mihomo/adapter/inbound" "github.com/metacubex/mihomo/adapter/inbound"
N "github.com/metacubex/mihomo/common/net" N "github.com/metacubex/mihomo/common/net"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/transport/socks5" "github.com/metacubex/mihomo/transport/socks5"
"github.com/metacubex/http"
"github.com/metacubex/tls"
) )
func isUpgradeRequest(req *http.Request) bool { func isUpgradeRequest(req *http.Request) bool {

View File

@ -4,9 +4,10 @@ import (
"encoding/base64" "encoding/base64"
"errors" "errors"
"net" "net"
"net/http"
"net/netip" "net/netip"
"strings" "strings"
"github.com/metacubex/http"
) )
// removeHopByHopHeaders remove Proxy-* headers // removeHopByHopHeaders remove Proxy-* headers

View File

@ -4,12 +4,10 @@ import (
"bytes" "bytes"
"context" "context"
"crypto/rand" "crypto/rand"
"crypto/tls"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"io" "io"
"net" "net"
"net/http"
"net/netip" "net/netip"
"strconv" "strconv"
"sync" "sync"
@ -23,13 +21,13 @@ import (
"github.com/metacubex/mihomo/component/dialer" "github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
"github.com/metacubex/mihomo/component/generator" "github.com/metacubex/mihomo/component/generator"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/go-chi/chi/v5" "github.com/metacubex/chi"
"github.com/go-chi/render" "github.com/metacubex/chi/render"
"github.com/metacubex/http"
"github.com/metacubex/tls"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"golang.org/x/net/http2"
) )
var httpPath = "/inbound_test" var httpPath = "/inbound_test"
@ -157,9 +155,9 @@ func NewHttpTestTunnel() *TestTunnel {
io.Copy(io.Discard, r.Body) io.Copy(io.Discard, r.Body)
render.Data(w, r, httpData[:size]) render.Data(w, r, httpData[:size])
}) })
h2Server := &http2.Server{} h2Server := &http.Http2Server{}
server := http.Server{Handler: r} server := http.Server{Handler: r}
_ = http2.ConfigureServer(&server, h2Server) _ = http.Http2ConfigureServer(&server, h2Server)
go server.Serve(ln) go server.Serve(ln)
testFn := func(t *testing.T, proxy C.ProxyAdapter, proto string, size int) { testFn := func(t *testing.T, proxy C.ProxyAdapter, proto string, size int) {
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s://%s%s?size=%d", proto, remoteAddr, httpPath, size), bytes.NewReader(httpData[:size])) req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s://%s%s?size=%d", proto, remoteAddr, httpPath, size), bytes.NewReader(httpData[:size]))
@ -268,7 +266,7 @@ func NewHttpTestTunnel() *TestTunnel {
ch: make(chan struct{}), ch: make(chan struct{}),
} }
if metadata.DstPort == 443 { if metadata.DstPort == 443 {
tlsConn := tlsC.Server(c, tlsC.UConfig(tlsConfig)) tlsConn := tls.Server(c, tlsConfig)
if metadata.Host == realityDest { // ignore the tls handshake error for realityDest if metadata.Host == realityDest { // ignore the tls handshake error for realityDest
if realityRealDial { if realityRealDial {
rconn, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress()) rconn, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress())
@ -284,8 +282,8 @@ func NewHttpTestTunnel() *TestTunnel {
if err := tlsConn.HandshakeContext(ctx); err != nil { if err := tlsConn.HandshakeContext(ctx); err != nil {
return return
} }
if tlsConn.ConnectionState().NegotiatedProtocol == http2.NextProtoTLS { if tlsConn.ConnectionState().NegotiatedProtocol == http.Http2NextProtoTLS {
h2Server.ServeConn(tlsConn, &http2.ServeConnOpts{BaseConfig: &server}) h2Server.ServeConn(tlsConn, &http.Http2ServeConnOpts{BaseConfig: &server})
} else { } else {
ln.ch <- tlsConn ln.ch <- tlsConn
} }

View File

@ -9,7 +9,6 @@ import (
"github.com/metacubex/mihomo/component/auth" "github.com/metacubex/mihomo/component/auth"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
authStore "github.com/metacubex/mihomo/listener/auth" authStore "github.com/metacubex/mihomo/listener/auth"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
@ -19,6 +18,8 @@ import (
"github.com/metacubex/mihomo/ntp" "github.com/metacubex/mihomo/ntp"
"github.com/metacubex/mihomo/transport/socks4" "github.com/metacubex/mihomo/transport/socks4"
"github.com/metacubex/mihomo/transport/socks5" "github.com/metacubex/mihomo/transport/socks5"
"github.com/metacubex/tls"
) )
type Listener struct { type Listener struct {
@ -62,7 +63,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
return nil, err return nil, err
} }
tlsConfig := &tlsC.Config{Time: ntp.Now} tlsConfig := &tls.Config{Time: ntp.Now}
var realityBuilder *reality.Builder var realityBuilder *reality.Builder
if config.Certificate != "" && config.PrivateKey != "" { if config.Certificate != "" && config.PrivateKey != "" {
@ -70,7 +71,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
if err != nil { if err != nil {
return nil, err return nil, err
} }
tlsConfig.Certificates = []tlsC.Certificate{tlsC.UCertificate(cert)} tlsConfig.Certificates = []tls.Certificate{cert}
if config.EchKey != "" { if config.EchKey != "" {
err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path) err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path)
@ -79,13 +80,13 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
} }
} }
} }
tlsConfig.ClientAuth = tlsC.ClientAuthTypeFromString(config.ClientAuthType) tlsConfig.ClientAuth = ca.ClientAuthTypeFromString(config.ClientAuthType)
if len(config.ClientAuthCert) > 0 { if len(config.ClientAuthCert) > 0 {
if tlsConfig.ClientAuth == tlsC.NoClientCert { if tlsConfig.ClientAuth == tls.NoClientCert {
tlsConfig.ClientAuth = tlsC.RequireAndVerifyClientCert tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
} }
} }
if tlsConfig.ClientAuth == tlsC.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tlsC.RequireAndVerifyClientCert { if tlsConfig.ClientAuth == tls.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tls.RequireAndVerifyClientCert {
pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path) pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -96,7 +97,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
if tlsConfig.Certificates != nil { if tlsConfig.Certificates != nil {
return nil, errors.New("certificate is unavailable in reality") return nil, errors.New("certificate is unavailable in reality")
} }
if tlsConfig.ClientAuth != tlsC.NoClientCert { if tlsConfig.ClientAuth != tls.NoClientCert {
return nil, errors.New("client-auth is unavailable in reality") return nil, errors.New("client-auth is unavailable in reality")
} }
realityBuilder, err = config.RealityConfig.Build(tunnel) realityBuilder, err = config.RealityConfig.Build(tunnel)
@ -108,7 +109,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
if realityBuilder != nil { if realityBuilder != nil {
l = realityBuilder.NewListener(l) l = realityBuilder.NewListener(l)
} else if len(tlsConfig.Certificates) > 0 { } else if len(tlsConfig.Certificates) > 0 {
l = tlsC.NewListener(l, tlsConfig) l = tls.NewListener(l, tlsConfig)
} }
ml := &Listener{ ml := &Listener{

View File

@ -5,8 +5,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/http"
"net/http/httputil"
"net/url" "net/url"
"strings" "strings"
@ -15,17 +13,18 @@ import (
"github.com/metacubex/mihomo/common/sockopt" "github.com/metacubex/mihomo/common/sockopt"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/sing" "github.com/metacubex/mihomo/listener/sing"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/mihomo/ntp" "github.com/metacubex/mihomo/ntp"
"github.com/metacubex/sing-quic/hysteria2" "github.com/metacubex/http"
"github.com/metacubex/http/httputil"
"github.com/metacubex/quic-go" "github.com/metacubex/quic-go"
"github.com/metacubex/sing-quic/hysteria2"
E "github.com/metacubex/sing/common/exceptions" E "github.com/metacubex/sing/common/exceptions"
"github.com/metacubex/tls"
) )
type Listener struct { type Listener struct {
@ -61,18 +60,18 @@ func New(config LC.Hysteria2Server, tunnel C.Tunnel, additions ...inbound.Additi
if err != nil { if err != nil {
return nil, err return nil, err
} }
tlsConfig := &tlsC.Config{ tlsConfig := &tls.Config{
Time: ntp.Now, Time: ntp.Now,
MinVersion: tlsC.VersionTLS13, MinVersion: tls.VersionTLS13,
} }
tlsConfig.Certificates = []tlsC.Certificate{tlsC.UCertificate(cert)} tlsConfig.Certificates = []tls.Certificate{cert}
tlsConfig.ClientAuth = tlsC.ClientAuthTypeFromString(config.ClientAuthType) tlsConfig.ClientAuth = ca.ClientAuthTypeFromString(config.ClientAuthType)
if len(config.ClientAuthCert) > 0 { if len(config.ClientAuthCert) > 0 {
if tlsConfig.ClientAuth == tlsC.NoClientCert { if tlsConfig.ClientAuth == tls.NoClientCert {
tlsConfig.ClientAuth = tlsC.RequireAndVerifyClientCert tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
} }
} }
if tlsConfig.ClientAuth == tlsC.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tlsC.RequireAndVerifyClientCert { if tlsConfig.ClientAuth == tls.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tls.RequireAndVerifyClientCert {
pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path) pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -4,13 +4,11 @@ import (
"context" "context"
"errors" "errors"
"net" "net"
"net/http"
"strings" "strings"
"github.com/metacubex/mihomo/adapter/inbound" "github.com/metacubex/mihomo/adapter/inbound"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/reality" "github.com/metacubex/mihomo/listener/reality"
@ -20,8 +18,10 @@ import (
"github.com/metacubex/mihomo/transport/vless/encryption" "github.com/metacubex/mihomo/transport/vless/encryption"
mihomoVMess "github.com/metacubex/mihomo/transport/vmess" mihomoVMess "github.com/metacubex/mihomo/transport/vmess"
"github.com/metacubex/http"
"github.com/metacubex/sing/common" "github.com/metacubex/sing/common"
"github.com/metacubex/sing/common/metadata" "github.com/metacubex/sing/common/metadata"
"github.com/metacubex/tls"
) )
type Listener struct { type Listener struct {
@ -76,7 +76,7 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition)
}() }()
} }
tlsConfig := &tlsC.Config{Time: ntp.Now} tlsConfig := &tls.Config{Time: ntp.Now}
var realityBuilder *reality.Builder var realityBuilder *reality.Builder
var httpServer http.Server var httpServer http.Server
@ -85,7 +85,7 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition)
if err != nil { if err != nil {
return nil, err return nil, err
} }
tlsConfig.Certificates = []tlsC.Certificate{tlsC.UCertificate(cert)} tlsConfig.Certificates = []tls.Certificate{cert}
if config.EchKey != "" { if config.EchKey != "" {
err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path) err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path)
@ -94,13 +94,13 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition)
} }
} }
} }
tlsConfig.ClientAuth = tlsC.ClientAuthTypeFromString(config.ClientAuthType) tlsConfig.ClientAuth = ca.ClientAuthTypeFromString(config.ClientAuthType)
if len(config.ClientAuthCert) > 0 { if len(config.ClientAuthCert) > 0 {
if tlsConfig.ClientAuth == tlsC.NoClientCert { if tlsConfig.ClientAuth == tls.NoClientCert {
tlsConfig.ClientAuth = tlsC.RequireAndVerifyClientCert tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
} }
} }
if tlsConfig.ClientAuth == tlsC.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tlsC.RequireAndVerifyClientCert { if tlsConfig.ClientAuth == tls.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tls.RequireAndVerifyClientCert {
pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path) pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -111,7 +111,7 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition)
if tlsConfig.Certificates != nil { if tlsConfig.Certificates != nil {
return nil, errors.New("certificate is unavailable in reality") return nil, errors.New("certificate is unavailable in reality")
} }
if tlsConfig.ClientAuth != tlsC.NoClientCert { if tlsConfig.ClientAuth != tls.NoClientCert {
return nil, errors.New("client-auth is unavailable in reality") return nil, errors.New("client-auth is unavailable in reality")
} }
realityBuilder, err = config.RealityConfig.Build(tunnel) realityBuilder, err = config.RealityConfig.Build(tunnel)
@ -154,11 +154,7 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition)
if realityBuilder != nil { if realityBuilder != nil {
l = realityBuilder.NewListener(l) l = realityBuilder.NewListener(l)
} else if len(tlsConfig.Certificates) > 0 { } else if len(tlsConfig.Certificates) > 0 {
if httpServer.Handler != nil { l = tls.NewListener(l, tlsConfig)
l = tlsC.NewListenerForHttps(l, &httpServer, tlsConfig)
} else {
l = tlsC.NewListener(l, tlsConfig)
}
} else if sl.decryption == nil { } else if sl.decryption == nil {
return nil, errors.New("disallow using Vless without any certificates/reality/decryption config") return nil, errors.New("disallow using Vless without any certificates/reality/decryption config")
} }

View File

@ -4,14 +4,12 @@ import (
"context" "context"
"errors" "errors"
"net" "net"
"net/http"
"net/url" "net/url"
"strings" "strings"
"github.com/metacubex/mihomo/adapter/inbound" "github.com/metacubex/mihomo/adapter/inbound"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/reality" "github.com/metacubex/mihomo/listener/reality"
@ -20,9 +18,11 @@ import (
"github.com/metacubex/mihomo/transport/gun" "github.com/metacubex/mihomo/transport/gun"
mihomoVMess "github.com/metacubex/mihomo/transport/vmess" mihomoVMess "github.com/metacubex/mihomo/transport/vmess"
"github.com/metacubex/http"
vmess "github.com/metacubex/sing-vmess" vmess "github.com/metacubex/sing-vmess"
"github.com/metacubex/sing/common" "github.com/metacubex/sing/common"
"github.com/metacubex/sing/common/metadata" "github.com/metacubex/sing/common/metadata"
"github.com/metacubex/tls"
) )
type Listener struct { type Listener struct {
@ -76,7 +76,7 @@ func New(config LC.VmessServer, tunnel C.Tunnel, additions ...inbound.Addition)
sl = &Listener{false, config, nil, service} sl = &Listener{false, config, nil, service}
tlsConfig := &tlsC.Config{Time: ntp.Now} tlsConfig := &tls.Config{Time: ntp.Now}
var realityBuilder *reality.Builder var realityBuilder *reality.Builder
var httpServer http.Server var httpServer http.Server
@ -85,7 +85,7 @@ func New(config LC.VmessServer, tunnel C.Tunnel, additions ...inbound.Addition)
if err != nil { if err != nil {
return nil, err return nil, err
} }
tlsConfig.Certificates = []tlsC.Certificate{tlsC.UCertificate(cert)} tlsConfig.Certificates = []tls.Certificate{cert}
if config.EchKey != "" { if config.EchKey != "" {
err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path) err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path)
@ -94,13 +94,13 @@ func New(config LC.VmessServer, tunnel C.Tunnel, additions ...inbound.Addition)
} }
} }
} }
tlsConfig.ClientAuth = tlsC.ClientAuthTypeFromString(config.ClientAuthType) tlsConfig.ClientAuth = ca.ClientAuthTypeFromString(config.ClientAuthType)
if len(config.ClientAuthCert) > 0 { if len(config.ClientAuthCert) > 0 {
if tlsConfig.ClientAuth == tlsC.NoClientCert { if tlsConfig.ClientAuth == tls.NoClientCert {
tlsConfig.ClientAuth = tlsC.RequireAndVerifyClientCert tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
} }
} }
if tlsConfig.ClientAuth == tlsC.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tlsC.RequireAndVerifyClientCert { if tlsConfig.ClientAuth == tls.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tls.RequireAndVerifyClientCert {
pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path) pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -111,7 +111,7 @@ func New(config LC.VmessServer, tunnel C.Tunnel, additions ...inbound.Addition)
if tlsConfig.Certificates != nil { if tlsConfig.Certificates != nil {
return nil, errors.New("certificate is unavailable in reality") return nil, errors.New("certificate is unavailable in reality")
} }
if tlsConfig.ClientAuth != tlsC.NoClientCert { if tlsConfig.ClientAuth != tls.NoClientCert {
return nil, errors.New("client-auth is unavailable in reality") return nil, errors.New("client-auth is unavailable in reality")
} }
realityBuilder, err = config.RealityConfig.Build(tunnel) realityBuilder, err = config.RealityConfig.Build(tunnel)
@ -154,11 +154,7 @@ func New(config LC.VmessServer, tunnel C.Tunnel, additions ...inbound.Addition)
if realityBuilder != nil { if realityBuilder != nil {
l = realityBuilder.NewListener(l) l = realityBuilder.NewListener(l)
} else if len(tlsConfig.Certificates) > 0 { } else if len(tlsConfig.Certificates) > 0 {
if httpServer.Handler != nil { l = tls.NewListener(l, tlsConfig)
l = tlsC.NewListenerForHttps(l, &httpServer, tlsConfig)
} else {
l = tlsC.NewListener(l, tlsConfig)
}
} }
sl.listeners = append(sl.listeners, l) sl.listeners = append(sl.listeners, l)

View File

@ -10,7 +10,6 @@ import (
"github.com/metacubex/mihomo/component/auth" "github.com/metacubex/mihomo/component/auth"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
authStore "github.com/metacubex/mihomo/listener/auth" authStore "github.com/metacubex/mihomo/listener/auth"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
@ -18,6 +17,8 @@ import (
"github.com/metacubex/mihomo/ntp" "github.com/metacubex/mihomo/ntp"
"github.com/metacubex/mihomo/transport/socks4" "github.com/metacubex/mihomo/transport/socks4"
"github.com/metacubex/mihomo/transport/socks5" "github.com/metacubex/mihomo/transport/socks5"
"github.com/metacubex/tls"
) )
type Listener struct { type Listener struct {
@ -61,7 +62,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
return nil, err return nil, err
} }
tlsConfig := &tlsC.Config{Time: ntp.Now} tlsConfig := &tls.Config{Time: ntp.Now}
var realityBuilder *reality.Builder var realityBuilder *reality.Builder
if config.Certificate != "" && config.PrivateKey != "" { if config.Certificate != "" && config.PrivateKey != "" {
@ -69,7 +70,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
if err != nil { if err != nil {
return nil, err return nil, err
} }
tlsConfig.Certificates = []tlsC.Certificate{tlsC.UCertificate(cert)} tlsConfig.Certificates = []tls.Certificate{cert}
if config.EchKey != "" { if config.EchKey != "" {
err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path) err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path)
@ -78,13 +79,13 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
} }
} }
} }
tlsConfig.ClientAuth = tlsC.ClientAuthTypeFromString(config.ClientAuthType) tlsConfig.ClientAuth = ca.ClientAuthTypeFromString(config.ClientAuthType)
if len(config.ClientAuthCert) > 0 { if len(config.ClientAuthCert) > 0 {
if tlsConfig.ClientAuth == tlsC.NoClientCert { if tlsConfig.ClientAuth == tls.NoClientCert {
tlsConfig.ClientAuth = tlsC.RequireAndVerifyClientCert tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
} }
} }
if tlsConfig.ClientAuth == tlsC.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tlsC.RequireAndVerifyClientCert { if tlsConfig.ClientAuth == tls.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tls.RequireAndVerifyClientCert {
pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path) pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -95,7 +96,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
if tlsConfig.Certificates != nil { if tlsConfig.Certificates != nil {
return nil, errors.New("certificate is unavailable in reality") return nil, errors.New("certificate is unavailable in reality")
} }
if tlsConfig.ClientAuth != tlsC.NoClientCert { if tlsConfig.ClientAuth != tls.NoClientCert {
return nil, errors.New("client-auth is unavailable in reality") return nil, errors.New("client-auth is unavailable in reality")
} }
realityBuilder, err = config.RealityConfig.Build(tunnel) realityBuilder, err = config.RealityConfig.Build(tunnel)
@ -107,7 +108,7 @@ func NewWithConfig(config LC.AuthServer, tunnel C.Tunnel, additions ...inbound.A
if realityBuilder != nil { if realityBuilder != nil {
l = realityBuilder.NewListener(l) l = realityBuilder.NewListener(l)
} else if len(tlsConfig.Certificates) > 0 { } else if len(tlsConfig.Certificates) > 0 {
l = tlsC.NewListener(l, tlsConfig) l = tls.NewListener(l, tlsConfig)
} }
sl := &Listener{ sl := &Listener{

View File

@ -4,13 +4,11 @@ import (
"errors" "errors"
"io" "io"
"net" "net"
"net/http"
"strings" "strings"
"github.com/metacubex/mihomo/adapter/inbound" "github.com/metacubex/mihomo/adapter/inbound"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/reality" "github.com/metacubex/mihomo/listener/reality"
@ -22,7 +20,9 @@ import (
"github.com/metacubex/mihomo/transport/trojan" "github.com/metacubex/mihomo/transport/trojan"
mihomoVMess "github.com/metacubex/mihomo/transport/vmess" mihomoVMess "github.com/metacubex/mihomo/transport/vmess"
"github.com/metacubex/http"
"github.com/metacubex/smux" "github.com/metacubex/smux"
"github.com/metacubex/tls"
) )
type Listener struct { type Listener struct {
@ -71,7 +71,7 @@ func New(config LC.TrojanServer, tunnel C.Tunnel, additions ...inbound.Addition)
} }
sl = &Listener{false, config, nil, keys, pickCipher, h} sl = &Listener{false, config, nil, keys, pickCipher, h}
tlsConfig := &tlsC.Config{Time: ntp.Now} tlsConfig := &tls.Config{Time: ntp.Now}
var realityBuilder *reality.Builder var realityBuilder *reality.Builder
var httpServer http.Server var httpServer http.Server
@ -80,7 +80,7 @@ func New(config LC.TrojanServer, tunnel C.Tunnel, additions ...inbound.Addition)
if err != nil { if err != nil {
return nil, err return nil, err
} }
tlsConfig.Certificates = []tlsC.Certificate{tlsC.UCertificate(cert)} tlsConfig.Certificates = []tls.Certificate{cert}
if config.EchKey != "" { if config.EchKey != "" {
err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path) err = ech.LoadECHKey(config.EchKey, tlsConfig, C.Path)
@ -89,13 +89,13 @@ func New(config LC.TrojanServer, tunnel C.Tunnel, additions ...inbound.Addition)
} }
} }
} }
tlsConfig.ClientAuth = tlsC.ClientAuthTypeFromString(config.ClientAuthType) tlsConfig.ClientAuth = ca.ClientAuthTypeFromString(config.ClientAuthType)
if len(config.ClientAuthCert) > 0 { if len(config.ClientAuthCert) > 0 {
if tlsConfig.ClientAuth == tlsC.NoClientCert { if tlsConfig.ClientAuth == tls.NoClientCert {
tlsConfig.ClientAuth = tlsC.RequireAndVerifyClientCert tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
} }
} }
if tlsConfig.ClientAuth == tlsC.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tlsC.RequireAndVerifyClientCert { if tlsConfig.ClientAuth == tls.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tls.RequireAndVerifyClientCert {
pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path) pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -106,7 +106,7 @@ func New(config LC.TrojanServer, tunnel C.Tunnel, additions ...inbound.Addition)
if tlsConfig.Certificates != nil { if tlsConfig.Certificates != nil {
return nil, errors.New("certificate is unavailable in reality") return nil, errors.New("certificate is unavailable in reality")
} }
if tlsConfig.ClientAuth != tlsC.NoClientCert { if tlsConfig.ClientAuth != tls.NoClientCert {
return nil, errors.New("client-auth is unavailable in reality") return nil, errors.New("client-auth is unavailable in reality")
} }
realityBuilder, err = config.RealityConfig.Build(tunnel) realityBuilder, err = config.RealityConfig.Build(tunnel)
@ -149,11 +149,7 @@ func New(config LC.TrojanServer, tunnel C.Tunnel, additions ...inbound.Addition)
if realityBuilder != nil { if realityBuilder != nil {
l = realityBuilder.NewListener(l) l = realityBuilder.NewListener(l)
} else if len(tlsConfig.Certificates) > 0 { } else if len(tlsConfig.Certificates) > 0 {
if httpServer.Handler != nil { l = tls.NewListener(l, tlsConfig)
l = tlsC.NewListenerForHttps(l, &httpServer, tlsConfig)
} else {
l = tlsC.NewListener(l, tlsConfig)
}
} else if !config.TrojanSSOption.Enabled { } else if !config.TrojanSSOption.Enabled {
return nil, errors.New("disallow using Trojan without both certificates/reality/ss config") return nil, errors.New("disallow using Trojan without both certificates/reality/ss config")
} }

View File

@ -9,7 +9,6 @@ import (
"github.com/metacubex/mihomo/common/sockopt" "github.com/metacubex/mihomo/common/sockopt"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/sing" "github.com/metacubex/mihomo/listener/sing"
@ -20,6 +19,7 @@ import (
"github.com/gofrs/uuid/v5" "github.com/gofrs/uuid/v5"
"github.com/metacubex/quic-go" "github.com/metacubex/quic-go"
"github.com/metacubex/tls"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
) )
@ -53,18 +53,18 @@ func New(config LC.TuicServer, tunnel C.Tunnel, additions ...inbound.Addition) (
if err != nil { if err != nil {
return nil, err return nil, err
} }
tlsConfig := &tlsC.Config{ tlsConfig := &tls.Config{
Time: ntp.Now, Time: ntp.Now,
MinVersion: tlsC.VersionTLS13, MinVersion: tls.VersionTLS13,
} }
tlsConfig.Certificates = []tlsC.Certificate{tlsC.UCertificate(cert)} tlsConfig.Certificates = []tls.Certificate{cert}
tlsConfig.ClientAuth = tlsC.ClientAuthTypeFromString(config.ClientAuthType) tlsConfig.ClientAuth = ca.ClientAuthTypeFromString(config.ClientAuthType)
if len(config.ClientAuthCert) > 0 { if len(config.ClientAuthCert) > 0 {
if tlsConfig.ClientAuth == tlsC.NoClientCert { if tlsConfig.ClientAuth == tls.NoClientCert {
tlsConfig.ClientAuth = tlsC.RequireAndVerifyClientCert tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
} }
} }
if tlsConfig.ClientAuth == tlsC.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tlsC.RequireAndVerifyClientCert { if tlsConfig.ClientAuth == tls.VerifyClientCertIfGiven || tlsConfig.ClientAuth == tls.RequireAndVerifyClientCert {
pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path) pool, err := ca.LoadCertificates(config.ClientAuthCert, C.Path)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -2,14 +2,15 @@ package gost
import ( import (
"context" "context"
"crypto/tls"
"net" "net"
"net/http"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
"github.com/metacubex/mihomo/transport/vmess" "github.com/metacubex/mihomo/transport/vmess"
smux "github.com/metacubex/smux"
"github.com/metacubex/http"
"github.com/metacubex/smux"
"github.com/metacubex/tls"
) )
// Option is options of gost websocket // Option is options of gost websocket

View File

@ -6,14 +6,11 @@ package gun
import ( import (
"bufio" "bufio"
"context" "context"
"crypto/tls"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"net" "net"
"net/http"
"net/http/httptrace"
"net/url" "net/url"
"sync" "sync"
"time" "time"
@ -24,7 +21,9 @@ import (
tlsC "github.com/metacubex/mihomo/component/tls" tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"golang.org/x/net/http2" "github.com/metacubex/http"
"github.com/metacubex/http/httptrace"
"github.com/metacubex/tls"
) )
var ( var (
@ -261,7 +260,7 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config, clientFingerprint stri
if clientFingerprint, ok := tlsC.GetFingerprint(clientFingerprint); ok { if clientFingerprint, ok := tlsC.GetFingerprint(clientFingerprint); ok {
tlsConfig := tlsC.UConfig(cfg) tlsConfig := tlsC.UConfig(cfg)
err := echConfig.ClientHandle(ctx, tlsConfig) err := echConfig.ClientHandleUTLS(ctx, tlsConfig)
if err != nil { if err != nil {
pconn.Close() pconn.Close()
return nil, err return nil, err
@ -274,9 +273,9 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config, clientFingerprint stri
return nil, err return nil, err
} }
state := tlsConn.ConnectionState() state := tlsConn.ConnectionState()
if p := state.NegotiatedProtocol; p != http2.NextProtoTLS { if p := state.NegotiatedProtocol; p != http.Http2NextProtoTLS {
tlsConn.Close() tlsConn.Close()
return nil, fmt.Errorf("http2: unexpected ALPN protocol %s, want %s", p, http2.NextProtoTLS) return nil, fmt.Errorf("http2: unexpected ALPN protocol %s, want %s", p, http.Http2NextProtoTLS)
} }
return tlsConn, nil return tlsConn, nil
} else { } else {
@ -286,9 +285,9 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config, clientFingerprint stri
return nil, err return nil, err
} }
//state := realityConn.(*utls.UConn).ConnectionState() //state := realityConn.(*utls.UConn).ConnectionState()
//if p := state.NegotiatedProtocol; p != http2.NextProtoTLS { //if p := state.NegotiatedProtocol; p != http.Http2NextProtoTLS {
// realityConn.Close() // realityConn.Close()
// return nil, fmt.Errorf("http2: unexpected ALPN protocol %s, want %s", p, http2.NextProtoTLS) // return nil, fmt.Errorf("http2: unexpected ALPN protocol %s, want %s", p, http.Http2NextProtoTLS)
//} //}
return realityConn, nil return realityConn, nil
} }
@ -299,7 +298,7 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config, clientFingerprint stri
if echConfig != nil { if echConfig != nil {
tlsConfig := tlsC.UConfig(cfg) tlsConfig := tlsC.UConfig(cfg)
err := echConfig.ClientHandle(ctx, tlsConfig) err := echConfig.ClientHandleUTLS(ctx, tlsConfig)
if err != nil { if err != nil {
pconn.Close() pconn.Close()
return nil, err return nil, err
@ -311,9 +310,9 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config, clientFingerprint stri
return nil, err return nil, err
} }
state := conn.ConnectionState() state := conn.ConnectionState()
if p := state.NegotiatedProtocol; p != http2.NextProtoTLS { if p := state.NegotiatedProtocol; p != http.Http2NextProtoTLS {
conn.Close() conn.Close()
return nil, fmt.Errorf("http2: unexpected ALPN protocol %s, want %s", p, http2.NextProtoTLS) return nil, fmt.Errorf("http2: unexpected ALPN protocol %s, want %s", p, http.Http2NextProtoTLS)
} }
return conn, nil return conn, nil
} }
@ -324,14 +323,14 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config, clientFingerprint stri
return nil, err return nil, err
} }
state := conn.ConnectionState() state := conn.ConnectionState()
if p := state.NegotiatedProtocol; p != http2.NextProtoTLS { if p := state.NegotiatedProtocol; p != http.Http2NextProtoTLS {
conn.Close() conn.Close()
return nil, fmt.Errorf("http2: unexpected ALPN protocol %s, want %s", p, http2.NextProtoTLS) return nil, fmt.Errorf("http2: unexpected ALPN protocol %s, want %s", p, http.Http2NextProtoTLS)
} }
return conn, nil return conn, nil
} }
transport := &http2.Transport{ transport := &http.Http2Transport{
DialTLSContext: dialFunc, DialTLSContext: dialFunc,
TLSClientConfig: tlsConfig, TLSClientConfig: tlsConfig,
AllowHTTP: false, AllowHTTP: false,
@ -341,9 +340,9 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config, clientFingerprint stri
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
wrap := &TransportWrap{ wrap := &TransportWrap{
Transport: transport, Http2Transport: transport,
ctx: ctx, ctx: ctx,
cancel: cancel, cancel: cancel,
} }
return wrap return wrap
} }

View File

@ -3,7 +3,6 @@ package gun
import ( import (
"io" "io"
"net" "net"
"net/http"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -12,8 +11,8 @@ import (
N "github.com/metacubex/mihomo/common/net" N "github.com/metacubex/mihomo/common/net"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"golang.org/x/net/http2" "github.com/metacubex/http"
"golang.org/x/net/http2/h2c" "github.com/metacubex/http/h2c"
) )
const idleTimeout = 30 * time.Second const idleTimeout = 30 * time.Second
@ -72,7 +71,7 @@ func NewServerHandler(options ServerOption) http.Handler {
} }
httpHandler.ServeHTTP(writer, request) httpHandler.ServeHTTP(writer, request)
}), &http2.Server{ }), &http.Http2Server{
IdleTimeout: idleTimeout, IdleTimeout: idleTimeout,
}) })
} }

View File

@ -5,11 +5,11 @@ import (
"net" "net"
"sync" "sync"
"golang.org/x/net/http2" "github.com/metacubex/http"
) )
type TransportWrap struct { type TransportWrap struct {
*http2.Transport *http.Http2Transport
ctx context.Context ctx context.Context
cancel context.CancelFunc cancel context.CancelFunc
closeOnce sync.Once closeOnce sync.Once
@ -18,7 +18,7 @@ type TransportWrap struct {
func (tw *TransportWrap) Close() error { func (tw *TransportWrap) Close() error {
tw.closeOnce.Do(func() { tw.closeOnce.Do(func() {
tw.cancel() tw.cancel()
closeTransport(tw.Transport) closeTransport(tw.Http2Transport)
}) })
return nil return nil
} }

View File

@ -2,21 +2,20 @@ package gun
import ( import (
"net" "net"
"net/http"
"sync" "sync"
"time" "time"
"unsafe" "unsafe"
"golang.org/x/net/http2" "github.com/metacubex/http"
) )
type clientConnPool struct { type clientConnPool struct {
t *http2.Transport t *http.Http2Transport
mu sync.Mutex mu sync.Mutex
conns map[string][]*http2.ClientConn // key is host:port conns map[string][]*http.Http2ClientConn // key is host:port
dialing map[string]unsafe.Pointer // currently in-flight dials dialing map[string]unsafe.Pointer // currently in-flight dials
keys map[*http2.ClientConn][]string keys map[*http.Http2ClientConn][]string
addConnCalls map[string]unsafe.Pointer // in-flight addConnIfNeeded calls addConnCalls map[string]unsafe.Pointer // in-flight addConnIfNeeded calls
} }
@ -35,7 +34,7 @@ type tlsConn interface {
NetConn() net.Conn NetConn() net.Conn
} }
func closeClientConn(cc *http2.ClientConn) { // like forceCloseConn() in http2.ClientConn but also apply for tls-like conn func closeClientConn(cc *http.Http2ClientConn) { // like forceCloseConn() in http.Http2ClientConn but also apply for tls-like conn
if conn, ok := (*clientConn)(unsafe.Pointer(cc)).tconn.(tlsConn); ok { if conn, ok := (*clientConn)(unsafe.Pointer(cc)).tconn.(tlsConn); ok {
t := time.AfterFunc(time.Second, func() { t := time.AfterFunc(time.Second, func() {
_ = conn.NetConn().Close() _ = conn.NetConn().Close()
@ -45,7 +44,7 @@ func closeClientConn(cc *http2.ClientConn) { // like forceCloseConn() in http2.C
_ = cc.Close() _ = cc.Close()
} }
func closeTransport(tr *http2.Transport) { func closeTransport(tr *http.Http2Transport) {
connPool := transportConnPool(tr) connPool := transportConnPool(tr)
p := (*clientConnPool)((*efaceWords)(unsafe.Pointer(&connPool)).data) p := (*clientConnPool)((*efaceWords)(unsafe.Pointer(&connPool)).data)
p.mu.Lock() p.mu.Lock()
@ -56,9 +55,9 @@ func closeTransport(tr *http2.Transport) {
} }
} }
// cleanup // cleanup
p.conns = make(map[string][]*http2.ClientConn) p.conns = make(map[string][]*http.Http2ClientConn)
p.keys = make(map[*http2.ClientConn][]string) p.keys = make(map[*http.Http2ClientConn][]string)
} }
//go:linkname transportConnPool golang.org/x/net/http2.(*Transport).connPool //go:linkname transportConnPool github.com/metacubex/http.(*http2Transport).connPool
func transportConnPool(t *http2.Transport) http2.ClientConnPool func transportConnPool(t *http.Http2Transport) http.Http2ClientConnPool

View File

@ -1,192 +0,0 @@
//go:build linux
// +build linux
package faketcp
import (
_ "net/http/pprof"
)
//const testPortStream = "127.0.0.1:3456"
//const testPortPacket = "127.0.0.1:3457"
const testPortStream = "127.0.0.1:3456"
const portServerPacket = "[::]:3457"
const portRemotePacket = "127.0.0.1:3457"
//func init() {
// startTCPServer()
// startTCPRawServer()
// go func() {
// log.Println(http.ListenAndServe("0.0.0.0:6060", nil))
// }()
//}
//
//func startTCPServer() net.Listener {
// l, err := net.Listen("tcp", testPortStream)
// if err != nil {
// log.Panicln(err)
// }
//
// go func() {
// defer l.Close()
// for {
// conn, err := l.Accept()
// if err != nil {
// log.Println(err)
// return
// }
//
// go handleRequest(conn)
// }
// }()
// return l
//}
//
//func startTCPRawServer() *TCPConn {
// conn, err := Listen("tcp", portServerPacket)
// if err != nil {
// log.Panicln(err)
// }
// err = conn.SetReadBuffer(1024 * 1024)
// if err != nil {
// log.Println(err)
// }
// err = conn.SetWriteBuffer(1024 * 1024)
// if err != nil {
// log.Println(err)
// }
//
// go func() {
// defer conn.Close()
// buf := make([]byte, 1024)
// for {
// n, addr, err := conn.ReadFrom(buf)
// if err != nil {
// log.Println("server readfrom:", err)
// return
// }
// //echo
// n, err = conn.WriteTo(buf[:n], addr)
// if err != nil {
// log.Println("server writeTo:", err)
// return
// }
// }
// }()
// return conn
//}
//
//func handleRequest(conn net.Conn) {
// defer conn.Close()
//
// for {
// buf := make([]byte, 1024)
// size, err := conn.Read(buf)
// if err != nil {
// log.Println("handleRequest:", err)
// return
// }
// data := buf[:size]
// conn.Write(data)
// }
//}
//
//func TestDialTCPStream(t *testing.T) {
// conn, err := Dial("tcp", testPortStream)
// if err != nil {
// t.Fatal(err)
// }
// defer conn.Close()
//
// addr, err := net.ResolveTCPAddr("tcp", testPortStream)
// if err != nil {
// t.Fatal(err)
// }
//
// n, err := conn.WriteTo([]byte("abc"), addr)
// if err != nil {
// t.Fatal(n, err)
// }
//
// buf := make([]byte, 1024)
// if n, addr, err := conn.ReadFrom(buf); err != nil {
// t.Fatal(n, addr, err)
// } else {
// log.Println(string(buf[:n]), "from:", addr)
// }
//}
//
//func TestDialToTCPPacket(t *testing.T) {
// conn, err := Dial("tcp", portRemotePacket)
// if err != nil {
// t.Fatal(err)
// }
// defer conn.Close()
//
// addr, err := net.ResolveTCPAddr("tcp", portRemotePacket)
// if err != nil {
// t.Fatal(err)
// }
//
// n, err := conn.WriteTo([]byte("abc"), addr)
// if err != nil {
// t.Fatal(n, err)
// }
// log.Println("written")
//
// buf := make([]byte, 1024)
// log.Println("readfrom buf")
// if n, addr, err := conn.ReadFrom(buf); err != nil {
// log.Println(err)
// t.Fatal(n, addr, err)
// } else {
// log.Println(string(buf[:n]), "from:", addr)
// }
//
// log.Println("complete")
//}
//
//func TestSettings(t *testing.T) {
// conn, err := Dial("tcp", portRemotePacket)
// if err != nil {
// t.Fatal(err)
// }
// defer conn.Close()
// if err := conn.SetDSCP(46); err != nil {
// log.Fatal("SetDSCP:", err)
// }
// if err := conn.SetReadBuffer(4096); err != nil {
// log.Fatal("SetReaderBuffer:", err)
// }
// if err := conn.SetWriteBuffer(4096); err != nil {
// log.Fatal("SetWriteBuffer:", err)
// }
//}
//
//func BenchmarkEcho(b *testing.B) {
// conn, err := Dial("tcp", portRemotePacket)
// if err != nil {
// b.Fatal(err)
// }
// defer conn.Close()
//
// addr, err := net.ResolveTCPAddr("tcp", portRemotePacket)
// if err != nil {
// b.Fatal(err)
// }
//
// buf := make([]byte, 1024)
// b.ReportAllocs()
// b.SetBytes(int64(len(buf)))
// for i := 0; i < b.N; i++ {
// n, err := conn.WriteTo(buf, addr)
// if err != nil {
// b.Fatal(n, err)
// }
//
// if n, addr, err := conn.ReadFrom(buf); err != nil {
// b.Fatal(n, addr, err)
// }
// }
//}

View File

@ -9,7 +9,6 @@ import (
"sync" "sync"
"time" "time"
tlsC "github.com/metacubex/mihomo/component/tls"
"github.com/metacubex/mihomo/transport/hysteria/obfs" "github.com/metacubex/mihomo/transport/hysteria/obfs"
"github.com/metacubex/mihomo/transport/hysteria/pmtud_fix" "github.com/metacubex/mihomo/transport/hysteria/pmtud_fix"
"github.com/metacubex/mihomo/transport/hysteria/transport" "github.com/metacubex/mihomo/transport/hysteria/transport"
@ -18,6 +17,7 @@ import (
"github.com/metacubex/quic-go" "github.com/metacubex/quic-go"
"github.com/metacubex/quic-go/congestion" "github.com/metacubex/quic-go/congestion"
"github.com/metacubex/randv2" "github.com/metacubex/randv2"
"github.com/metacubex/tls"
) )
var ( var (
@ -36,7 +36,7 @@ type Client struct {
congestionFactory CongestionFactory congestionFactory CongestionFactory
obfuscator obfs.Obfuscator obfuscator obfs.Obfuscator
tlsConfig *tlsC.Config tlsConfig *tls.Config
quicConfig *quic.Config quicConfig *quic.Config
quicSession *quic.Conn quicSession *quic.Conn
@ -50,7 +50,7 @@ type Client struct {
fastOpen bool fastOpen bool
} }
func NewClient(serverAddr string, serverPorts string, protocol string, auth []byte, tlsConfig *tlsC.Config, quicConfig *quic.Config, func NewClient(serverAddr string, serverPorts string, protocol string, auth []byte, tlsConfig *tls.Config, quicConfig *quic.Config,
transport *transport.ClientTransport, sendBPS uint64, recvBPS uint64, congestionFactory CongestionFactory, transport *transport.ClientTransport, sendBPS uint64, recvBPS uint64, congestionFactory CongestionFactory,
obfuscator obfs.Obfuscator, hopInterval time.Duration, fastOpen bool) (*Client, error) { obfuscator obfs.Obfuscator, hopInterval time.Duration, fastOpen bool) (*Client, error) {
quicConfig.DisablePathMTUDiscovery = quicConfig.DisablePathMTUDiscovery || pmtud_fix.DisablePathMTUDiscovery quicConfig.DisablePathMTUDiscovery = quicConfig.DisablePathMTUDiscovery || pmtud_fix.DisablePathMTUDiscovery

View File

@ -5,7 +5,6 @@ import (
"net" "net"
"time" "time"
tlsC "github.com/metacubex/mihomo/component/tls"
"github.com/metacubex/mihomo/transport/hysteria/conns/faketcp" "github.com/metacubex/mihomo/transport/hysteria/conns/faketcp"
"github.com/metacubex/mihomo/transport/hysteria/conns/udp" "github.com/metacubex/mihomo/transport/hysteria/conns/udp"
"github.com/metacubex/mihomo/transport/hysteria/conns/wechat" "github.com/metacubex/mihomo/transport/hysteria/conns/wechat"
@ -13,6 +12,7 @@ import (
"github.com/metacubex/mihomo/transport/hysteria/utils" "github.com/metacubex/mihomo/transport/hysteria/utils"
"github.com/metacubex/quic-go" "github.com/metacubex/quic-go"
"github.com/metacubex/tls"
) )
type ClientTransport struct{} type ClientTransport struct{}
@ -62,7 +62,7 @@ func (ct *ClientTransport) quicPacketConn(proto string, rAddr net.Addr, serverPo
} }
} }
func (ct *ClientTransport) QUICDial(proto string, server string, serverPorts string, tlsConfig *tlsC.Config, quicConfig *quic.Config, obfs obfsPkg.Obfuscator, hopInterval time.Duration, dialer utils.PacketDialer) (*quic.Conn, error) { func (ct *ClientTransport) QUICDial(proto string, server string, serverPorts string, tlsConfig *tls.Config, quicConfig *quic.Config, obfs obfsPkg.Obfuscator, hopInterval time.Duration, dialer utils.PacketDialer) (*quic.Conn, error) {
serverUDPAddr, err := dialer.RemoteAddr(server) serverUDPAddr, err := dialer.RemoteAddr(server)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"crypto/hmac" "crypto/hmac"
"crypto/sha1" "crypto/sha1"
"crypto/tls"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"hash" "hash"
@ -13,6 +12,8 @@ import (
"github.com/metacubex/mihomo/common/pool" "github.com/metacubex/mihomo/common/pool"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/tls"
) )
const ( const (

View File

@ -7,10 +7,10 @@ import (
"fmt" "fmt"
"io" "io"
"net" "net"
"net/http"
"github.com/metacubex/mihomo/common/pool" "github.com/metacubex/mihomo/common/pool"
"github.com/metacubex/http"
"github.com/metacubex/randv2" "github.com/metacubex/randv2"
) )

View File

@ -2,7 +2,6 @@ package sing_shadowtls
import ( import (
"context" "context"
"crypto/tls"
"net" "net"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
@ -10,6 +9,7 @@ import (
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/sing-shadowtls" "github.com/metacubex/sing-shadowtls"
"github.com/metacubex/tls"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
) )

View File

@ -9,7 +9,6 @@ import (
"github.com/metacubex/mihomo/adapter/inbound" "github.com/metacubex/mihomo/adapter/inbound"
N "github.com/metacubex/mihomo/common/net" N "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/mihomo/common/utils" "github.com/metacubex/mihomo/common/utils"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/transport/socks5" "github.com/metacubex/mihomo/transport/socks5"
"github.com/metacubex/mihomo/transport/tuic/common" "github.com/metacubex/mihomo/transport/tuic/common"
@ -18,13 +17,14 @@ import (
"github.com/gofrs/uuid/v5" "github.com/gofrs/uuid/v5"
"github.com/metacubex/quic-go" "github.com/metacubex/quic-go"
"github.com/metacubex/tls"
) )
type ServerOption struct { type ServerOption struct {
HandleTcpFn func(conn net.Conn, addr socks5.Addr, additions ...inbound.Addition) error HandleTcpFn func(conn net.Conn, addr socks5.Addr, additions ...inbound.Addition) error
HandleUdpFn func(addr socks5.Addr, packet C.UDPPacket, additions ...inbound.Addition) error HandleUdpFn func(addr socks5.Addr, packet C.UDPPacket, additions ...inbound.Addition) error
TlsConfig *tlsC.Config TlsConfig *tls.Config
QuicConfig *quic.Config QuicConfig *quic.Config
Tokens [][32]byte // V4 special Tokens [][32]byte // V4 special
Users map[[16]byte]string // V5 special Users map[[16]byte]string // V5 special

View File

@ -15,17 +15,17 @@ import (
N "github.com/metacubex/mihomo/common/net" N "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/mihomo/common/pool" "github.com/metacubex/mihomo/common/pool"
"github.com/metacubex/mihomo/common/xsync" "github.com/metacubex/mihomo/common/xsync"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/mihomo/transport/tuic/common" "github.com/metacubex/mihomo/transport/tuic/common"
"github.com/metacubex/quic-go" "github.com/metacubex/quic-go"
"github.com/metacubex/randv2" "github.com/metacubex/randv2"
"github.com/metacubex/tls"
) )
type ClientOption struct { type ClientOption struct {
TlsConfig *tlsC.Config TlsConfig *tls.Config
QuicConfig *quic.Config QuicConfig *quic.Config
Token [32]byte Token [32]byte
UdpRelayMode common.UdpRelayMode UdpRelayMode common.UdpRelayMode

View File

@ -15,17 +15,17 @@ import (
N "github.com/metacubex/mihomo/common/net" N "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/mihomo/common/pool" "github.com/metacubex/mihomo/common/pool"
"github.com/metacubex/mihomo/common/xsync" "github.com/metacubex/mihomo/common/xsync"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/mihomo/transport/tuic/common" "github.com/metacubex/mihomo/transport/tuic/common"
"github.com/metacubex/quic-go" "github.com/metacubex/quic-go"
"github.com/metacubex/randv2" "github.com/metacubex/randv2"
"github.com/metacubex/tls"
) )
type ClientOption struct { type ClientOption struct {
TlsConfig *tlsC.Config TlsConfig *tls.Config
QuicConfig *quic.Config QuicConfig *quic.Config
Uuid [16]byte Uuid [16]byte
Password string Password string

View File

@ -2,13 +2,14 @@ package obfs
import ( import (
"context" "context"
"crypto/tls"
"net" "net"
"net/http"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
"github.com/metacubex/mihomo/transport/vmess" "github.com/metacubex/mihomo/transport/vmess"
"github.com/metacubex/http"
"github.com/metacubex/tls"
) )
// Option is options of websocket obfs // Option is options of websocket obfs

View File

@ -18,6 +18,7 @@ import (
"github.com/metacubex/mihomo/transport/vless/encryption" "github.com/metacubex/mihomo/transport/vless/encryption"
"github.com/gofrs/uuid/v5" "github.com/gofrs/uuid/v5"
"github.com/metacubex/tls"
) )
var ErrNotHandshakeComplete = errors.New("tls connection not handshake complete") var ErrNotHandshakeComplete = errors.New("tls connection not handshake complete")
@ -47,6 +48,13 @@ func NewConn(conn net.Conn, tlsConn net.Conn, userUUID uuid.UUID) (*Conn, error)
t = reflect.TypeOf(underlying).Elem() t = reflect.TypeOf(underlying).Elem()
p = unsafe.Pointer(underlying) p = unsafe.Pointer(underlying)
break break
case *tls.Conn:
//log.Debugln("type tls")
tlsConn = underlying
c.netConn = underlying.NetConn()
t = reflect.TypeOf(underlying).Elem()
p = unsafe.Pointer(underlying)
break
case *tlsC.Conn: case *tlsC.Conn:
//log.Debugln("type *tlsC.Conn") //log.Debugln("type *tlsC.Conn")
tlsConn = underlying tlsConn = underlying
@ -114,6 +122,14 @@ func checkTLSVersion(tlsConn net.Conn) error {
if state.Version != gotls.VersionTLS13 { if state.Version != gotls.VersionTLS13 {
return ErrNotTLS13 return ErrNotTLS13
} }
case *tls.Conn:
state := underlying.ConnectionState()
if !state.HandshakeComplete {
return ErrNotHandshakeComplete
}
if state.Version != tls.VersionTLS13 {
return ErrNotTLS13
}
case *tlsC.Conn: case *tlsC.Conn:
state := underlying.ConnectionState() state := underlying.ConnectionState()
if !state.HandshakeComplete { if !state.HandshakeComplete {

View File

@ -4,18 +4,17 @@ import (
"context" "context"
"io" "io"
"net" "net"
"net/http"
"net/url" "net/url"
N "github.com/metacubex/mihomo/common/net" N "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/http"
"github.com/metacubex/randv2" "github.com/metacubex/randv2"
"golang.org/x/net/http2"
) )
type h2Conn struct { type h2Conn struct {
net.Conn net.Conn
*http2.ClientConn *http.Http2ClientConn
pwriter *io.PipeWriter pwriter *io.PipeWriter
res *http.Response res *http.Response
cfg *H2Config cfg *H2Config
@ -50,7 +49,7 @@ func (hc *h2Conn) establishConn() error {
} }
// it will be close at : `func (hc *h2Conn) Close() error` // it will be close at : `func (hc *h2Conn) Close() error`
res, err := hc.ClientConn.RoundTrip(&req) res, err := hc.Http2ClientConn.RoundTrip(&req)
if err != nil { if err != nil {
return err return err
} }
@ -96,7 +95,7 @@ func (hc *h2Conn) Close() error {
if hc.res != nil { if hc.res != nil {
ctx = hc.res.Request.Context() ctx = hc.res.Request.Context()
} }
if err := hc.ClientConn.Shutdown(ctx); err != nil { if err := hc.Http2ClientConn.Shutdown(ctx); err != nil {
return err return err
} }
return hc.Conn.Close() return hc.Conn.Close()
@ -108,7 +107,7 @@ func StreamH2Conn(ctx context.Context, conn net.Conn, cfg *H2Config) (_ net.Conn
defer done(&err) defer done(&err)
} }
transport := &http2.Transport{} transport := &http.Http2Transport{}
cconn, err := transport.NewClientConn(conn) cconn, err := transport.NewClientConn(conn)
if err != nil { if err != nil {
@ -116,8 +115,8 @@ func StreamH2Conn(ctx context.Context, conn net.Conn, cfg *H2Config) (_ net.Conn
} }
return &h2Conn{ return &h2Conn{
Conn: conn, Conn: conn,
ClientConn: cconn, Http2ClientConn: cconn,
cfg: cfg, cfg: cfg,
}, nil }, nil
} }

View File

@ -5,11 +5,11 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"net" "net"
"net/http"
"net/textproto" "net/textproto"
"github.com/metacubex/mihomo/common/utils" "github.com/metacubex/mihomo/common/utils"
"github.com/metacubex/http"
"github.com/metacubex/randv2" "github.com/metacubex/randv2"
) )

View File

@ -2,13 +2,14 @@ package vmess
import ( import (
"context" "context"
"crypto/tls"
"errors" "errors"
"net" "net"
"github.com/metacubex/mihomo/component/ca" "github.com/metacubex/mihomo/component/ca"
"github.com/metacubex/mihomo/component/ech" "github.com/metacubex/mihomo/component/ech"
tlsC "github.com/metacubex/mihomo/component/tls" tlsC "github.com/metacubex/mihomo/component/tls"
"github.com/metacubex/tls"
) )
type TLSConfig struct { type TLSConfig struct {
@ -44,7 +45,7 @@ func StreamTLSConn(ctx context.Context, conn net.Conn, cfg *TLSConfig) (net.Conn
if clientFingerprint, ok := tlsC.GetFingerprint(cfg.ClientFingerprint); ok { if clientFingerprint, ok := tlsC.GetFingerprint(cfg.ClientFingerprint); ok {
tlsConfig := tlsC.UConfig(tlsConfig) tlsConfig := tlsC.UConfig(tlsConfig)
err = cfg.ECH.ClientHandle(ctx, tlsConfig) err = cfg.ECH.ClientHandleUTLS(ctx, tlsConfig)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -66,7 +67,7 @@ func StreamTLSConn(ctx context.Context, conn net.Conn, cfg *TLSConfig) (net.Conn
if cfg.ECH != nil { if cfg.ECH != nil {
tlsConfig := tlsC.UConfig(tlsConfig) tlsConfig := tlsC.UConfig(tlsConfig)
err = cfg.ECH.ClientHandle(ctx, tlsConfig) err = cfg.ECH.ClientHandleUTLS(ctx, tlsConfig)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -5,14 +5,12 @@ import (
"bytes" "bytes"
"context" "context"
"crypto/rand" "crypto/rand"
"crypto/tls"
"encoding/base64" "encoding/base64"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"net" "net"
"net/http"
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
@ -26,7 +24,9 @@ import (
"github.com/gobwas/ws" "github.com/gobwas/ws"
"github.com/gobwas/ws/wsutil" "github.com/gobwas/ws/wsutil"
"github.com/metacubex/http"
"github.com/metacubex/randv2" "github.com/metacubex/randv2"
"github.com/metacubex/tls"
) )
type websocketConn struct { type websocketConn struct {
@ -357,7 +357,7 @@ func streamWebsocketConn(ctx context.Context, conn net.Conn, c *WebsocketConfig,
if clientFingerprint, ok := tlsC.GetFingerprint(c.ClientFingerprint); ok { if clientFingerprint, ok := tlsC.GetFingerprint(c.ClientFingerprint); ok {
tlsConfig := tlsC.UConfig(config) tlsConfig := tlsC.UConfig(config)
err = c.ECHConfig.ClientHandle(ctx, tlsConfig) err = c.ECHConfig.ClientHandleUTLS(ctx, tlsConfig)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -372,7 +372,7 @@ func streamWebsocketConn(ctx context.Context, conn net.Conn, c *WebsocketConfig,
conn = tlsConn conn = tlsConn
} else if c.ECHConfig != nil { } else if c.ECHConfig != nil {
tlsConfig := tlsC.UConfig(config) tlsConfig := tlsC.UConfig(config)
err = c.ECHConfig.ClientHandle(ctx, tlsConfig) err = c.ECHConfig.ClientHandleUTLS(ctx, tlsConfig)
if err != nil { if err != nil {
return nil, err return nil, err
} }