support ExternalHostname which has precedence over IPs

This commit is contained in:
Callan Bryant 2020-11-29 18:34:05 +00:00
parent 6ca3614cff
commit 45b61f8a63
No known key found for this signature in database
GPG Key ID: C31FA9DF3ACBFFAA
4 changed files with 47 additions and 19 deletions

View File

@ -1,12 +1,26 @@
Explanation of each field: Explanation of each field:
{ {
"ExternalHostname": "",
The `ExternalHostname` is used for the client config server `Endpoint` if
defined. It has precedence over `ExternalIP` and `ExternalIP6`.
"ExternalIP": "198.51.100.2", "ExternalIP": "198.51.100.2",
"ExternalIP6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "ExternalIP6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
This is the external IP that will be the value of Endpoint for the server peer This is the external IPv4 and IPv6 that will be the value of Endpoint for the
in client configs. It is automatically detected by opening a socket or using an server peer in client configs. It is automatically detected by opening a socket
external IP discovery service -- the first to give a valid public IP will win. or using an external IP discovery service -- the first to give a valid public
IP will win.
When generating configs, the `ExternalHostname` has precendence for the server
`Endpoint`, followed by `ExternalIP` (IPv4) and `ExternalIP6` (IPv6) The IPs are
discovered automatically on init. Define an `ExternalHostname` if you're using
dynamic DNS, want to change IPs without updating configs, or want wireguard to
be able to choose between IPv4/IPv6. It is only possible to specify one
Endpoint per peer entry in wireguard.
"ListenPort": 51820, "ListenPort": 51820,

View File

@ -60,6 +60,7 @@ Main (automatically generated) configuration example:
{ {
"ExternalHostname": "",
"ExternalIP": "198.51.100.2", "ExternalIP": "198.51.100.2",
"ExternalIP6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "ExternalIP6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
"ListenPort": 51820, "ListenPort": 51820,

28
add.go
View File

@ -22,11 +22,7 @@ DNS={{ .DsnetConfig.DNS }}
[Peer] [Peer]
PublicKey={{ .DsnetConfig.PrivateKey.PublicKey.Key }} PublicKey={{ .DsnetConfig.PrivateKey.PublicKey.Key }}
PresharedKey={{ .Peer.PresharedKey.Key }} PresharedKey={{ .Peer.PresharedKey.Key }}
{{ if gt (.DsnetConfig.ExternalIP | len) 0 -}} Endpoint={{ .Endpoint }}:{{ .DsnetConfig.ListenPort }}
Endpoint={{ .DsnetConfig.ExternalIP }}:{{ .DsnetConfig.ListenPort }}
{{ else -}}
Endpoint={{ .DsnetConfig.ExternalIP6 }}:{{ .DsnetConfig.ListenPort }}
{{ end -}}
PersistentKeepalive={{ .Keepalive }} PersistentKeepalive={{ .Keepalive }}
{{ if gt (.DsnetConfig.Network.IPNet.IP | len) 0 -}} {{ if gt (.DsnetConfig.Network.IPNet.IP | len) 0 -}}
AllowedIPs={{ .DsnetConfig.Network }} AllowedIPs={{ .DsnetConfig.Network }}
@ -54,11 +50,7 @@ set interfaces wireguard {{ .Wgif }} description {{ .DsnetConfig.InterfaceName }
#set service dns forwarding name-server {{ .DsnetConfig.DNS }} #set service dns forwarding name-server {{ .DsnetConfig.DNS }}
{{ end }} {{ end }}
{{ if gt (.DsnetConfig.ExternalIP | len) 0 -}} set interfaces wireguard {{ .Wgif }} peer {{ .DsnetConfig.PrivateKey.PublicKey.Key }} endpoint {{ .Endpoint }}:{{ .DsnetConfig.ListenPort }}
set interfaces wireguard {{ .Wgif }} peer {{ .DsnetConfig.PrivateKey.PublicKey.Key }} endpoint {{ .DsnetConfig.ExternalIP }}:{{ .DsnetConfig.ListenPort }}
{{ else -}}
set interfaces wireguard {{ .Wgif }} peer {{ .DsnetConfig.PrivateKey.PublicKey.Key }} endpoint {{ .DsnetConfig.ExternalIP6 }}:{{ .DsnetConfig.ListenPort }}
{{ end -}}
set interfaces wireguard {{ .Wgif }} peer {{ .DsnetConfig.PrivateKey.PublicKey.Key }} persistent-keepalive {{ .Keepalive }} set interfaces wireguard {{ .Wgif }} peer {{ .DsnetConfig.PrivateKey.PublicKey.Key }} persistent-keepalive {{ .Keepalive }}
set interfaces wireguard {{ .Wgif }} peer {{ .DsnetConfig.PrivateKey.PublicKey.Key }} preshared-key {{ .Peer.PresharedKey.Key }} set interfaces wireguard {{ .Wgif }} peer {{ .DsnetConfig.PrivateKey.PublicKey.Key }} preshared-key {{ .Peer.PresharedKey.Key }}
{{ if gt (.DsnetConfig.Network.IPNet.IP | len) 0 -}} {{ if gt (.DsnetConfig.Network.IPNet.IP | len) 0 -}}
@ -151,6 +143,19 @@ func PrintPeerCfg(peer PeerConfig, conf *DsnetConfig) {
wgifSeed += int(b) wgifSeed += int(b)
} }
// See DsnetConfig type for explanation
var endpoint string
if conf.ExternalHostname != "" {
endpoint = conf.ExternalHostname
} else if len(conf.ExternalIP) > 0 {
endpoint = conf.ExternalIP.String()
} else if len(conf.ExternalIP6) > 0 {
endpoint = conf.ExternalIP6.String()
} else {
ExitFail("Config does not contain ExternalIP, ExternalIP6 or ExternalHostname")
}
t := template.Must(template.New("peerConf").Parse(peerConf)) t := template.Must(template.New("peerConf").Parse(peerConf))
err := t.Execute(os.Stdout, map[string]interface{}{ err := t.Execute(os.Stdout, map[string]interface{}{
"Peer": peer, "Peer": peer,
@ -161,7 +166,8 @@ func PrintPeerCfg(peer PeerConfig, conf *DsnetConfig) {
// vyatta requires an interface in range/format wg0-wg999 // vyatta requires an interface in range/format wg0-wg999
// deterministically choosing one in this range will probably allow use // deterministically choosing one in this range will probably allow use
// of the config without a colliding interface name // of the config without a colliding interface name
"Wgif": fmt.Sprintf("wg%d", wgifSeed%999), "Wgif": fmt.Sprintf("wg%d", wgifSeed%999),
"Endpoint": endpoint,
}) })
check(err) check(err)
} }

View File

@ -34,11 +34,18 @@ type PeerConfig struct {
} }
type DsnetConfig struct { type DsnetConfig struct {
// When generating configs, the ExternalHostname has precendence for the
// server Endpoint, followed by ExternalIP (IPv4) and ExternalIP6 (IPv6)
// The IPs are discovered automatically on init. Define an ExternalHostname
// if you're using dynamic DNS, want to change IPs without updating
// configs, or want wireguard to be able to choose between IPv4/IPv6. It is
// only possible to specify one Endpoint per peer entry in wireguard.
ExternalHostname string
ExternalIP net.IP
ExternalIP6 net.IP
ListenPort int `validate:"gte=1024,lte=65535"`
// domain to append to hostnames. Relies on separate DNS server for // domain to append to hostnames. Relies on separate DNS server for
// resolution. Informational only. // resolution. Informational only.
ExternalIP net.IP
ExternalIP6 net.IP
ListenPort int `validate:"gte=1024,lte=65535"`
Domain string `validate:"required,gte=1,lte=255"` Domain string `validate:"required,gte=1,lte=255"`
InterfaceName string `validate:"required,gte=1,lte=255"` InterfaceName string `validate:"required,gte=1,lte=255"`
// IP network from which to allocate automatic sequential addresses // IP network from which to allocate automatic sequential addresses
@ -76,8 +83,8 @@ func MustLoadDsnetConfig() *DsnetConfig {
err = validator.New().Struct(conf) err = validator.New().Struct(conf)
check(err) check(err)
if len(conf.ExternalIP) == 0 && len(conf.ExternalIP6) == 0 { if conf.ExternalHostname == "" && len(conf.ExternalIP) == 0 && len(conf.ExternalIP6) == 0 {
ExitFail("Config does not contain ExternalIP or ExternalIP6") ExitFail("Config does not contain ExternalIP, ExternalIP6 or ExternalHostname")
} }
return &conf return &conf