feat: implement clientFingerprint for anytls client

This commit is contained in:
anytls 2025-02-16 22:30:09 +09:00
parent cfdb6a24e6
commit 952f286e5f
2 changed files with 48 additions and 13 deletions

View file

@ -13,6 +13,7 @@ import (
"github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/component/proxydialer"
"github.com/metacubex/mihomo/component/resolver"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/transport/anytls"
"github.com/sagernet/sing/common"
@ -101,6 +102,7 @@ func NewAnyTLS(option AnyTLSOption) (*AnyTLS, error) {
Dialer: singDialer,
IdleSessionCheckInterval: time.Duration(option.IdleSessionCheckInterval) * time.Second,
IdleSessionTimeout: time.Duration(option.IdleSessionTimeout) * time.Second,
ClientFingerprint: option.ClientFingerprint,
}
tlsConfig := &tls.Config{
ServerName: option.SNI,
@ -112,6 +114,10 @@ func NewAnyTLS(option AnyTLSOption) (*AnyTLS, error) {
}
tOption.TLSConfig = tlsConfig
if tlsC.HaveGlobalFingerprint() && len(tOption.ClientFingerprint) == 0 {
tOption.ClientFingerprint = tlsC.GetGlobalFingerprint()
}
outbound := &AnyTLS{
Base: &Base{
name: option.Name,

View file

@ -8,8 +8,11 @@ import (
"net"
"time"
tlsC "github.com/metacubex/mihomo/component/tls"
C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/transport/anytls/padding"
"github.com/metacubex/mihomo/transport/anytls/session"
"github.com/metacubex/mihomo/transport/vmess"
"github.com/sagernet/sing/common/atomic"
"github.com/sagernet/sing/common/buf"
M "github.com/sagernet/sing/common/metadata"
@ -23,24 +26,27 @@ type ClientConfig struct {
Server M.Socksaddr
Dialer N.Dialer
TLSConfig *tls.Config
ClientFingerprint string
}
type Client struct {
passwordSha256 []byte
tlsConfig *tls.Config
dialer N.Dialer
server M.Socksaddr
sessionClient *session.Client
padding atomic.TypedValue[*padding.PaddingFactory]
passwordSha256 []byte
tlsConfig *tls.Config
clientFingerprint string
dialer N.Dialer
server M.Socksaddr
sessionClient *session.Client
padding atomic.TypedValue[*padding.PaddingFactory]
}
func NewClient(ctx context.Context, config ClientConfig) *Client {
pw := sha256.Sum256([]byte(config.Password))
c := &Client{
passwordSha256: pw[:],
tlsConfig: config.TLSConfig,
dialer: config.Dialer,
server: config.Server,
passwordSha256: pw[:],
tlsConfig: config.TLSConfig,
clientFingerprint: config.ClientFingerprint,
dialer: config.Dialer,
server: config.Server,
}
// Initialize the padding state of this client
padding.UpdatePaddingScheme(padding.DefaultPaddingScheme, &c.padding)
@ -78,15 +84,38 @@ func (c *Client) CreateOutboundTLSConnection(ctx context.Context) (net.Conn, err
b.WriteZeroN(paddingLen)
}
conn = tls.Client(conn, c.tlsConfig)
getTlsConn := func() (net.Conn, error) {
if len(c.clientFingerprint) != 0 {
utlsConn, valid := vmess.GetUTLSConn(conn, c.clientFingerprint, c.tlsConfig)
if valid {
ctx, cancel := context.WithTimeout(ctx, C.DefaultTLSTimeout)
defer cancel()
_, err = b.WriteTo(conn)
err := utlsConn.(*tlsC.UConn).HandshakeContext(ctx)
return utlsConn, err
}
}
tlsConn := tls.Client(conn, c.tlsConfig)
ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
defer cancel()
err = tlsConn.HandshakeContext(ctx)
return tlsConn, err
}
tlsConn, err := getTlsConn()
if err != nil {
conn.Close()
return nil, err
}
return conn, nil
_, err = b.WriteTo(tlsConn)
if err != nil {
tlsConn.Close()
return nil, err
}
return tlsConn, nil
}
func (h *Client) Close() error {