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,

26
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,
@ -162,6 +167,7 @@ func PrintPeerCfg(peer PeerConfig, conf *DsnetConfig) {
// 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 {
// domain to append to hostnames. Relies on separate DNS server for // When generating configs, the ExternalHostname has precendence for the
// resolution. Informational only. // 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 ExternalIP net.IP
ExternalIP6 net.IP ExternalIP6 net.IP
ListenPort int `validate:"gte=1024,lte=65535"` ListenPort int `validate:"gte=1024,lte=65535"`
// domain to append to hostnames. Relies on separate DNS server for
// resolution. Informational only.
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