Compare commits

..
1 Commits
Author SHA1 Message Date
Fangliding 4add189c24 little refine 2026-04-27 12:42:00 +08:00
2 changed files with 18 additions and 27 deletions
+8 -12
View File
@@ -17,7 +17,7 @@ import (
type Holder struct { type Holder struct {
domainToIP cache.Lru domainToIP cache.Lru
ipRange *net.IPNet ipRange *net.IPNet
mu *sync.Mutex mu sync.Mutex
config *FakeDnsPool config *FakeDnsPool
} }
@@ -49,9 +49,7 @@ func (fkdns *Holder) Start() error {
} }
func (fkdns *Holder) Close() error { func (fkdns *Holder) Close() error {
fkdns.domainToIP = nil // nothing to do for now, just wait GC
fkdns.ipRange = nil
fkdns.mu = nil
return nil return nil
} }
@@ -70,7 +68,7 @@ func NewFakeDNSHolder() (*Holder, error) {
} }
func NewFakeDNSHolderConfigOnly(conf *FakeDnsPool) (*Holder, error) { func NewFakeDNSHolderConfigOnly(conf *FakeDnsPool) (*Holder, error) {
return &Holder{nil, nil, nil, conf}, nil return &Holder{config: conf}, nil
} }
func (fkdns *Holder) initializeFromConfig() error { func (fkdns *Holder) initializeFromConfig() error {
@@ -92,7 +90,6 @@ func (fkdns *Holder) initialize(ipPoolCidr string, lruSize int) error {
} }
fkdns.domainToIP = cache.NewLru(lruSize) fkdns.domainToIP = cache.NewLru(lruSize)
fkdns.ipRange = ipRange fkdns.ipRange = ipRange
fkdns.mu = new(sync.Mutex)
return nil return nil
} }
@@ -103,7 +100,7 @@ func (fkdns *Holder) GetFakeIPForDomain(domain string) []net.Address {
if v, ok := fkdns.domainToIP.Get(domain); ok { if v, ok := fkdns.domainToIP.Get(domain); ok {
return []net.Address{v.(net.Address)} return []net.Address{v.(net.Address)}
} }
currentTimeMillis := uint64(time.Now().UnixNano() / 1e6) currentTimeMillis := uint64(time.Now().UnixMilli())
ones, bits := fkdns.ipRange.Mask.Size() ones, bits := fkdns.ipRange.Mask.Size()
rooms := bits - ones rooms := bits - ones
if rooms < 64 { if rooms < 64 {
@@ -202,12 +199,11 @@ func (h *HolderMulti) Start() error {
} }
func (h *HolderMulti) Close() error { func (h *HolderMulti) Close() error {
var errs []error
for _, v := range h.holders { for _, v := range h.holders {
if err := v.Close(); err != nil { errs = append(errs, v.Close())
return errors.New("Cannot close all fake dns pools").Base(err)
}
} }
return nil return errors.Combine(errs...)
} }
func (h *HolderMulti) createHolderGroups() error { func (h *HolderMulti) createHolderGroups() error {
@@ -222,7 +218,7 @@ func (h *HolderMulti) createHolderGroups() error {
} }
func NewFakeDNSHolderMulti(conf *FakeDnsPoolMulti) (*HolderMulti, error) { func NewFakeDNSHolderMulti(conf *FakeDnsPoolMulti) (*HolderMulti, error) {
holderMulti := &HolderMulti{nil, conf} holderMulti := &HolderMulti{config: conf}
if err := holderMulti.createHolderGroups(); err != nil { if err := holderMulti.createHolderGroups(); err != nil {
return nil, err return nil, err
} }
+10 -15
View File
@@ -5,7 +5,6 @@ import (
"crypto/rand" "crypto/rand"
"crypto/tls" "crypto/tls"
"math/big" "math/big"
"slices"
"time" "time"
utls "github.com/refraction-networking/utls" utls "github.com/refraction-networking/utls"
@@ -91,24 +90,18 @@ func (c *UConn) HandshakeContextServerName(ctx context.Context) string {
return c.ConnectionState().ServerName return c.ConnectionState().ServerName
} }
// WebsocketHandshakeContext basically calls UConn.Handshake inside it but it will try // WebsocketHandshake basically calls UConn.Handshake inside it but it will only send
// to build outer ALPN to `http/1.1` or `h2 http/1.1` (if manually specified for camouflage) // http/1.1 in its ALPN.
func (c *UConn) WebsocketHandshakeContext(ctx context.Context) error { func (c *UConn) WebsocketHandshakeContext(ctx context.Context) error {
config := *utils.AccessField[*utls.Config](c, "config")
ALPN := slices.Clone(config.NextProtos)
// set other kinds of ALPN to http/1.1
if !slices.Equal(ALPN, []string{"h2", "http/1.1"}) {
ALPN = []string{"http/1.1"}
}
// Build the handshake state. This will apply every variable of the TLS of the // Build the handshake state. This will apply every variable of the TLS of the
// fingerprint in the UConn // fingerprint in the UConn
if err := c.BuildHandshakeState(); err != nil { if err := c.BuildHandshakeState(); err != nil {
return err return err
} }
// Do not modify outer ALPN if ECH is used config := *utils.AccessField[*utls.Config](c, "config")
// Outer ALPN will be h2,http/1.1, and real http/1.1 in config will be hidden in ECH // Do not modify outer ALPN to http/1.1 if ECH is used
// Outer ALPN will be h2,http/1.1, and real ALPN in config will be hidden in ECH
if config.EncryptedClientHelloConfigList != nil { if config.EncryptedClientHelloConfigList != nil {
config.NextProtos = []string{"http/1.1"}
return c.HandshakeContext(ctx) return c.HandshakeContext(ctx)
} }
// Iterate over extensions and check for utls.ALPNExtension // Iterate over extensions and check for utls.ALPNExtension
@@ -116,12 +109,12 @@ func (c *UConn) WebsocketHandshakeContext(ctx context.Context) error {
for _, extension := range c.Extensions { for _, extension := range c.Extensions {
if alpn, ok := extension.(*utls.ALPNExtension); ok { if alpn, ok := extension.(*utls.ALPNExtension); ok {
hasALPNExtension = true hasALPNExtension = true
alpn.AlpnProtocols = ALPN alpn.AlpnProtocols = []string{"http/1.1"}
break break
} }
} }
if !hasALPNExtension { // Append extension if doesn't exists if !hasALPNExtension { // Append extension if doesn't exists
c.Extensions = append(c.Extensions, &utls.ALPNExtension{AlpnProtocols: ALPN}) c.Extensions = append(c.Extensions, &utls.ALPNExtension{AlpnProtocols: []string{"http/1.1"}})
} }
// Rebuild the client hello and do the handshake // Rebuild the client hello and do the handshake
if err := c.BuildHandshakeState(); err != nil { if err := c.BuildHandshakeState(); err != nil {
@@ -153,7 +146,9 @@ func copyConfig(c *tls.Config) *utls.Config {
VerifyPeerCertificate: c.VerifyPeerCertificate, VerifyPeerCertificate: c.VerifyPeerCertificate,
KeyLogWriter: c.KeyLogWriter, KeyLogWriter: c.KeyLogWriter,
EncryptedClientHelloConfigList: c.EncryptedClientHelloConfigList, EncryptedClientHelloConfigList: c.EncryptedClientHelloConfigList,
NextProtos: c.NextProtos, }
if config.EncryptedClientHelloConfigList != nil {
config.NextProtos = c.NextProtos
} }
return config return config
} }