Merge pull request #78 from Snawoot/sni_control

SNI control
This commit is contained in:
Snawoot 2024-12-22 23:25:30 +02:00 committed by GitHub
commit abc91c4279
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 20 additions and 4 deletions

View file

@ -65,16 +65,18 @@ type ContextDialer interface {
type ProxyDialer struct { type ProxyDialer struct {
address stringCb address stringCb
tlsServerName stringCb tlsServerName stringCb
fakeSNI stringCb
auth stringCb auth stringCb
next ContextDialer next ContextDialer
intermediateWorkaround bool intermediateWorkaround bool
caPool *x509.CertPool caPool *x509.CertPool
} }
func NewProxyDialer(address, tlsServerName, auth stringCb, intermediateWorkaround bool, caPool *x509.CertPool, nextDialer ContextDialer) *ProxyDialer { func NewProxyDialer(address, tlsServerName, fakeSNI, auth stringCb, intermediateWorkaround bool, caPool *x509.CertPool, nextDialer ContextDialer) *ProxyDialer {
return &ProxyDialer{ return &ProxyDialer{
address: address, address: address,
tlsServerName: tlsServerName, tlsServerName: tlsServerName,
fakeSNI: fakeSNI,
auth: auth, auth: auth,
next: nextDialer, next: nextDialer,
intermediateWorkaround: intermediateWorkaround, intermediateWorkaround: intermediateWorkaround,
@ -109,7 +111,14 @@ func ProxyDialerFromURL(u *url.URL, next ContextDialer) (*ProxyDialer, error) {
password, _ := u.User.Password() password, _ := u.User.Password()
auth = WrapStringToCb(BasicAuthHeader(username, password)) auth = WrapStringToCb(BasicAuthHeader(username, password))
} }
return NewProxyDialer(WrapStringToCb(address), WrapStringToCb(tlsServerName), auth, false, nil, next), nil return NewProxyDialer(
WrapStringToCb(address),
WrapStringToCb(tlsServerName),
WrapStringToCb(tlsServerName),
auth,
false,
nil,
next), nil
} }
func (d *ProxyDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) { func (d *ProxyDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
@ -132,12 +141,16 @@ func (d *ProxyDialer) DialContext(ctx context.Context, network, address string)
if err != nil { if err != nil {
return nil, err return nil, err
} }
fakeSNI, err := d.fakeSNI()
if err != nil {
return nil, err
}
if uTLSServerName != "" { if uTLSServerName != "" {
// Custom cert verification logic: // Custom cert verification logic:
// DO NOT send SNI extension of TLS ClientHello // DO NOT send SNI extension of TLS ClientHello
// DO peer certificate verification against specified servername // DO peer certificate verification against specified servername
conn = tls.Client(conn, &tls.Config{ conn = tls.Client(conn, &tls.Config{
ServerName: "", ServerName: fakeSNI,
InsecureSkipVerify: true, InsecureSkipVerify: true,
VerifyConnection: func(cs tls.ConnectionState) error { VerifyConnection: func(cs tls.ConnectionState) error {
opts := x509.VerifyOptions{ opts := x509.VerifyOptions{

View file

@ -102,6 +102,7 @@ type CLIArgs struct {
initRetryInterval time.Duration initRetryInterval time.Duration
certChainWorkaround bool certChainWorkaround bool
caFile string caFile string
fakeSNI string
} }
func parse_args() *CLIArgs { func parse_args() *CLIArgs {
@ -147,6 +148,7 @@ func parse_args() *CLIArgs {
flag.BoolVar(&args.certChainWorkaround, "certchain-workaround", true, flag.BoolVar(&args.certChainWorkaround, "certchain-workaround", true,
"add bundled cross-signed intermediate cert to certchain to make it check out on old systems") "add bundled cross-signed intermediate cert to certchain to make it check out on old systems")
flag.StringVar(&args.caFile, "cafile", "", "use custom CA certificate bundle file") flag.StringVar(&args.caFile, "cafile", "", "use custom CA certificate bundle file")
flag.StringVar(&args.fakeSNI, "fake-SNI", "", "domain name to use as SNI in communications with servers")
flag.Parse() flag.Parse()
if args.country == "" { if args.country == "" {
arg_fail("Country can't be empty string.") arg_fail("Country can't be empty string.")
@ -223,7 +225,7 @@ func run() int {
// Dialing w/o SNI, receiving self-signed certificate, so skip verification. // Dialing w/o SNI, receiving self-signed certificate, so skip verification.
// Either way we'll validate certificate of actual proxy server. // Either way we'll validate certificate of actual proxy server.
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
ServerName: "", ServerName: args.fakeSNI,
InsecureSkipVerify: true, InsecureSkipVerify: true,
} }
seclient, err := se.NewSEClient(args.apiLogin, args.apiPassword, &http.Transport{ seclient, err := se.NewSEClient(args.apiLogin, args.apiPassword, &http.Transport{
@ -337,6 +339,7 @@ func run() int {
handlerDialer := dialer.NewProxyDialer( handlerDialer := dialer.NewProxyDialer(
dialer.WrapStringToCb(endpoint.NetAddr()), dialer.WrapStringToCb(endpoint.NetAddr()),
dialer.WrapStringToCb(fmt.Sprintf("%s0.%s", args.country, PROXY_SUFFIX)), dialer.WrapStringToCb(fmt.Sprintf("%s0.%s", args.country, PROXY_SUFFIX)),
dialer.WrapStringToCb(args.fakeSNI),
func() (string, error) { func() (string, error) {
return dialer.BasicAuthHeader(seclient.GetProxyCredentials()), nil return dialer.BasicAuthHeader(seclient.GetProxyCredentials()), nil
}, },