Skip to content

Commit

Permalink
basic sni padding wip
Browse files Browse the repository at this point in the history
  • Loading branch information
mosajjal committed Jan 13, 2024
1 parent b321d21 commit 5c3f9f7
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 6 deletions.
24 changes: 20 additions & 4 deletions common/tls/utls_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
type UTLSClientConfig struct {
config *utls.Config
paddingSize [2]int
paddingSNI string
id utls.ClientHelloID
}

Expand Down Expand Up @@ -52,13 +53,22 @@ func (e *UTLSClientConfig) Config() (*STDConfig, error) {
func (e *UTLSClientConfig) Client(conn net.Conn) (Conn, error) {
var uConn *utls.UConn
if e.id != utls.HelloCustom {

uConn = utls.UClient(conn, e.config.Clone(), e.id)
} else {
var err error
uConn, err = makeTLSHelloPacketWithPadding(conn, e, e.config.ServerName)
if err != nil {
return nil, err

if e.paddingSNI != "" {
// TODO: add a flag to switch between random padding and smart padding
uConn, err = makeTLSHelloPacketWithSmartPadding(conn, e, e.config.ServerName, e.paddingSNI)
if err != nil {
return nil, err
}
} else {

uConn, err = makeTLSHelloPacketWithPadding(conn, e, e.config.ServerName)
if err != nil {
return nil, err
}
}
}
return &utlsALPNWrapper{utlsConnWrapper{UConn: uConn}, e.config.NextProtos}, nil
Expand Down Expand Up @@ -205,6 +215,12 @@ func NewUTLSClient(ctx context.Context, serverAddress string, options option.Out
if err != nil {
return nil, err
}

if options.PaddingSNI != "" {
// using smartpadding
return &UTLSClientConfig{config: &tlsConfig, paddingSNI: options.PaddingSNI, id: id}, nil
}

if options.PaddingSize != "" {
padding_size, err := option.ParseIntRange(options.PaddingSize)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion common/tls/utls_padding.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build with_utls
// go:build with_utls

package tls

Expand Down
133 changes: 133 additions & 0 deletions common/tls/utls_smartpadding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// go:build with_utls

package tls

import (
"io"
"net"

utls "github.com/sagernet/utls"
)

// FakeSmartPaddingExtension implements padding (0x15) extension. The padding data is another TLS client hello message
type FakeSmartPaddingExtension struct {
*utls.GenericExtension
// PaddingLen int
FakeSNI string
data []byte // the actual fake bytes that will be read
// WillPad bool // set false to disable extension
}

// Len returns the length of the FakeSmartPaddingExtension.
func (e *FakeSmartPaddingExtension) Len() int {
return 4 + len(e.data)
}

func NewFakeSmartPaddingExtension(fakesni string) *FakeSmartPaddingExtension {
conn := new(net.TCPConn)
uConn := utls.UClient(conn,
&utls.Config{
ServerName: fakesni,
},
utls.HelloRandomizedALPN)
// create a new TLS client hello with a fake SNI
c := utls.ClientHelloSpec{
TLSVersMax: utls.VersionTLS13,
TLSVersMin: utls.VersionTLS10,
CipherSuites: []uint16{
utls.GREASE_PLACEHOLDER, // GREASE
utls.TLS_AES_128_GCM_SHA256,
utls.TLS_AES_256_GCM_SHA384,
utls.TLS_CHACHA20_POLY1305_SHA256,
utls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
utls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
utls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
utls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
utls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
utls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
},
Extensions: []utls.TLSExtension{
&SNIExtension{
ServerName: fakesni,
},
},
}
_ = uConn.ApplyPreset(&c)
_ = uConn.MarshalClientHello()
rawHello := uConn.HandshakeState.Hello.Raw

return &FakeSmartPaddingExtension{
FakeSNI: fakesni,
data: rawHello,
}
}

// Read reads the FakeSmartPaddingExtension.
func (e *FakeSmartPaddingExtension) Read(b []byte) (n int, err error) {
if len(b) < e.Len() {
return 0, io.ErrShortBuffer
}
// https://tools.ietf.org/html/rfc7627
b[0] = byte(tlsExtensionPadding >> 8)
b[1] = byte(tlsExtensionPadding)
b[2] = byte(len(e.data) >> 8)
b[3] = byte(len(e.data))

copy(b[4:], e.data)
return e.Len(), io.EOF
}

// makeTLSHelloPacketWithSmartPadding creates a TLS hello packet with padding that looks like another TLS client hello with a given fake SNI
func makeTLSHelloPacketWithSmartPadding(conn net.Conn, e *UTLSClientConfig, sni string, fakesni string) (*utls.UConn, error) {

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / Debug build (Go 1.20)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (darwin-arm64, darwin, arm64)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (freebsd-amd64, freebsd, amd64, v1)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-arm64, linux, arm64)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-armv5, linux, arm, 5)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-mips64el, linux, mips64le)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-amd64, linux, amd64, v1)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-armv6, linux, arm, 6)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-mipsel-softfloat, linux, mipsle, softfloat)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (darwin-amd64, darwin, amd64, v1)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (freebsd-arm64, freebsd, arm64)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-mips64, linux, mips64)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-armv7, linux, arm, 7)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-mipsel-hardfloat, linux, mipsle, hardfloat)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (freebsd-amd64-v3, freebsd, amd64, v3)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (freebsd-386, freebsd, 386)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-amd64-v3, linux, amd64, v3)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-386, linux, 386)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / Debug build

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (darwin-amd64-v3, darwin, amd64, v3)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-mips-hardfloat, linux, mips, hardfloat)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-mips-softfloat, linux, mips, softfloat)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (linux-s390x, linux, s390x)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (windows-arm32v7, windows, arm, 7)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (windows-arm64, windows, arm64)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (windows-amd64, windows, amd64, v1)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (windows-386, windows, 386)

undefined: UTLSClientConfig

Check failure on line 81 in common/tls/utls_smartpadding.go

View workflow job for this annotation

GitHub Actions / cross (windows-amd64-v3, windows, amd64, v3)

undefined: UTLSClientConfig

uConn := utls.UClient(conn, e.config.Clone(), e.id)

spec := utls.ClientHelloSpec{
TLSVersMax: utls.VersionTLS13,
TLSVersMin: utls.VersionTLS10,
CipherSuites: []uint16{
utls.GREASE_PLACEHOLDER,
utls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
utls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
utls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
utls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
utls.TLS_AES_128_GCM_SHA256, // tls 1.3
utls.FAKE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
utls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
utls.TLS_RSA_WITH_AES_256_CBC_SHA,
},
Extensions: []utls.TLSExtension{
&utls.SupportedCurvesExtension{Curves: []utls.CurveID{utls.X25519, utls.CurveP256}},
&utls.SupportedPointsExtension{SupportedPoints: []byte{0}}, // uncompressed
&utls.SessionTicketExtension{},
&utls.ALPNExtension{AlpnProtocols: []string{"http/1.1"}},
&utls.SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []utls.SignatureScheme{
utls.ECDSAWithP256AndSHA256,
utls.ECDSAWithP384AndSHA384,
utls.ECDSAWithP521AndSHA512,
utls.PSSWithSHA256,
utls.PSSWithSHA384,
utls.PSSWithSHA512,
utls.PKCS1WithSHA256,
utls.PKCS1WithSHA384,
utls.PKCS1WithSHA512,
utls.ECDSAWithSHA1,
utls.PKCS1WithSHA1}},
&utls.KeyShareExtension{KeyShares: []utls.KeyShare{
{Group: utls.CurveID(utls.GREASE_PLACEHOLDER), Data: []byte{0}},
{Group: utls.X25519},
}},
&utls.PSKKeyExchangeModesExtension{Modes: []uint8{1}}, // pskModeDHE
NewFakeSmartPaddingExtension(fakesni),
&SNIExtension{
ServerName: sni,
},
},
GetSessionID: nil,
}
err := uConn.ApplyPreset(&spec)
if err != nil {
return nil, err
}
return uConn, nil
}
3 changes: 2 additions & 1 deletion option/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ type OutboundTLSOptions struct {
MixedCaseSNI bool `json:"mixedcase_sni,omitempty"`
ServerName string `json:"server_name,omitempty"`
Insecure bool `json:"insecure,omitempty"`
PaddingSize string `json:"padding_size,omitempty"`
PaddingSize string `json:"padding_size,omitempty"` // uses a random bytearray as padding. mutually exclusive with padding_sni
PaddingSNI string `json:"padding_sni,omitempty"` // uses smartpadding which creates a client hello as padding
ALPN Listable[string] `json:"alpn,omitempty"`
MinVersion string `json:"min_version,omitempty"`
MaxVersion string `json:"max_version,omitempty"`
Expand Down

0 comments on commit 5c3f9f7

Please sign in to comment.