Improve dual stack handling

Now creates both A and AAAA records, and checks added domains
for both IPv4 and IPv6.
This commit is contained in:
Anders Pitman
2022-03-09 11:42:06 -07:00
parent 951fa52c81
commit 2f89820589
5 changed files with 82 additions and 37 deletions

23
api.go
View File

@@ -693,16 +693,27 @@ func (a *Api) SetDomain(tokenData TokenData, params url.Values, domain, ownerId
return err
}
found := false
ipv4Match := false
ipv6Match := false
if a.config.PublicIpv4 == "" {
ipv4Match = true
}
if a.config.PublicIpv6 == "" {
ipv6Match = true
}
for _, ip := range ips {
if ip.String() == a.config.PublicIp {
found = true
break
ipStr := ip.String()
if ipStr == a.config.PublicIpv4 {
ipv4Match = true
} else if ipStr == a.config.PublicIpv6 {
ipv6Match = true
}
}
if !found {
return errors.New(fmt.Sprintf("The requested domain does not appear to have an A/AAAA record pointed at the public IP address of the server (%s). This may be because the record is not properly set, or because the DNS is still propagating (can take up to 48 hours).", a.config.PublicIp))
if !ipv4Match || !ipv6Match {
return errors.New(fmt.Sprintf("The requested domain does not appear to have an A/AAAA record pointed at the public IP address of the server. This may be because the record is not properly set, or because the DNS is still propagating (can take up to 48 hours). IPv4: '%s', IPv6: '%s'", a.config.PublicIpv4, a.config.PublicIpv6))
}
err = a.db.AddDomain(domain, ownerId)

View File

@@ -26,7 +26,8 @@ import (
type Config struct {
SshServerPort int `json:"ssh_server_port"`
PublicIp string `json:"public_ip"`
PublicIpv4 string `json:"public_ipv4"`
PublicIpv6 string `json:"public_ipv6"`
namedropClient *namedrop.Client
autoCerts bool
}
@@ -56,11 +57,14 @@ func Listen() {
httpPort := flagSet.Int("http-port", 80, "HTTP (insecure) port")
httpsPort := flagSet.Int("https-port", 443, "HTTPS (secure) port")
allowHttp := flagSet.Bool("allow-http", false, "Allow unencrypted (HTTP) requests")
publicIp := flagSet.String("public-ip", "", "Public IP")
behindProxy := flagSet.Bool("behind-proxy", false, "Whether we're running behind another reverse proxy")
acmeEmail := flagSet.String("acme-email", "", "Email for ACME (ie Let's Encrypt)")
acmeUseStaging := flagSet.Bool("acme-use-staging", false, "Use ACME (ie Let's Encrypt) staging servers")
acceptCATerms := flagSet.Bool("accept-ca-terms", false, "Automatically accept CA terms")
var publicIpv4 string
flagSet.StringVar(&publicIpv4, "public-ipv4", "", "Public IPv4 address")
var publicIpv6 string
flagSet.StringVar(&publicIpv6, "public-ipv6", "", "Public IPv6 address")
err := flagSet.Parse(os.Args[2:])
if err != nil {
fmt.Fprintf(os.Stderr, "%s: parsing flags: %s\n", os.Args[0], err)
@@ -75,25 +79,36 @@ func Listen() {
namedropClient := namedrop.NewClient(db, db.GetAdminDomain(), "takingnames.io/namedrop")
var ip string
if *publicIp != "" {
ip = *publicIp
} else {
ip, err = namedropClient.GetPublicIp()
if publicIpv4 == "" {
publicIpv4, err = namedropClient.GetPublicIpv4()
if err != nil {
fmt.Printf("WARNING: Failed to determine public IP: %s\n", err.Error())
}
}
err = namedrop.CheckPublicAddress(ip, *httpPort)
if err != nil {
fmt.Printf("WARNING: Failed to access %s:%d from the internet\n", ip, *httpPort)
if publicIpv6 == "" {
publicIpv6, err = namedropClient.GetPublicIpv6()
if err != nil {
fmt.Printf("WARNING: Failed to determine public IP: %s\n", err.Error())
}
}
err = namedrop.CheckPublicAddress(ip, *httpsPort)
err = namedrop.CheckPublicAddress(publicIpv4, *httpPort)
if err != nil {
fmt.Printf("WARNING: Failed to access %s:%d from the internet\n", ip, *httpsPort)
fmt.Printf("WARNING: Failed to access %s:%d from the internet\n", publicIpv4, *httpPort)
}
err = namedrop.CheckPublicAddress(publicIpv4, *httpsPort)
if err != nil {
fmt.Printf("WARNING: Failed to access %s:%d from the internet\n", publicIpv4, *httpsPort)
}
err = namedrop.CheckPublicAddress(publicIpv6, *httpPort)
if err != nil {
fmt.Printf("WARNING: Failed to access %s:%d from the internet\n", publicIpv6, *httpPort)
}
err = namedrop.CheckPublicAddress(publicIpv6, *httpsPort)
if err != nil {
fmt.Printf("WARNING: Failed to access %s:%d from the internet\n", publicIpv6, *httpsPort)
}
autoCerts := true
@@ -168,7 +183,8 @@ func Listen() {
config := &Config{
SshServerPort: *sshServerPort,
PublicIp: ip,
PublicIpv4: publicIpv4,
PublicIpv6: publicIpv6,
namedropClient: namedropClient,
autoCerts: autoCerts,
}
@@ -250,24 +266,36 @@ func Listen() {
domain := namedropTokenData.Scopes[0].Domain
host := namedropTokenData.Scopes[0].Host
recordType := "AAAA"
if IsIPv4(config.PublicIp) {
recordType = "A"
if config.PublicIpv4 != "" {
createRecordReq := namedrop.Record{
Domain: domain,
Host: host,
Type: "A",
Value: config.PublicIpv4,
TTL: 300,
}
err = namedropClient.CreateRecord(createRecordReq)
if err != nil {
w.WriteHeader(500)
io.WriteString(w, err.Error())
return
}
}
createRecordReq := namedrop.Record{
Domain: domain,
Host: host,
Type: recordType,
Value: config.PublicIp,
TTL: 300,
}
err = namedropClient.CreateRecord(createRecordReq)
if err != nil {
w.WriteHeader(500)
io.WriteString(w, err.Error())
return
if config.PublicIpv6 != "" {
createRecordReq := namedrop.Record{
Domain: domain,
Host: host,
Type: "AAAA",
Value: config.PublicIpv6,
TTL: 300,
}
err = namedropClient.CreateRecord(createRecordReq)
if err != nil {
w.WriteHeader(500)
io.WriteString(w, err.Error())
return
}
}
fqdn := host + "." + domain

View File

@@ -101,6 +101,10 @@ func NewDatabase(path string) (*Database, error) {
db.Users = make(map[string]User)
}
if db.Domains == nil {
db.Domains = make(map[string]Domain)
}
if db.dnsRequests == nil {
db.dnsRequests = make(map[string]namedrop.DNSRequest)
}

2
go.mod
View File

@@ -9,7 +9,7 @@ require (
github.com/caddyserver/certmagic v0.15.3
github.com/mdp/qrterminal/v3 v3.0.0
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/takingnames/namedrop-go v0.7.0
github.com/takingnames/namedrop-go v0.8.0
github.com/takingnames/waygate-go v0.0.0-00010101000000-000000000000
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
)

2
go.sum
View File

@@ -139,6 +139,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/takingnames/namedrop-go v0.7.0 h1:xgIXrK9clSbnZFZwVuGCYhn7bGQO2fPYAIlACah4rtg=
github.com/takingnames/namedrop-go v0.7.0/go.mod h1:E3nx6fxAMfestthd1O3VhbaPesLaiYSGkWXRD1nIc88=
github.com/takingnames/namedrop-go v0.8.0 h1:lLltsu5NA0WlgjZ65AFP+AAb+maP/Xb5uCsfKVQwEGg=
github.com/takingnames/namedrop-go v0.8.0/go.mod h1:E3nx6fxAMfestthd1O3VhbaPesLaiYSGkWXRD1nIc88=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=