From f5964653c66008348b61f4846c214e60509b1278 Mon Sep 17 00:00:00 2001 From: uoosef Date: Wed, 24 Jan 2024 11:42:57 +0330 Subject: [PATCH] improve making account --- go.mod | 11 ++- go.sum | 38 ++++++-- warp/account.go | 37 +++++--- warp/tls.go | 233 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 297 insertions(+), 22 deletions(-) create mode 100644 warp/tls.go diff --git a/go.mod b/go.mod index dd297cd4f..b69dc358c 100644 --- a/go.mod +++ b/go.mod @@ -6,15 +6,20 @@ require ( github.com/MakeNowJust/heredoc/v2 v2.0.1 github.com/bepass-org/proxy v0.0.0-20240103080554-a7e12466f91f github.com/go-ini/ini v1.67.0 - golang.org/x/crypto v0.13.0 - golang.org/x/net v0.15.0 - golang.org/x/sys v0.12.0 + github.com/refraction-networking/utls v1.6.1 + golang.org/x/crypto v0.17.0 + golang.org/x/net v0.17.0 + golang.org/x/sys v0.15.0 golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 ) require ( + github.com/andybalholm/brotli v1.0.5 // indirect + github.com/cloudflare/circl v1.3.7 // indirect github.com/google/btree v1.0.1 // indirect + github.com/klauspost/compress v1.16.7 // indirect + github.com/quic-go/quic-go v0.37.4 // indirect github.com/stretchr/testify v1.8.4 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect ) diff --git a/go.sum b/go.sum index b3892ee87..fa2c8dff0 100644 --- a/go.sum +++ b/go.sum @@ -1,25 +1,51 @@ github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZYIR/J6A= github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/bepass-org/proxy v0.0.0-20240103080554-a7e12466f91f h1:pzRqHgMut0aqeU9q6Qp9mZsc7CFsEL57SQzKZP60u1I= github.com/bepass-org/proxy v0.0.0-20240103080554-a7e12466f91f/go.mod h1:RlF0oO3D6Ju6VYjtL1I6lVLdc3l8jA4ggleJc8S+P0Y= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +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/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +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/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= 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/quic-go/quic-go v0.37.4 h1:ke8B73yMCWGq9MfrCCAw0Uzdm7GaViC3i39dsIdDlH4= +github.com/quic-go/quic-go v0.37.4/go.mod h1:YsbH1r4mSHPJcLF4k4zruUkLBqctEMBDR6VPvcYjIsU= +github.com/refraction-networking/utls v1.6.1 h1:n1JG5karzdGWsI6iZmGrOv3SNzR4c+4M8J6KWGsk3lA= +github.com/refraction-networking/utls v1.6.1/go.mod h1:+EbcQOvQvXoFV9AEKbuGlljt1doLRKAVY1jJHe9EtDo= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/warp/account.go b/warp/account.go index b35c13a81..f2ec9afae 100644 --- a/warp/account.go +++ b/warp/account.go @@ -2,12 +2,13 @@ package warp import ( "bytes" - "crypto/tls" + "context" "encoding/json" "errors" "fmt" "io" "log" + "net" "net/http" "os" "path/filepath" @@ -53,18 +54,24 @@ func makeDefaultHeaders() map[string]string { } func makeClient() *http.Client { - return &http.Client{Transport: &http.Transport{ - // Match app's TLS config or API will reject us with code 403 error 1020 - TLSClientConfig: &tls.Config{ - MinVersion: tls.VersionTLS12, - MaxVersion: tls.VersionTLS12}, - ForceAttemptHTTP2: false, - // From http.DefaultTransport - MaxIdleConns: 100, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - }} + // Create a custom dialer using the TLS config + plainDialer := &net.Dialer{ + Timeout: 5 * time.Second, + KeepAlive: 5 * time.Second, + } + tlsDialer := Dialer{} + // Create a custom HTTP transport + transport := &http.Transport{ + DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + return tlsDialer.TLSDial(plainDialer, network, addr) + }, + } + + // Create a custom HTTP client using the transport + return &http.Client{ + Transport: transport, + // Other client configurations can be added here + } } func MergeMaps(maps ...map[string]string) map[string]string { @@ -466,6 +473,10 @@ func getWireguardConfig(privateKey, address1, address2, publicKey, endpoint stri buffer.WriteString(fmt.Sprintf("PublicKey = %s\n", publicKey)) buffer.WriteString("AllowedIPs = 0.0.0.0/0\n") buffer.WriteString("AllowedIPs = ::/0\n") + ip, err := randomIPFromRange("162.159.192.0/24") + if err == nil { + endpoint = ip.String() + ":8854" + } buffer.WriteString(fmt.Sprintf("Endpoint = %s\n", endpoint)) return buffer.String() diff --git a/warp/tls.go b/warp/tls.go new file mode 100644 index 000000000..d9e51b3a8 --- /dev/null +++ b/warp/tls.go @@ -0,0 +1,233 @@ +package warp + +import ( + "crypto/rand" + "fmt" + tls "github.com/refraction-networking/utls" + "io" + "net" +) + +// Dialer is a struct that holds various options for custom dialing. +type Dialer struct { +} + +const ( + extensionServerName uint16 = 0x0 + utlsExtensionSNICurve uint16 = 0x15 +) + +func hostnameInSNI(name string) string { + return name +} + +// SNIExtension implements server_name (0) +type SNIExtension struct { + *tls.GenericExtension + ServerName string // not an array because go crypto/tls doesn't support multiple SNIs +} + +// Len returns the length of the SNIExtension. +func (e *SNIExtension) Len() int { + // Literal IP addresses, absolute FQDNs, and empty strings are not permitted as SNI values. + // See RFC 6066, Section 3. + hostName := hostnameInSNI(e.ServerName) + if len(hostName) == 0 { + return 0 + } + return 4 + 2 + 1 + 2 + len(hostName) +} + +// Read reads the SNIExtension. +func (e *SNIExtension) Read(b []byte) (int, error) { + // Literal IP addresses, absolute FQDNs, and empty strings are not permitted as SNI values. + // See RFC 6066, Section 3. + hostName := hostnameInSNI(e.ServerName) + if len(hostName) == 0 { + return 0, io.EOF + } + if len(b) < e.Len() { + return 0, io.ErrShortBuffer + } + // RFC 3546, section 3.1 + b[0] = byte(extensionServerName >> 8) + b[1] = byte(extensionServerName) + b[2] = byte((len(hostName) + 5) >> 8) + b[3] = byte(len(hostName) + 5) + b[4] = byte((len(hostName) + 3) >> 8) + b[5] = byte(len(hostName) + 3) + // b[6] Server Name Type: host_name (0) + b[7] = byte(len(hostName) >> 8) + b[8] = byte(len(hostName)) + copy(b[9:], hostName) + return e.Len(), io.EOF +} + +// SNICurveExtension implements SNICurve (0x15) extension +type SNICurveExtension struct { + *tls.GenericExtension + SNICurveLen int + WillPad bool // set false to disable extension +} + +// Len returns the length of the SNICurveExtension. +func (e *SNICurveExtension) Len() int { + if e.WillPad { + return 4 + e.SNICurveLen + } + return 0 +} + +// Read reads the SNICurveExtension. +func (e *SNICurveExtension) Read(b []byte) (n int, err error) { + if !e.WillPad { + return 0, io.EOF + } + if len(b) < e.Len() { + return 0, io.ErrShortBuffer + } + // https://tools.ietf.org/html/rfc7627 + b[0] = byte(utlsExtensionSNICurve >> 8) + b[1] = byte(utlsExtensionSNICurve) + b[2] = byte(e.SNICurveLen >> 8) + b[3] = byte(e.SNICurveLen) + y := make([]byte, 1200) + copy(b[4:], y) + return e.Len(), io.EOF +} + +// makeTLSHelloPacketWithSNICurve creates a TLS hello packet with SNICurve. +func (d *Dialer) makeTLSHelloPacketWithSNICurve(plainConn net.Conn, config *tls.Config, sni string) (*tls.UConn, error) { + SNICurveSize := 1200 + + utlsConn := tls.UClient(plainConn, config, tls.HelloCustom) + spec := tls.ClientHelloSpec{ + TLSVersMax: tls.VersionTLS12, + TLSVersMin: tls.VersionTLS12, + CipherSuites: []uint16{ + tls.GREASE_PLACEHOLDER, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + tls.TLS_AES_128_GCM_SHA256, // tls 1.3 + tls.FAKE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_RSA_WITH_AES_256_CBC_SHA, + }, + Extensions: []tls.TLSExtension{ + &SNICurveExtension{ + SNICurveLen: SNICurveSize, + WillPad: true, + }, + &tls.SupportedCurvesExtension{Curves: []tls.CurveID{tls.X25519, tls.CurveP256}}, + &tls.SupportedPointsExtension{SupportedPoints: []byte{0}}, // uncompressed + &tls.SessionTicketExtension{}, + &tls.ALPNExtension{AlpnProtocols: []string{"http/1.1"}}, + &tls.SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []tls.SignatureScheme{ + tls.ECDSAWithP256AndSHA256, + tls.ECDSAWithP384AndSHA384, + tls.ECDSAWithP521AndSHA512, + tls.PSSWithSHA256, + tls.PSSWithSHA384, + tls.PSSWithSHA512, + tls.PKCS1WithSHA256, + tls.PKCS1WithSHA384, + tls.PKCS1WithSHA512, + tls.ECDSAWithSHA1, + tls.PKCS1WithSHA1}}, + &tls.KeyShareExtension{KeyShares: []tls.KeyShare{ + {Group: tls.CurveID(tls.GREASE_PLACEHOLDER), Data: []byte{0}}, + {Group: tls.X25519}, + }}, + &tls.PSKKeyExchangeModesExtension{Modes: []uint8{1}}, // pskModeDHE + &SNIExtension{ + ServerName: sni, + }, + }, + GetSessionID: nil, + } + err := utlsConn.ApplyPreset(&spec) + + if err != nil { + return nil, fmt.Errorf("uTlsConn.Handshake() error: %+v", err) + } + + err = utlsConn.Handshake() + + if err != nil { + return nil, fmt.Errorf("uTlsConn.Handshake() error: %+v", err) + } + + return utlsConn, nil +} + +func randomIPFromRange(cidr string) (net.IP, error) { + +GENERATE: + + ip, ipnet, err := net.ParseCIDR(cidr) + if err != nil { + return nil, err + } + + // The number of leading 1s in the mask + ones, _ := ipnet.Mask.Size() + quotient := ones / 8 + remainder := ones % 8 + + // create random 4-byte byte slice + r := make([]byte, 4) + _, err = rand.Read(r) + if err != nil { + return nil, err + } + + for i := 0; i <= quotient; i++ { + if i == quotient { + shifted := byte(r[i]) >> remainder + r[i] = ^ipnet.IP[i] & shifted + } else { + r[i] = ipnet.IP[i] + } + } + ip = net.IPv4(r[0], r[1], r[2], r[3]) + + if ip.Equal(ipnet.IP) /*|| ip.Equal(broadcast) */ { + // we got unlucky. The host portion of our ipv4 address was + // either all 0s (the network address) or all 1s (the broadcast address) + goto GENERATE + } + return ip, nil +} + +// TLSDial dials a TLS connection. +func (d *Dialer) TLSDial(plainDialer *net.Dialer, network, addr string) (net.Conn, error) { + sni, _, err := net.SplitHostPort(addr) + if err != nil { + return nil, err + } + ip, err := randomIPFromRange("141.101.113.0/24") + if err != nil { + return nil, err + } + plainConn, err := plainDialer.Dial(network, ip.String()+":443") + if err != nil { + return nil, err + } + + config := tls.Config{ + ServerName: sni, + InsecureSkipVerify: true, + NextProtos: nil, + MinVersion: tls.VersionTLS10, + } + + utlsConn, handshakeErr := d.makeTLSHelloPacketWithSNICurve(plainConn, &config, sni) + if handshakeErr != nil { + _ = plainConn.Close() + fmt.Println(handshakeErr) + return nil, handshakeErr + } + return utlsConn, nil +}