mirror of
https://github.com/qdm12/gluetun.git
synced 2025-12-13 03:03:22 -06:00
444 lines
12 KiB
Go
444 lines
12 KiB
Go
package wireguard
|
|
|
|
import (
|
|
"net/netip"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"golang.zx2c4.com/wireguard/device"
|
|
)
|
|
|
|
func ptr[T any](v T) *T { return &v }
|
|
|
|
func Test_Settings_SetDefaults(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testCases := map[string]struct {
|
|
original Settings
|
|
expected Settings
|
|
}{
|
|
"empty settings": {
|
|
expected: Settings{
|
|
InterfaceName: "wg0",
|
|
FirewallMark: 51820,
|
|
AllowedIPs: []netip.Prefix{allIPv4()},
|
|
MTU: device.DefaultMTU,
|
|
IPv6: ptr(false),
|
|
Implementation: "auto",
|
|
},
|
|
},
|
|
"default endpoint port": {
|
|
original: Settings{
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 0),
|
|
},
|
|
expected: Settings{
|
|
InterfaceName: "wg0",
|
|
FirewallMark: 51820,
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 51820),
|
|
AllowedIPs: []netip.Prefix{allIPv4()},
|
|
MTU: device.DefaultMTU,
|
|
IPv6: ptr(false),
|
|
Implementation: "auto",
|
|
},
|
|
},
|
|
"not empty settings": {
|
|
original: Settings{
|
|
InterfaceName: "wg1",
|
|
FirewallMark: 999,
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 9999),
|
|
AllowedIPs: []netip.Prefix{allIPv4()},
|
|
MTU: device.DefaultMTU,
|
|
IPv6: ptr(true),
|
|
Implementation: "userspace",
|
|
},
|
|
expected: Settings{
|
|
InterfaceName: "wg1",
|
|
FirewallMark: 999,
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 9999),
|
|
AllowedIPs: []netip.Prefix{allIPv4()},
|
|
MTU: device.DefaultMTU,
|
|
IPv6: ptr(true),
|
|
Implementation: "userspace",
|
|
},
|
|
},
|
|
}
|
|
|
|
for name, testCase := range testCases {
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testCase.original.SetDefaults()
|
|
|
|
assert.Equal(t, testCase.expected, testCase.original)
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_Settings_Check(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
const (
|
|
validKey1 = "oMNSf/zJ0pt1ciy+qIRk8Rlyfs9accwuRLnKd85Yl1Q="
|
|
validKey2 = "aPjc9US5ICB30D1P4glR9tO7bkB2Ga+KZiFqnoypBHk="
|
|
)
|
|
|
|
testCases := map[string]struct {
|
|
settings Settings
|
|
errWrapped error
|
|
errMessage string
|
|
}{
|
|
"empty settings": {
|
|
errWrapped: ErrInterfaceNameInvalid,
|
|
errMessage: "invalid interface name: ",
|
|
},
|
|
"bad interface name": {
|
|
settings: Settings{
|
|
InterfaceName: "$H1T",
|
|
},
|
|
errWrapped: ErrInterfaceNameInvalid,
|
|
errMessage: "invalid interface name: $H1T",
|
|
},
|
|
"empty private key": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
},
|
|
errWrapped: ErrPrivateKeyMissing,
|
|
errMessage: "private key is missing",
|
|
},
|
|
"bad private key": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: "bad key",
|
|
},
|
|
errWrapped: ErrPrivateKeyInvalid,
|
|
errMessage: "cannot parse private key",
|
|
},
|
|
"empty public key": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
},
|
|
errWrapped: ErrPublicKeyMissing,
|
|
errMessage: "public key is missing",
|
|
},
|
|
"bad public key": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
PublicKey: "bad key",
|
|
},
|
|
errWrapped: ErrPublicKeyInvalid,
|
|
errMessage: "cannot parse public key: bad key",
|
|
},
|
|
"bad preshared key": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
PublicKey: validKey2,
|
|
PreSharedKey: "bad key",
|
|
},
|
|
errWrapped: ErrPreSharedKeyInvalid,
|
|
errMessage: "cannot parse pre-shared key",
|
|
},
|
|
"invalid endpoint address": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
PublicKey: validKey2,
|
|
},
|
|
errWrapped: ErrEndpointAddrMissing,
|
|
errMessage: "endpoint address is missing",
|
|
},
|
|
"zero endpoint port": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
PublicKey: validKey2,
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 0),
|
|
},
|
|
errWrapped: ErrEndpointPortMissing,
|
|
errMessage: "endpoint port is missing",
|
|
},
|
|
"no address": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
PublicKey: validKey2,
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 51820),
|
|
},
|
|
errWrapped: ErrAddressMissing,
|
|
errMessage: "interface address is missing",
|
|
},
|
|
"invalid address": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
PublicKey: validKey2,
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 51820),
|
|
Addresses: []netip.Prefix{{}},
|
|
},
|
|
errWrapped: ErrAddressNotValid,
|
|
errMessage: "interface address is not valid: for address 1 of 1",
|
|
},
|
|
|
|
"no allowed IP": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
PublicKey: validKey2,
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 51820),
|
|
Addresses: []netip.Prefix{
|
|
netip.PrefixFrom(netip.AddrFrom4([4]byte{5, 6, 7, 8}), 24),
|
|
},
|
|
},
|
|
errWrapped: ErrAllowedIPsMissing,
|
|
errMessage: "allowed IPs are missing",
|
|
},
|
|
"invalid allowed IP": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
PublicKey: validKey2,
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 51820),
|
|
Addresses: []netip.Prefix{
|
|
netip.PrefixFrom(netip.AddrFrom4([4]byte{5, 6, 7, 8}), 24),
|
|
},
|
|
AllowedIPs: []netip.Prefix{{}},
|
|
},
|
|
errWrapped: ErrAllowedIPNotValid,
|
|
errMessage: "allowed IP is not valid: for allowed IP 1 of 1",
|
|
},
|
|
"ipv6 allowed IP": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
PublicKey: validKey2,
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 51820),
|
|
Addresses: []netip.Prefix{
|
|
netip.PrefixFrom(netip.AddrFrom4([4]byte{5, 6, 7, 8}), 24),
|
|
},
|
|
AllowedIPs: []netip.Prefix{
|
|
allIPv6(),
|
|
},
|
|
IPv6: ptrTo(false),
|
|
},
|
|
errWrapped: ErrAllowedIPv6NotSupported,
|
|
errMessage: "allowed IPv6 address not supported: for allowed IP ::/0",
|
|
},
|
|
"zero firewall mark": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
PublicKey: validKey2,
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 51820),
|
|
AllowedIPs: []netip.Prefix{allIPv4()},
|
|
Addresses: []netip.Prefix{
|
|
netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 24),
|
|
},
|
|
},
|
|
errWrapped: ErrFirewallMarkMissing,
|
|
errMessage: "firewall mark is missing",
|
|
},
|
|
"missing_MTU": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
PublicKey: validKey2,
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 51820),
|
|
AllowedIPs: []netip.Prefix{allIPv4()},
|
|
Addresses: []netip.Prefix{
|
|
netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 24),
|
|
},
|
|
FirewallMark: 999,
|
|
},
|
|
errWrapped: ErrMTUMissing,
|
|
errMessage: "MTU is missing",
|
|
},
|
|
"invalid implementation": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
PublicKey: validKey2,
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 51820),
|
|
AllowedIPs: []netip.Prefix{allIPv4()},
|
|
Addresses: []netip.Prefix{
|
|
netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 24),
|
|
},
|
|
FirewallMark: 999,
|
|
MTU: 1420,
|
|
Implementation: "x",
|
|
},
|
|
errWrapped: ErrImplementationInvalid,
|
|
errMessage: "invalid implementation: x",
|
|
},
|
|
"all valid": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: validKey1,
|
|
PublicKey: validKey2,
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 51820),
|
|
AllowedIPs: []netip.Prefix{
|
|
allIPv6(),
|
|
},
|
|
Addresses: []netip.Prefix{
|
|
netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 24),
|
|
},
|
|
FirewallMark: 999,
|
|
MTU: 1420,
|
|
IPv6: ptrTo(true),
|
|
Implementation: "userspace",
|
|
},
|
|
},
|
|
}
|
|
|
|
for name, testCase := range testCases {
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
err := testCase.settings.Check()
|
|
|
|
assert.ErrorIs(t, err, testCase.errWrapped)
|
|
if testCase.errWrapped != nil {
|
|
assert.EqualError(t, err, testCase.errMessage)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func toStringPtr(s string) *string { return &s }
|
|
|
|
func Test_ToLinesSettings_setDefaults(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
settings := ToLinesSettings{
|
|
Indent: toStringPtr("indent"),
|
|
}
|
|
|
|
someFunc := func(settings ToLinesSettings) {
|
|
settings.setDefaults()
|
|
expectedSettings := ToLinesSettings{
|
|
Indent: toStringPtr("indent"),
|
|
FieldPrefix: toStringPtr("├── "),
|
|
LastFieldPrefix: toStringPtr("└── "),
|
|
}
|
|
assert.Equal(t, expectedSettings, settings)
|
|
}
|
|
someFunc(settings)
|
|
|
|
untouchedSettings := ToLinesSettings{
|
|
Indent: toStringPtr("indent"),
|
|
}
|
|
assert.Equal(t, untouchedSettings, settings)
|
|
}
|
|
|
|
func Test_Settings_String(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
settings := Settings{
|
|
InterfaceName: "wg0",
|
|
IPv6: ptr(true),
|
|
Implementation: "x",
|
|
}
|
|
const expected = `├── Interface name: wg0
|
|
├── Private key: not set
|
|
├── Pre shared key: not set
|
|
├── Endpoint: not set
|
|
├── IPv6: enabled
|
|
├── Implementation: x
|
|
└── Addresses: not set`
|
|
s := settings.String()
|
|
assert.Equal(t, expected, s)
|
|
}
|
|
|
|
func Test_Settings_Lines(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testCases := map[string]struct {
|
|
settings Settings
|
|
lineSettings ToLinesSettings
|
|
lines []string
|
|
}{
|
|
"empty settings": {
|
|
settings: Settings{
|
|
IPv6: ptr(false),
|
|
},
|
|
lines: []string{
|
|
"├── Interface name: ",
|
|
"├── Private key: not set",
|
|
"├── Pre shared key: not set",
|
|
"├── Endpoint: not set",
|
|
"├── IPv6: disabled",
|
|
"├── Implementation: ",
|
|
"└── Addresses: not set",
|
|
},
|
|
},
|
|
"settings all set": {
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
PrivateKey: "private key",
|
|
PublicKey: "public key",
|
|
PreSharedKey: "pre-shared key",
|
|
Endpoint: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 51820),
|
|
FirewallMark: 999,
|
|
RulePriority: 888,
|
|
Addresses: []netip.Prefix{
|
|
netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 1, 1, 1}), 24),
|
|
netip.PrefixFrom(netip.AddrFrom4([4]byte{2, 2, 2, 2}), 32),
|
|
},
|
|
IPv6: ptr(true),
|
|
Implementation: "userspace",
|
|
},
|
|
lines: []string{
|
|
"├── Interface name: wg0",
|
|
"├── Private key: set",
|
|
"├── PublicKey: public key",
|
|
"├── Pre shared key: set",
|
|
"├── Endpoint: 1.2.3.4:51820",
|
|
"├── IPv6: enabled",
|
|
"├── Firewall mark: 999",
|
|
"├── Rule priority: 888",
|
|
"├── Implementation: userspace",
|
|
"└── Addresses:",
|
|
" ├── 1.1.1.1/24",
|
|
" └── 2.2.2.2/32",
|
|
},
|
|
},
|
|
"custom line settings": {
|
|
lineSettings: ToLinesSettings{
|
|
Indent: toStringPtr(" "),
|
|
FieldPrefix: toStringPtr("- "),
|
|
LastFieldPrefix: toStringPtr("* "),
|
|
},
|
|
settings: Settings{
|
|
InterfaceName: "wg0",
|
|
Addresses: []netip.Prefix{
|
|
netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 1, 1, 1}), 24),
|
|
netip.PrefixFrom(netip.AddrFrom4([4]byte{2, 2, 2, 2}), 32),
|
|
},
|
|
IPv6: ptr(false),
|
|
},
|
|
lines: []string{
|
|
"- Interface name: wg0",
|
|
"- Private key: not set",
|
|
"- Pre shared key: not set",
|
|
"- Endpoint: not set",
|
|
"- IPv6: disabled",
|
|
"- Implementation: ",
|
|
"* Addresses:",
|
|
" - 1.1.1.1/24",
|
|
" * 2.2.2.2/32",
|
|
},
|
|
},
|
|
}
|
|
|
|
for name, testCase := range testCases {
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
lines := testCase.settings.ToLines(testCase.lineSettings)
|
|
|
|
assert.Equal(t, testCase.lines, lines)
|
|
})
|
|
}
|
|
}
|