ipn/config: add RelayServerPort and RelayServerStaticEndpoints to config file (#18300)
This commit is contained in:
+17
@@ -52,6 +52,15 @@ type ConfigVAlpha struct {
|
|||||||
// should advertise amongst its wireguard endpoints.
|
// should advertise amongst its wireguard endpoints.
|
||||||
StaticEndpoints []netip.AddrPort `json:",omitempty"`
|
StaticEndpoints []netip.AddrPort `json:",omitempty"`
|
||||||
|
|
||||||
|
// RelayServerPort is the UDP port for the relay server to bind to.
|
||||||
|
// A value of 0 will pick a random unused port. Nil disables relay server.
|
||||||
|
RelayServerPort *uint16 `json:",omitzero"`
|
||||||
|
|
||||||
|
// RelayServerStaticEndpoints are static IP:port endpoints to advertise
|
||||||
|
// as candidates for relay connections. Only relevant when RelayServerPort
|
||||||
|
// is non-nil.
|
||||||
|
RelayServerStaticEndpoints []netip.AddrPort `json:",omitempty"`
|
||||||
|
|
||||||
// TODO(bradfitz,maisem): future something like:
|
// TODO(bradfitz,maisem): future something like:
|
||||||
// Profile map[string]*Config // keyed by alice@gmail.com, corp.com (TailnetSID)
|
// Profile map[string]*Config // keyed by alice@gmail.com, corp.com (TailnetSID)
|
||||||
}
|
}
|
||||||
@@ -166,5 +175,13 @@ func (c *ConfigVAlpha) ToPrefs() (MaskedPrefs, error) {
|
|||||||
if c.AdvertiseServices != nil {
|
if c.AdvertiseServices != nil {
|
||||||
mp.AdvertiseServices = c.AdvertiseServices
|
mp.AdvertiseServices = c.AdvertiseServices
|
||||||
}
|
}
|
||||||
|
mp.RelayServerPortSet = true
|
||||||
|
mp.RelayServerStaticEndpointsSet = true
|
||||||
|
if c.RelayServerPort != nil {
|
||||||
|
mp.RelayServerPort = c.RelayServerPort
|
||||||
|
}
|
||||||
|
if c.RelayServerStaticEndpoints != nil {
|
||||||
|
mp.RelayServerStaticEndpoints = c.RelayServerStaticEndpoints
|
||||||
|
}
|
||||||
return mp, nil
|
return mp, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ package ipn
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"reflect"
|
||||||
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -64,3 +66,123 @@ func TestConfigVAlpha_ToPrefs_AdvertiseRoutes(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigVAlphaToPrefs(t *testing.T) {
|
||||||
|
aps := func(t *testing.T, strs ...string) (ret []netip.AddrPort) {
|
||||||
|
t.Helper()
|
||||||
|
for _, s := range strs {
|
||||||
|
n, err := netip.ParseAddrPort(s)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parse AddrPort %q: %v", s, err)
|
||||||
|
}
|
||||||
|
ret = append(ret, n)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
cfg *ConfigVAlpha
|
||||||
|
want MaskedPrefs
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "nil_config",
|
||||||
|
cfg: nil,
|
||||||
|
want: MaskedPrefs{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "relay_server_port_and_static_endpoints",
|
||||||
|
cfg: &ConfigVAlpha{
|
||||||
|
RelayServerPort: new(uint16(12345)),
|
||||||
|
RelayServerStaticEndpoints: aps(t, "[2001:db8::1]:40000", "192.0.2.1:40000"),
|
||||||
|
},
|
||||||
|
want: MaskedPrefs{
|
||||||
|
Prefs: Prefs{
|
||||||
|
RelayServerPort: new(uint16(12345)),
|
||||||
|
RelayServerStaticEndpoints: aps(t, "[2001:db8::1]:40000", "192.0.2.1:40000"),
|
||||||
|
},
|
||||||
|
RelayServerPortSet: true,
|
||||||
|
RelayServerStaticEndpointsSet: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Port 0 means "pick a random unused port"; it is
|
||||||
|
// distinct from a nil port which disables the relay
|
||||||
|
// server. The zero value must be propagated.
|
||||||
|
name: "relay_server_port_zero_is_random_not_disabled",
|
||||||
|
cfg: &ConfigVAlpha{
|
||||||
|
RelayServerPort: new(uint16(0)),
|
||||||
|
},
|
||||||
|
want: MaskedPrefs{
|
||||||
|
Prefs: Prefs{
|
||||||
|
RelayServerPort: new(uint16(0)),
|
||||||
|
},
|
||||||
|
RelayServerPortSet: true,
|
||||||
|
RelayServerStaticEndpointsSet: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "only_static_endpoints_set",
|
||||||
|
cfg: &ConfigVAlpha{
|
||||||
|
RelayServerStaticEndpoints: aps(t, "192.0.2.1:40000"),
|
||||||
|
},
|
||||||
|
want: MaskedPrefs{
|
||||||
|
Prefs: Prefs{
|
||||||
|
RelayServerStaticEndpoints: aps(t, "192.0.2.1:40000"),
|
||||||
|
},
|
||||||
|
RelayServerPortSet: true,
|
||||||
|
RelayServerStaticEndpointsSet: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Both fields nil but masks set: the config file is the
|
||||||
|
// source of truth, so this disables any previously
|
||||||
|
// configured relay server.
|
||||||
|
name: "both_nil_disables_relay_server",
|
||||||
|
cfg: &ConfigVAlpha{},
|
||||||
|
want: MaskedPrefs{
|
||||||
|
RelayServerPortSet: true,
|
||||||
|
RelayServerStaticEndpointsSet: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// An empty (non-nil) static endpoints slice is treated as
|
||||||
|
// "advertise no static endpoints", disabling them.
|
||||||
|
name: "empty_static_endpoints_disables",
|
||||||
|
cfg: &ConfigVAlpha{
|
||||||
|
RelayServerStaticEndpoints: []netip.AddrPort{},
|
||||||
|
},
|
||||||
|
want: MaskedPrefs{
|
||||||
|
Prefs: Prefs{
|
||||||
|
RelayServerStaticEndpoints: []netip.AddrPort{},
|
||||||
|
},
|
||||||
|
RelayServerPortSet: true,
|
||||||
|
RelayServerStaticEndpointsSet: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := tt.cfg.ToPrefs()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ToPrefs() unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
// Compare only the relay-server-related fields rather than
|
||||||
|
// the whole MaskedPrefs, since ToPrefs populates many
|
||||||
|
// unrelated default fields (e.g. WantRunning).
|
||||||
|
if got.RelayServerPortSet != tt.want.RelayServerPortSet {
|
||||||
|
t.Errorf("RelayServerPortSet = %v; want %v", got.RelayServerPortSet, tt.want.RelayServerPortSet)
|
||||||
|
}
|
||||||
|
if got.RelayServerStaticEndpointsSet != tt.want.RelayServerStaticEndpointsSet {
|
||||||
|
t.Errorf("RelayServerStaticEndpointsSet = %v; want %v", got.RelayServerStaticEndpointsSet, tt.want.RelayServerStaticEndpointsSet)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got.RelayServerPort, tt.want.RelayServerPort) {
|
||||||
|
t.Errorf("RelayServerPort = %v; want %v", got.RelayServerPort, tt.want.RelayServerPort)
|
||||||
|
}
|
||||||
|
if !slices.Equal(got.RelayServerStaticEndpoints, tt.want.RelayServerStaticEndpoints) {
|
||||||
|
t.Errorf("RelayServerStaticEndpoints = %v; want %v", got.RelayServerStaticEndpoints, tt.want.RelayServerStaticEndpoints)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7490,6 +7490,78 @@ func TestConfigFileReload(t *testing.T) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "enable_relay_server",
|
||||||
|
initial: &conffile.Config{
|
||||||
|
Parsed: ipn.ConfigVAlpha{
|
||||||
|
Version: "alpha0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
updated: &conffile.Config{
|
||||||
|
Parsed: ipn.ConfigVAlpha{
|
||||||
|
Version: "alpha0",
|
||||||
|
RelayServerPort: new(uint16(12345)),
|
||||||
|
RelayServerStaticEndpoints: []netip.AddrPort{netip.MustParseAddrPort("[2001:db8::1]:40000")},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
checkFn: func(t *testing.T, b *LocalBackend) {
|
||||||
|
pv := b.Prefs()
|
||||||
|
if port, ok := pv.RelayServerPort().GetOk(); !ok || port != 12345 {
|
||||||
|
t.Errorf("RelayServerPort = (%d, %v); want (12345, true)", port, ok)
|
||||||
|
}
|
||||||
|
if got := pv.RelayServerStaticEndpoints().AsSlice(); !slices.Equal(got, []netip.AddrPort{netip.MustParseAddrPort("[2001:db8::1]:40000")}) {
|
||||||
|
t.Errorf("RelayServerStaticEndpoints = %v; want [[2001:db8::1]:40000]", got)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Disabling: a config that omits the relay server fields
|
||||||
|
// must clear any previously configured values, because
|
||||||
|
// ToPrefs sets the masks unconditionally.
|
||||||
|
name: "disable_relay_server",
|
||||||
|
initial: &conffile.Config{
|
||||||
|
Parsed: ipn.ConfigVAlpha{
|
||||||
|
Version: "alpha0",
|
||||||
|
RelayServerPort: new(uint16(12345)),
|
||||||
|
RelayServerStaticEndpoints: []netip.AddrPort{netip.MustParseAddrPort("[2001:db8::1]:40000")},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
updated: &conffile.Config{
|
||||||
|
Parsed: ipn.ConfigVAlpha{
|
||||||
|
Version: "alpha0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
checkFn: func(t *testing.T, b *LocalBackend) {
|
||||||
|
pv := b.Prefs()
|
||||||
|
if _, ok := pv.RelayServerPort().GetOk(); ok {
|
||||||
|
t.Errorf("RelayServerPort = %v; want disabled", pv.RelayServerPort())
|
||||||
|
}
|
||||||
|
if got := pv.RelayServerStaticEndpoints().AsSlice(); len(got) != 0 {
|
||||||
|
t.Errorf("RelayServerStaticEndpoints = %v; want empty", got)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "change_relay_server_port",
|
||||||
|
initial: &conffile.Config{
|
||||||
|
Parsed: ipn.ConfigVAlpha{
|
||||||
|
Version: "alpha0",
|
||||||
|
RelayServerPort: new(uint16(12345)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
updated: &conffile.Config{
|
||||||
|
Parsed: ipn.ConfigVAlpha{
|
||||||
|
Version: "alpha0",
|
||||||
|
RelayServerPort: new(uint16(54321)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
checkFn: func(t *testing.T, b *LocalBackend) {
|
||||||
|
pv := b.Prefs()
|
||||||
|
if port, ok := pv.RelayServerPort().GetOk(); !ok || port != 54321 {
|
||||||
|
t.Errorf("RelayServerPort = (%d, %v); want (54321, true)", port, ok)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
|
|||||||
Reference in New Issue
Block a user