mirror of https://github.com/cbeuw/Cloak
Refactor client TLS
This commit is contained in:
parent
33f232475d
commit
1a628cb524
|
|
@ -16,7 +16,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cbeuw/Cloak/internal/client"
|
"github.com/cbeuw/Cloak/internal/client"
|
||||||
"github.com/cbeuw/Cloak/internal/client/TLS"
|
|
||||||
mux "github.com/cbeuw/Cloak/internal/multiplex"
|
mux "github.com/cbeuw/Cloak/internal/multiplex"
|
||||||
"github.com/cbeuw/Cloak/internal/util"
|
"github.com/cbeuw/Cloak/internal/util"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
@ -51,7 +50,7 @@ func makeRemoteConn(sta *client.State) (net.Conn, []byte, error) {
|
||||||
// For android
|
// For android
|
||||||
d := net.Dialer{Control: protector}
|
d := net.Dialer{Control: protector}
|
||||||
|
|
||||||
clientHello, sharedSecret := TLS.ComposeClientHello(sta)
|
clientHello, sharedSecret := client.ComposeClientHello(sta)
|
||||||
connectingIP := sta.RemoteHost
|
connectingIP := sta.RemoteHost
|
||||||
if net.ParseIP(connectingIP).To4() == nil {
|
if net.ParseIP(connectingIP).To4() == nil {
|
||||||
// IPv6 needs square brackets
|
// IPv6 needs square brackets
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
package TLS
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"github.com/cbeuw/Cloak/internal/client"
|
|
||||||
"github.com/cbeuw/Cloak/internal/util"
|
"github.com/cbeuw/Cloak/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type browser interface {
|
type Browser interface {
|
||||||
composeClientHello()
|
composeClientHello(*State) ([]byte, []byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeServerName(serverName string) []byte {
|
func makeServerName(serverName string) []byte {
|
||||||
|
|
@ -43,16 +42,8 @@ func addExtRec(typ []byte, data []byte) []byte {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// ComposeInitHandshake composes ClientHello with record layer
|
// ComposeClientHello composes ClientHello with record layer
|
||||||
func ComposeInitHandshake(sta *client.State) ([]byte, []byte) {
|
func ComposeClientHello(sta *State) ([]byte, []byte) {
|
||||||
var ch, sharedSecret []byte
|
ch, sharedSecret := sta.Browser.composeClientHello(sta)
|
||||||
switch sta.BrowserSig {
|
|
||||||
case "chrome":
|
|
||||||
ch, sharedSecret = (&chrome{}).composeClientHello(sta)
|
|
||||||
case "firefox":
|
|
||||||
ch, sharedSecret = (&firefox{}).composeClientHello(sta)
|
|
||||||
default:
|
|
||||||
panic("Unsupported browser:" + sta.BrowserSig)
|
|
||||||
}
|
|
||||||
return util.AddRecordLayer(ch, []byte{0x16}, []byte{0x03, 0x01}), sharedSecret
|
return util.AddRecordLayer(ch, []byte{0x16}, []byte{0x03, 0x01}), sharedSecret
|
||||||
}
|
}
|
||||||
|
|
@ -1,23 +1,19 @@
|
||||||
// Chrome 76
|
// Chrome 76
|
||||||
|
|
||||||
package TLS
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cbeuw/Cloak/internal/client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type chrome struct {
|
type Chrome struct{}
|
||||||
browser
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeGREASE() []byte {
|
func makeGREASE() []byte {
|
||||||
// see https://tools.ietf.org/html/draft-davidben-tls-grease-01
|
// see https://tools.ietf.org/html/draft-davidben-tls-grease-01
|
||||||
// This is exclusive to chrome.
|
// This is exclusive to Chrome.
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
sixteenth := rand.Intn(16)
|
sixteenth := rand.Intn(16)
|
||||||
monoGREASE := byte(sixteenth*16 + 0xA)
|
monoGREASE := byte(sixteenth*16 + 0xA)
|
||||||
|
|
@ -25,7 +21,7 @@ func makeGREASE() []byte {
|
||||||
return doubleGREASE
|
return doubleGREASE
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *chrome) composeExtensions(sta *client.State, keyShare []byte) []byte {
|
func (c *Chrome) composeExtensions(serverName string, keyShare []byte) []byte {
|
||||||
|
|
||||||
makeSupportedGroups := func() []byte {
|
makeSupportedGroups := func() []byte {
|
||||||
suppGroupListLen := []byte{0x00, 0x08}
|
suppGroupListLen := []byte{0x00, 0x08}
|
||||||
|
|
@ -52,7 +48,7 @@ func (c *chrome) composeExtensions(sta *client.State, keyShare []byte) []byte {
|
||||||
|
|
||||||
var ext [17][]byte
|
var ext [17][]byte
|
||||||
ext[0] = addExtRec(makeGREASE(), nil) // First GREASE
|
ext[0] = addExtRec(makeGREASE(), nil) // First GREASE
|
||||||
ext[1] = addExtRec([]byte{0x00, 0x00}, makeServerName(sta.ServerName)) // server name indication
|
ext[1] = addExtRec([]byte{0x00, 0x00}, makeServerName(serverName)) // server name indication
|
||||||
ext[2] = addExtRec([]byte{0x00, 0x17}, nil) // extended_master_secret
|
ext[2] = addExtRec([]byte{0x00, 0x17}, nil) // extended_master_secret
|
||||||
ext[3] = addExtRec([]byte{0xff, 0x01}, []byte{0x00}) // renegotiation_info
|
ext[3] = addExtRec([]byte{0xff, 0x01}, []byte{0x00}) // renegotiation_info
|
||||||
ext[4] = addExtRec([]byte{0x00, 0x0a}, makeSupportedGroups()) // supported groups
|
ext[4] = addExtRec([]byte{0x00, 0x0a}, makeSupportedGroups()) // supported groups
|
||||||
|
|
@ -83,8 +79,8 @@ func (c *chrome) composeExtensions(sta *client.State, keyShare []byte) []byte {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *chrome) composeClientHello(sta *client.State) ([]byte, []byte) {
|
func (c *Chrome) composeClientHello(sta *State) (ch []byte, sharedSecret []byte) {
|
||||||
random, sessionID, keyShare, sharedSecret := client.MakeHiddenData(sta)
|
random, sessionID, keyShare, sharedSecret := MakeHiddenData(sta)
|
||||||
var clientHello [12][]byte
|
var clientHello [12][]byte
|
||||||
clientHello[0] = []byte{0x01} // handshake type
|
clientHello[0] = []byte{0x01} // handshake type
|
||||||
clientHello[1] = []byte{0x00, 0x01, 0xfc} // length 508
|
clientHello[1] = []byte{0x00, 0x01, 0xfc} // length 508
|
||||||
|
|
@ -97,7 +93,7 @@ func (c *chrome) composeClientHello(sta *client.State) ([]byte, []byte) {
|
||||||
clientHello[7] = append(makeGREASE(), cipherSuites...) // cipher suites
|
clientHello[7] = append(makeGREASE(), cipherSuites...) // cipher suites
|
||||||
clientHello[8] = []byte{0x01} // compression methods length 1
|
clientHello[8] = []byte{0x01} // compression methods length 1
|
||||||
clientHello[9] = []byte{0x00} // compression methods
|
clientHello[9] = []byte{0x00} // compression methods
|
||||||
clientHello[11] = c.composeExtensions(sta, keyShare)
|
clientHello[11] = c.composeExtensions(sta.ServerName, keyShare)
|
||||||
clientHello[10] = []byte{0x00, 0x00} // extensions length 401
|
clientHello[10] = []byte{0x00, 0x00} // extensions length 401
|
||||||
binary.BigEndian.PutUint16(clientHello[10], uint16(len(clientHello[11])))
|
binary.BigEndian.PutUint16(clientHello[10], uint16(len(clientHello[11])))
|
||||||
var ret []byte
|
var ret []byte
|
||||||
|
|
@ -1,19 +1,15 @@
|
||||||
// Firefox 68
|
// Firefox 68
|
||||||
package TLS
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
|
||||||
"github.com/cbeuw/Cloak/internal/client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type firefox struct {
|
type Firefox struct{}
|
||||||
browser
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *firefox) composeExtensions(serverName string, keyShare []byte) []byte {
|
func (f *Firefox) composeExtensions(serverName string, keyShare []byte) []byte {
|
||||||
composeKeyShare := func(hidden []byte) []byte {
|
composeKeyShare := func(hidden []byte) []byte {
|
||||||
ret := make([]byte, 107)
|
ret := make([]byte, 107)
|
||||||
ret[0], ret[1] = 0x00, 0x69 // length 105
|
ret[0], ret[1] = 0x00, 0x69 // length 105
|
||||||
|
|
@ -54,8 +50,8 @@ func (f *firefox) composeExtensions(serverName string, keyShare []byte) []byte {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *firefox) composeClientHello(sta *client.State) ([]byte, []byte) {
|
func (f *Firefox) composeClientHello(sta *State) (ch []byte, sharedSecret []byte) {
|
||||||
random, sessionID, keyShare, sharedSecret := client.MakeHiddenData(sta)
|
random, sessionID, keyShare, sharedSecret := MakeHiddenData(sta)
|
||||||
|
|
||||||
var clientHello [12][]byte
|
var clientHello [12][]byte
|
||||||
clientHello[0] = []byte{0x01} // handshake type
|
clientHello[0] = []byte{0x01} // handshake type
|
||||||
|
|
@ -35,10 +35,11 @@ type State struct {
|
||||||
staticPub crypto.PublicKey
|
staticPub crypto.PublicKey
|
||||||
IsAdmin bool
|
IsAdmin bool
|
||||||
|
|
||||||
|
Browser Browser
|
||||||
|
|
||||||
ProxyMethod string
|
ProxyMethod string
|
||||||
EncryptionMethod byte
|
EncryptionMethod byte
|
||||||
ServerName string
|
ServerName string
|
||||||
BrowserSig string
|
|
||||||
NumConn int
|
NumConn int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,7 +101,7 @@ func (sta *State) ParseConfig(conf string) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch preParse.EncryptionMethod {
|
switch strings.ToLower(preParse.EncryptionMethod) {
|
||||||
case "plain":
|
case "plain":
|
||||||
sta.EncryptionMethod = 0x00
|
sta.EncryptionMethod = 0x00
|
||||||
case "aes-gcm":
|
case "aes-gcm":
|
||||||
|
|
@ -111,9 +112,17 @@ func (sta *State) ParseConfig(conf string) (err error) {
|
||||||
return errors.New("Unknown encryption method")
|
return errors.New("Unknown encryption method")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch strings.ToLower(preParse.BrowserSig) {
|
||||||
|
case "chrome":
|
||||||
|
sta.Browser = &Chrome{}
|
||||||
|
case "firefox":
|
||||||
|
sta.Browser = &Firefox{}
|
||||||
|
default:
|
||||||
|
return errors.New("unsupported browser signature")
|
||||||
|
}
|
||||||
|
|
||||||
sta.ProxyMethod = preParse.ProxyMethod
|
sta.ProxyMethod = preParse.ProxyMethod
|
||||||
sta.ServerName = preParse.ServerName
|
sta.ServerName = preParse.ServerName
|
||||||
sta.BrowserSig = preParse.BrowserSig
|
|
||||||
sta.NumConn = preParse.NumConn
|
sta.NumConn = preParse.NumConn
|
||||||
|
|
||||||
uid, err := base64.StdEncoding.DecodeString(preParse.UID)
|
uid, err := base64.StdEncoding.DecodeString(preParse.UID)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue