Support ServerName randomization (by setting ServerName=random) using the same algorithm as ProtonVPN bcf344b39b

pull/242/head
notsure2 11 months ago committed by Andy Wang
parent a848d2f7e5
commit 3b449b64b3
No known key found for this signature in database
GPG Key ID: 181B49F9F38F3374

@ -137,7 +137,7 @@ random-like. **You may only leave it as `plain` if you are certain that your und
encryption and authentication (via AEAD or similar techniques).**
`ServerName` is the domain you want to make your ISP or firewall _think_ you are visiting. Ideally it should
match `RedirAddr` in the server's configuration, a major site the censor allows, but it doesn't have to.
match `RedirAddr` in the server's configuration, a major site the censor allows, but it doesn't have to. Use `random` to randomize the server name for every connection made.
`AlternativeNames` is an array used alongside `ServerName` to shuffle between different ServerNames for every new
connection. **This may conflict with `CDN` Transport mode** if the CDN provider prohibits domain fronting and rejects

@ -1,9 +1,14 @@
package client
import (
cryptoRand "crypto/rand"
utls "github.com/refraction-networking/utls"
log "github.com/sirupsen/logrus"
"math/big"
"math/rand"
"net"
"strings"
"time"
"github.com/cbeuw/Cloak/internal/common"
)
@ -30,6 +35,33 @@ type DirectTLS struct {
browser browser
}
var topLevelDomains = []string{"com", "net", "org", "it", "fr", "me", "ru", "cn", "es", "tr", "top", "xyz", "info"}
// https://github.com/ProtonVPN/wireguard-go/commit/bcf344b39b213c1f32147851af0d2a8da9266883
func randomServerName() string {
charNum := int('z') - int('a') + 1
size := 3 + randInt(10)
name := make([]byte, size)
for i := range name {
name[i] = byte(int('a') + randInt(charNum))
}
return string(name) + "." + randItem(topLevelDomains)
}
func randItem(list []string) string {
return list[randInt(len(list))]
}
func randInt(n int) int {
size, err := cryptoRand.Int(cryptoRand.Reader, big.NewInt(int64(n)))
if err == nil {
return int(size.Int64())
}
//goland:noinspection GoDeprecation
rand.Seed(time.Now().UnixNano())
return rand.Intn(n)
}
func buildClientHello(browser browser, fields clientHelloFields) ([]byte, error) {
// We don't use utls to handle connections (as it'll attempt a real TLS negotiation)
// We only want it to build the ClientHello locally
@ -89,6 +121,10 @@ func (tls *DirectTLS) Handshake(rawConn net.Conn, authInfo AuthInfo) (sessionKey
serverName: authInfo.MockDomain,
}
if strings.EqualFold(fields.serverName, "random") {
fields.serverName = randomServerName()
}
var ch []byte
ch, err = buildClientHello(tls.browser, fields)
if err != nil {

Loading…
Cancel
Save