all: dealing with VLAN config on Firewalla

Firewalla ignores 127.0.0.1 in all VLAN config, so making 127.0.0.1 as
dnsmasq upstream would break thing when multiple VLAN presents.

To deal with this, we need to gather all interfaces available, and
making them as upstream of dnsmasq. Then changing ctrld to listen on all
interfaces, too.

It also leads to better improvement for dnsmasq configuration template,
as the upstream server can now be generated dynamically instead of hard
coding to 127.0.0.1:5354.
This commit is contained in:
Cuong Manh Le
2023-06-27 01:22:32 +07:00
committed by Cuong Manh Le
parent a4c1983657
commit f3a3227f21
4 changed files with 56 additions and 4 deletions
+6 -2
View File
@@ -236,10 +236,14 @@ func (p *prog) setDNS() {
} }
logger.Debug().Msg("setting DNS for interface") logger.Debug().Msg("setting DNS for interface")
ns := cfg.Listener["0"].IP ns := cfg.Listener["0"].IP
if router.Name() == router.Firewalla && ns == "127.0.0.1" { if router.Name() == router.Firewalla && (ns == "127.0.0.1" || ns == "0.0.0.0" || ns == "") {
// On Firewalla, the lo interface is excluded in all dnsmasq settings of all interfaces. // On Firewalla, the lo interface is excluded in all dnsmasq settings of all interfaces.
// Thus, we use "br0" as the nameserver in /etc/resolv.conf file. // Thus, we use "br0" as the nameserver in /etc/resolv.conf file.
logger.Warn().Msg("127.0.0.1 won't work on Firewalla") if ns == "127.0.0.1" {
logger.Warn().Msg("127.0.0.1 as DNS server won't work on Firewalla")
} else {
logger.Warn().Msgf("%q could not be used as DNS server", ns)
}
if netIface, err := net.InterfaceByName("br0"); err == nil { if netIface, err := net.InterfaceByName("br0"); err == nil {
addrs, _ := netIface.Addrs() addrs, _ := netIface.Addrs()
for _, addr := range addrs { for _, addr := range addrs {
+17 -2
View File
@@ -7,7 +7,9 @@ import (
const dnsMasqConfigContentTmpl = `# GENERATED BY ctrld - DO NOT MODIFY const dnsMasqConfigContentTmpl = `# GENERATED BY ctrld - DO NOT MODIFY
no-resolv no-resolv
server=127.0.0.1#5354 {{- range .Upstreams}}
server={{ .Ip }}#{{ .Port }}
{{- end}}
{{- if .SendClientInfo}} {{- if .SendClientInfo}}
add-mac add-mac
{{- end}} {{- end}}
@@ -45,6 +47,11 @@ if [ -n "$pid" ] && [ -f "/proc/${pid}/cmdline" ]; then
fi fi
` `
type dnsmasqUpstream struct {
Ip string
Port int
}
func dnsMasqConf() (string, error) { func dnsMasqConf() (string, error) {
var sb strings.Builder var sb strings.Builder
var tmplText string var tmplText string
@@ -55,10 +62,18 @@ func dnsMasqConf() (string, error) {
tmplText = merlinDNSMasqPostConfTmpl tmplText = merlinDNSMasqPostConfTmpl
} }
tmpl := template.Must(template.New("").Parse(tmplText)) tmpl := template.Must(template.New("").Parse(tmplText))
upstreams := []dnsmasqUpstream{{ListenIP(), ListenPort()}}
if Name() == Firewalla {
if fu := firewallaDnsmasqUpstreams(); len(fu) > 0 {
upstreams = fu
}
}
var to = &struct { var to = &struct {
SendClientInfo bool SendClientInfo bool
Upstreams []dnsmasqUpstream
}{ }{
routerPlatform.Load().sendClientInfo, SendClientInfo: routerPlatform.Load().sendClientInfo,
Upstreams: upstreams,
} }
if err := tmpl.Execute(&sb, to); err != nil { if err := tmpl.Execute(&sb, to); err != nil {
return "", err return "", err
+26
View File
@@ -2,8 +2,10 @@ package router
import ( import (
"fmt" "fmt"
"net"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"strings" "strings"
) )
@@ -78,3 +80,27 @@ func writeFirewallStartupScript() error {
script := fmt.Sprintf("#!/bin/bash\n\nsudo %q %s\n", exe, argStr) script := fmt.Sprintf("#!/bin/bash\n\nsudo %q %s\n", exe, argStr)
return os.WriteFile(firewallaCtrldInitScriptPath, []byte(script), 0755) return os.WriteFile(firewallaCtrldInitScriptPath, []byte(script), 0755)
} }
func firewallaDnsmasqUpstreams() []dnsmasqUpstream {
matches, err := filepath.Glob("/home/pi/firerouter/etc/dnsmasq.dns.*.conf")
if err != nil {
return nil
}
upstreams := make([]dnsmasqUpstream, 0, len(matches))
for _, match := range matches {
// Trim prefix and suffix to get the iface name only.
ifaceName := strings.TrimSuffix(strings.TrimPrefix(match, "/home/pi/firerouter/etc/dnsmasq.dns."), ".conf")
if netIface, _ := net.InterfaceByName(ifaceName); netIface != nil {
addrs, _ := netIface.Addrs()
for _, addr := range addrs {
if netIP, ok := addr.(*net.IPNet); ok && netIP.IP.To4() != nil {
upstreams = append(upstreams, dnsmasqUpstream{
Ip: netIP.IP.To4().String(),
Port: ListenPort(),
})
}
}
}
}
return upstreams
}
+7
View File
@@ -220,6 +220,13 @@ func Cleanup(svc *service.Config) error {
// ListenIP returns the listener IP of ctrld on router. // ListenIP returns the listener IP of ctrld on router.
func ListenIP() string { func ListenIP() string {
name := Name()
switch name {
case Firewalla:
// Firewalla excepts 127.0.0.1 in all interfaces config. So we need to listen on all interfaces,
// making dnsmasq to be able to forward DNS query to specific interface based on VLAN config.
return "0.0.0.0"
}
return "127.0.0.1" return "127.0.0.1"
} }