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 {
|
||||
client.RawConfig
|
||||
client.Config
|
||||
|
||||
// LocalHost is the hostname or IP address to listen for incoming proxy client connections
|
||||
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) {
|
||||
remote, auth, err = raw.RawConfig.ProcessRawConfig(worldState)
|
||||
remote, auth, err = raw.Config.Process(worldState)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ var privateKey, _ = base64.StdEncoding.DecodeString("SMWeC6VuZF8S/id65VuFQFlfa7h
|
|||
var four = 4
|
||||
var zero = 0
|
||||
|
||||
var basicUDPConfig = client.RawConfig{
|
||||
var basicUDPConfig = client.Config{
|
||||
ServerName: "www.example.com",
|
||||
ProxyMethod: "openvpn",
|
||||
EncryptionMethod: "plain",
|
||||
|
|
@ -92,7 +92,7 @@ var basicUDPConfig = client.RawConfig{
|
|||
RemotePort: "9999",
|
||||
}
|
||||
|
||||
var basicTCPConfig = client.RawConfig{
|
||||
var basicTCPConfig = client.Config{
|
||||
ServerName: "www.example.com",
|
||||
ProxyMethod: "shadowsocks",
|
||||
EncryptionMethod: "plain",
|
||||
|
|
@ -106,7 +106,7 @@ var basicTCPConfig = client.RawConfig{
|
|||
BrowserSig: "firefox",
|
||||
}
|
||||
|
||||
var singleplexTCPConfig = client.RawConfig{
|
||||
var singleplexTCPConfig = client.Config{
|
||||
ServerName: "www.example.com",
|
||||
ProxyMethod: "shadowsocks",
|
||||
EncryptionMethod: "plain",
|
||||
|
|
@ -120,8 +120,8 @@ var singleplexTCPConfig = client.RawConfig{
|
|||
BrowserSig: "chrome",
|
||||
}
|
||||
|
||||
func generateClientConfigs(rawConfig client.RawConfig, state common.WorldState) (client.RemoteConnConfig, client.AuthInfo) {
|
||||
rmt, auth, err := rawConfig.ProcessRawConfig(state)
|
||||
func generateClientConfigs(rawConfig client.Config, state common.WorldState) (client.RemoteConnConfig, client.AuthInfo) {
|
||||
rmt, auth, err := rawConfig.Process(state)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
@ -458,7 +458,7 @@ func TestClosingStreamsFromProxy(t *testing.T) {
|
|||
log.SetLevel(log.ErrorLevel)
|
||||
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
|
||||
clientConfigName := clientConfigName
|
||||
t.Run(clientConfigName, func(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -19,10 +19,8 @@ import (
|
|||
mux "github.com/cbeuw/Cloak/internal/multiplex"
|
||||
)
|
||||
|
||||
// RawConfig represents the fields in the config json file
|
||||
// jsonOptional means if the json's empty, its value will be set from environment variables or commandline args
|
||||
// but it mustn't be empty when ProcessRawConfig is called
|
||||
type RawConfig struct {
|
||||
// Config contains the configuration parameter fields for a Cloak client
|
||||
type Config struct {
|
||||
// Required fields
|
||||
// ServerName is the domain you appear to be visiting
|
||||
// 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 []byte
|
||||
// RemoteHost is the Cloak server's hostname or IP address
|
||||
RemoteHost string // jsonOptional
|
||||
RemoteHost string
|
||||
|
||||
// Optional Fields
|
||||
// EncryptionMethod is the cryptographic algorithm used to
|
||||
|
|
@ -86,59 +84,57 @@ type RemoteConnConfig struct {
|
|||
|
||||
type AuthInfo = transports.AuthInfo
|
||||
|
||||
func (raw *RawConfig) ProcessRawConfig(worldState common.WorldState) (remote RemoteConnConfig, auth AuthInfo, err error) {
|
||||
nullErr := func(field string) (remote RemoteConnConfig, auth AuthInfo, err error) {
|
||||
err = fmt.Errorf("%v cannot be empty", field)
|
||||
func (raw *Config) Process(worldState common.WorldState) (remote RemoteConnConfig, auth AuthInfo, err error) {
|
||||
if raw.ServerName == "" {
|
||||
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
|
||||
}
|
||||
|
||||
auth.UID = raw.UID
|
||||
auth.Unordered = raw.UDP
|
||||
if raw.ServerName == "" {
|
||||
return nullErr("ServerName")
|
||||
}
|
||||
auth.MockDomain = raw.ServerName
|
||||
|
||||
if raw.ProxyMethod == "" {
|
||||
return nullErr("ProxyMethod")
|
||||
}
|
||||
auth.ProxyMethod = raw.ProxyMethod
|
||||
if len(raw.UID) == 0 {
|
||||
return nullErr("UID")
|
||||
}
|
||||
auth.WorldState = worldState
|
||||
|
||||
// static public key
|
||||
if len(raw.PublicKey) == 0 {
|
||||
return nullErr("PublicKey")
|
||||
}
|
||||
pub, ok := ecdh.Unmarshal(raw.PublicKey)
|
||||
if !ok {
|
||||
err = fmt.Errorf("failed to unmarshal Public key")
|
||||
return
|
||||
}
|
||||
auth.ServerPubKey = pub
|
||||
auth.WorldState = worldState
|
||||
|
||||
// Encryption method
|
||||
switch strings.ToLower(raw.EncryptionMethod) {
|
||||
case "plain":
|
||||
auth.EncryptionMethod = mux.EncryptionMethodPlain
|
||||
case "aes-gcm", "aes-256-gcm":
|
||||
case "aes-gcm", "aes-256-gcm", "":
|
||||
auth.EncryptionMethod = mux.EncryptionMethodAES256GCM
|
||||
case "aes-128-gcm":
|
||||
auth.EncryptionMethod = mux.EncryptionMethodAES128GCM
|
||||
case "chacha20-poly1305":
|
||||
auth.EncryptionMethod = mux.EncryptionMethodChaha20Poly1305
|
||||
case "":
|
||||
auth.EncryptionMethod = mux.EncryptionMethodAES256GCM
|
||||
default:
|
||||
err = fmt.Errorf("unknown encryption method %v", raw.EncryptionMethod)
|
||||
return
|
||||
}
|
||||
|
||||
if raw.RemoteHost == "" {
|
||||
return nullErr("RemoteHost")
|
||||
}
|
||||
var remotePort string
|
||||
if raw.RemotePort == "" {
|
||||
remotePort = "443"
|
||||
|
|
@ -175,8 +171,6 @@ func (raw *RawConfig) ProcessRawConfig(worldState common.WorldState) (remote Rem
|
|||
}
|
||||
}
|
||||
case "direct":
|
||||
fallthrough
|
||||
default:
|
||||
var browser browser
|
||||
switch strings.ToLower(raw.BrowserSig) {
|
||||
case "firefox":
|
||||
|
|
@ -193,6 +187,9 @@ func (raw *RawConfig) ProcessRawConfig(worldState common.WorldState) (remote Rem
|
|||
Browser: browser,
|
||||
}
|
||||
}
|
||||
default:
|
||||
err = fmt.Errorf("unknown transport %v", raw.Transport)
|
||||
return
|
||||
}
|
||||
|
||||
// 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