mirror of https://github.com/cbeuw/Cloak
Refactor client Config
This commit is contained in:
parent
2aa49ce543
commit
f30141b388
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type CLIConfig struct {
|
type CLIConfig struct {
|
||||||
client.RawConfig
|
client.Config
|
||||||
|
|
||||||
// LocalHost is the hostname or IP address to listen for incoming proxy client connections
|
// LocalHost is the hostname or IP address to listen for incoming proxy client connections
|
||||||
LocalHost string // jsonOptional
|
LocalHost string // jsonOptional
|
||||||
|
|
@ -111,7 +111,7 @@ type LocalConnConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (raw *CLIConfig) ProcessCLIConfig(worldState common.WorldState) (local LocalConnConfig, remote client.RemoteConnConfig, auth client.AuthInfo, err error) {
|
func (raw *CLIConfig) ProcessCLIConfig(worldState common.WorldState) (local LocalConnConfig, remote client.RemoteConnConfig, auth client.AuthInfo, err error) {
|
||||||
remote, auth, err = raw.RawConfig.ProcessRawConfig(worldState)
|
remote, auth, err = raw.Config.Process(worldState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ var privateKey, _ = base64.StdEncoding.DecodeString("SMWeC6VuZF8S/id65VuFQFlfa7h
|
||||||
var four = 4
|
var four = 4
|
||||||
var zero = 0
|
var zero = 0
|
||||||
|
|
||||||
var basicUDPConfig = client.RawConfig{
|
var basicUDPConfig = client.Config{
|
||||||
ServerName: "www.example.com",
|
ServerName: "www.example.com",
|
||||||
ProxyMethod: "openvpn",
|
ProxyMethod: "openvpn",
|
||||||
EncryptionMethod: "plain",
|
EncryptionMethod: "plain",
|
||||||
|
|
@ -92,7 +92,7 @@ var basicUDPConfig = client.RawConfig{
|
||||||
RemotePort: "9999",
|
RemotePort: "9999",
|
||||||
}
|
}
|
||||||
|
|
||||||
var basicTCPConfig = client.RawConfig{
|
var basicTCPConfig = client.Config{
|
||||||
ServerName: "www.example.com",
|
ServerName: "www.example.com",
|
||||||
ProxyMethod: "shadowsocks",
|
ProxyMethod: "shadowsocks",
|
||||||
EncryptionMethod: "plain",
|
EncryptionMethod: "plain",
|
||||||
|
|
@ -106,7 +106,7 @@ var basicTCPConfig = client.RawConfig{
|
||||||
BrowserSig: "firefox",
|
BrowserSig: "firefox",
|
||||||
}
|
}
|
||||||
|
|
||||||
var singleplexTCPConfig = client.RawConfig{
|
var singleplexTCPConfig = client.Config{
|
||||||
ServerName: "www.example.com",
|
ServerName: "www.example.com",
|
||||||
ProxyMethod: "shadowsocks",
|
ProxyMethod: "shadowsocks",
|
||||||
EncryptionMethod: "plain",
|
EncryptionMethod: "plain",
|
||||||
|
|
@ -120,8 +120,8 @@ var singleplexTCPConfig = client.RawConfig{
|
||||||
BrowserSig: "chrome",
|
BrowserSig: "chrome",
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateClientConfigs(rawConfig client.RawConfig, state common.WorldState) (client.RemoteConnConfig, client.AuthInfo) {
|
func generateClientConfigs(rawConfig client.Config, state common.WorldState) (client.RemoteConnConfig, client.AuthInfo) {
|
||||||
rmt, auth, err := rawConfig.ProcessRawConfig(state)
|
rmt, auth, err := rawConfig.Process(state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -458,7 +458,7 @@ func TestClosingStreamsFromProxy(t *testing.T) {
|
||||||
log.SetLevel(log.ErrorLevel)
|
log.SetLevel(log.ErrorLevel)
|
||||||
worldState := common.WorldOfTime(time.Unix(10, 0))
|
worldState := common.WorldOfTime(time.Unix(10, 0))
|
||||||
|
|
||||||
for clientConfigName, clientConfig := range map[string]client.RawConfig{"basic": basicTCPConfig, "singleplex": singleplexTCPConfig} {
|
for clientConfigName, clientConfig := range map[string]client.Config{"basic": basicTCPConfig, "singleplex": singleplexTCPConfig} {
|
||||||
clientConfig := clientConfig
|
clientConfig := clientConfig
|
||||||
clientConfigName := clientConfigName
|
clientConfigName := clientConfigName
|
||||||
t.Run(clientConfigName, func(t *testing.T) {
|
t.Run(clientConfigName, func(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,8 @@ import (
|
||||||
mux "github.com/cbeuw/Cloak/internal/multiplex"
|
mux "github.com/cbeuw/Cloak/internal/multiplex"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RawConfig represents the fields in the config json file
|
// Config contains the configuration parameter fields for a Cloak client
|
||||||
// jsonOptional means if the json's empty, its value will be set from environment variables or commandline args
|
type Config struct {
|
||||||
// but it mustn't be empty when ProcessRawConfig is called
|
|
||||||
type RawConfig struct {
|
|
||||||
// Required fields
|
// Required fields
|
||||||
// ServerName is the domain you appear to be visiting
|
// ServerName is the domain you appear to be visiting
|
||||||
// to your Firewall or ISP
|
// to your Firewall or ISP
|
||||||
|
|
@ -38,7 +36,7 @@ type RawConfig struct {
|
||||||
// PublicKey is the 32-byte public Curve25519 ECDH key of your server
|
// PublicKey is the 32-byte public Curve25519 ECDH key of your server
|
||||||
PublicKey []byte
|
PublicKey []byte
|
||||||
// RemoteHost is the Cloak server's hostname or IP address
|
// RemoteHost is the Cloak server's hostname or IP address
|
||||||
RemoteHost string // jsonOptional
|
RemoteHost string
|
||||||
|
|
||||||
// Optional Fields
|
// Optional Fields
|
||||||
// EncryptionMethod is the cryptographic algorithm used to
|
// EncryptionMethod is the cryptographic algorithm used to
|
||||||
|
|
@ -86,59 +84,57 @@ type RemoteConnConfig struct {
|
||||||
|
|
||||||
type AuthInfo = transports.AuthInfo
|
type AuthInfo = transports.AuthInfo
|
||||||
|
|
||||||
func (raw *RawConfig) ProcessRawConfig(worldState common.WorldState) (remote RemoteConnConfig, auth AuthInfo, err error) {
|
func (raw *Config) Process(worldState common.WorldState) (remote RemoteConnConfig, auth AuthInfo, err error) {
|
||||||
nullErr := func(field string) (remote RemoteConnConfig, auth AuthInfo, err error) {
|
if raw.ServerName == "" {
|
||||||
err = fmt.Errorf("%v cannot be empty", field)
|
err = fmt.Errorf("ServerName cannot be empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if raw.ProxyMethod == "" {
|
||||||
|
err = fmt.Errorf("ProxyMethod cannot be empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(raw.UID) == 0 {
|
||||||
|
err = fmt.Errorf("UID cannot be empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(raw.PublicKey) == 0 {
|
||||||
|
err = fmt.Errorf("PublicKey cannot be empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if raw.RemoteHost == "" {
|
||||||
|
err = fmt.Errorf("RemoteHost cannot be empty")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
auth.UID = raw.UID
|
auth.UID = raw.UID
|
||||||
auth.Unordered = raw.UDP
|
auth.Unordered = raw.UDP
|
||||||
if raw.ServerName == "" {
|
|
||||||
return nullErr("ServerName")
|
|
||||||
}
|
|
||||||
auth.MockDomain = raw.ServerName
|
auth.MockDomain = raw.ServerName
|
||||||
|
|
||||||
if raw.ProxyMethod == "" {
|
|
||||||
return nullErr("ProxyMethod")
|
|
||||||
}
|
|
||||||
auth.ProxyMethod = raw.ProxyMethod
|
auth.ProxyMethod = raw.ProxyMethod
|
||||||
if len(raw.UID) == 0 {
|
auth.WorldState = worldState
|
||||||
return nullErr("UID")
|
|
||||||
}
|
|
||||||
|
|
||||||
// static public key
|
// static public key
|
||||||
if len(raw.PublicKey) == 0 {
|
|
||||||
return nullErr("PublicKey")
|
|
||||||
}
|
|
||||||
pub, ok := ecdh.Unmarshal(raw.PublicKey)
|
pub, ok := ecdh.Unmarshal(raw.PublicKey)
|
||||||
if !ok {
|
if !ok {
|
||||||
err = fmt.Errorf("failed to unmarshal Public key")
|
err = fmt.Errorf("failed to unmarshal Public key")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
auth.ServerPubKey = pub
|
auth.ServerPubKey = pub
|
||||||
auth.WorldState = worldState
|
|
||||||
|
|
||||||
// Encryption method
|
// Encryption method
|
||||||
switch strings.ToLower(raw.EncryptionMethod) {
|
switch strings.ToLower(raw.EncryptionMethod) {
|
||||||
case "plain":
|
case "plain":
|
||||||
auth.EncryptionMethod = mux.EncryptionMethodPlain
|
auth.EncryptionMethod = mux.EncryptionMethodPlain
|
||||||
case "aes-gcm", "aes-256-gcm":
|
case "aes-gcm", "aes-256-gcm", "":
|
||||||
auth.EncryptionMethod = mux.EncryptionMethodAES256GCM
|
auth.EncryptionMethod = mux.EncryptionMethodAES256GCM
|
||||||
case "aes-128-gcm":
|
case "aes-128-gcm":
|
||||||
auth.EncryptionMethod = mux.EncryptionMethodAES128GCM
|
auth.EncryptionMethod = mux.EncryptionMethodAES128GCM
|
||||||
case "chacha20-poly1305":
|
case "chacha20-poly1305":
|
||||||
auth.EncryptionMethod = mux.EncryptionMethodChaha20Poly1305
|
auth.EncryptionMethod = mux.EncryptionMethodChaha20Poly1305
|
||||||
case "":
|
|
||||||
auth.EncryptionMethod = mux.EncryptionMethodAES256GCM
|
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("unknown encryption method %v", raw.EncryptionMethod)
|
err = fmt.Errorf("unknown encryption method %v", raw.EncryptionMethod)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if raw.RemoteHost == "" {
|
|
||||||
return nullErr("RemoteHost")
|
|
||||||
}
|
|
||||||
var remotePort string
|
var remotePort string
|
||||||
if raw.RemotePort == "" {
|
if raw.RemotePort == "" {
|
||||||
remotePort = "443"
|
remotePort = "443"
|
||||||
|
|
@ -175,8 +171,6 @@ func (raw *RawConfig) ProcessRawConfig(worldState common.WorldState) (remote Rem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "direct":
|
case "direct":
|
||||||
fallthrough
|
|
||||||
default:
|
|
||||||
var browser browser
|
var browser browser
|
||||||
switch strings.ToLower(raw.BrowserSig) {
|
switch strings.ToLower(raw.BrowserSig) {
|
||||||
case "firefox":
|
case "firefox":
|
||||||
|
|
@ -193,6 +187,9 @@ func (raw *RawConfig) ProcessRawConfig(worldState common.WorldState) (remote Rem
|
||||||
Browser: browser,
|
Browser: browser,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("unknown transport %v", raw.Transport)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeepAlive
|
// KeepAlive
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cbeuw/Cloak/internal/common"
|
||||||
|
mux "github.com/cbeuw/Cloak/internal/multiplex"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var baseConfig = Config{
|
||||||
|
ServerName: "www.bing.com",
|
||||||
|
ProxyMethod: "ssh",
|
||||||
|
UID: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf},
|
||||||
|
PublicKey: make([]byte, 32),
|
||||||
|
RemoteHost: "12.34.56.78",
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefault(t *testing.T) {
|
||||||
|
remote, auth, err := baseConfig.Process(common.RealWorldState)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.EqualValues(t, 4, remote.NumConn)
|
||||||
|
assert.EqualValues(t, mux.EncryptionMethodAES256GCM, auth.EncryptionMethod)
|
||||||
|
assert.EqualValues(t, -1, remote.KeepAlive)
|
||||||
|
assert.False(t, auth.Unordered)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidation(t *testing.T) {
|
||||||
|
_, _, err := baseConfig.Process(common.RealWorldState)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
type test struct {
|
||||||
|
fieldToChange string
|
||||||
|
newValue any
|
||||||
|
errPattern string
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []test{
|
||||||
|
{
|
||||||
|
fieldToChange: "ServerName",
|
||||||
|
newValue: "",
|
||||||
|
errPattern: "empty",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldToChange: "UID",
|
||||||
|
newValue: []byte{},
|
||||||
|
errPattern: "empty",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldToChange: "PublicKey",
|
||||||
|
newValue: []byte{0x1},
|
||||||
|
errPattern: "unmarshal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldToChange: "RemoteHost",
|
||||||
|
newValue: "",
|
||||||
|
errPattern: "empty",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldToChange: "BrowserSig",
|
||||||
|
newValue: "not-a-browser",
|
||||||
|
errPattern: "unknown",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
config := baseConfig
|
||||||
|
reflect.ValueOf(&config).Elem().FieldByName(test.fieldToChange).Set(reflect.ValueOf(test.newValue))
|
||||||
|
_, _, err := config.Process(common.RealWorldState)
|
||||||
|
assert.ErrorContains(t, err, test.errPattern)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue