mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-08-10 13:20:33 +02:00
all: use 127.0.0.1 as nameserver when ctrld is an upstream
This commit is contained in:
+13
-21
@@ -35,15 +35,9 @@ import (
|
|||||||
"tailscale.com/net/interfaces"
|
"tailscale.com/net/interfaces"
|
||||||
|
|
||||||
"github.com/Control-D-Inc/ctrld"
|
"github.com/Control-D-Inc/ctrld"
|
||||||
"github.com/Control-D-Inc/ctrld/internal/certs"
|
|
||||||
"github.com/Control-D-Inc/ctrld/internal/controld"
|
"github.com/Control-D-Inc/ctrld/internal/controld"
|
||||||
ctrldnet "github.com/Control-D-Inc/ctrld/internal/net"
|
ctrldnet "github.com/Control-D-Inc/ctrld/internal/net"
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router"
|
"github.com/Control-D-Inc/ctrld/internal/router"
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router/ddwrt"
|
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router/firewalla"
|
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router/merlin"
|
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router/tomato"
|
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router/ubios"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -278,8 +272,8 @@ func initCLI() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
if platform := router.Name(); platform != "" {
|
if platform := router.Name(); platform != "" {
|
||||||
if platform == ddwrt.Name {
|
if cp := router.CertPool(); cp != nil {
|
||||||
rootCertPool = certs.CACertPool()
|
rootCertPool = cp
|
||||||
}
|
}
|
||||||
// Perform router setup/cleanup if ctrld could not be direct listener.
|
// Perform router setup/cleanup if ctrld could not be direct listener.
|
||||||
if !couldBeDirectListener(cfg.FirstListener()) {
|
if !couldBeDirectListener(cfg.FirstListener()) {
|
||||||
@@ -979,6 +973,9 @@ func netInterface(ifaceName string) (*net.Interface, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func defaultIfaceName() string {
|
func defaultIfaceName() string {
|
||||||
|
if ifaceName := router.DefaultInterfaceName(); ifaceName != "" {
|
||||||
|
return ifaceName
|
||||||
|
}
|
||||||
dri, err := interfaces.DefaultRouteInterface()
|
dri, err := interfaces.DefaultRouteInterface()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// On WSL 1, the route table does not have any default route. But the fact that
|
// On WSL 1, the route table does not have any default route. But the fact that
|
||||||
@@ -986,10 +983,6 @@ func defaultIfaceName() string {
|
|||||||
if oi := osinfo.New(); strings.Contains(oi.String(), "Microsoft") {
|
if oi := osinfo.New(); strings.Contains(oi.String(), "Microsoft") {
|
||||||
return "lo"
|
return "lo"
|
||||||
}
|
}
|
||||||
// Same as WSL case above.
|
|
||||||
if router.Name() == ubios.Name {
|
|
||||||
return "lo"
|
|
||||||
}
|
|
||||||
mainLog.Fatal().Err(err).Msg("failed to get default route interface")
|
mainLog.Fatal().Err(err).Msg("failed to get default route interface")
|
||||||
}
|
}
|
||||||
return dri
|
return dri
|
||||||
@@ -1057,19 +1050,18 @@ func selfCheckStatus(status service.Status, domain string) service.Status {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func userHomeDir() (string, error) {
|
func userHomeDir() (string, error) {
|
||||||
switch router.Name() {
|
dir, err := router.HomeDir()
|
||||||
case ddwrt.Name, merlin.Name, tomato.Name:
|
if err != nil {
|
||||||
exe, err := os.Executable()
|
return "", err
|
||||||
if err != nil {
|
}
|
||||||
return "", err
|
if dir != "" {
|
||||||
}
|
return dir, nil
|
||||||
return filepath.Dir(exe), nil
|
|
||||||
}
|
}
|
||||||
// viper will expand for us.
|
// viper will expand for us.
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
return os.UserHomeDir()
|
return os.UserHomeDir()
|
||||||
}
|
}
|
||||||
dir := "/etc/controld"
|
dir = "/etc/controld"
|
||||||
if err := os.MkdirAll(dir, 0750); err != nil {
|
if err := os.MkdirAll(dir, 0750); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -1291,7 +1283,7 @@ func updateListenerConfig() {
|
|||||||
|
|
||||||
// On firewalla, we don't need to check localhost, because the lo interface is excluded in dnsmasq
|
// On firewalla, we don't need to check localhost, because the lo interface is excluded in dnsmasq
|
||||||
// config, so we can always listen on localhost port 53, but no traffic could be routed there.
|
// config, so we can always listen on localhost port 53, but no traffic could be routed there.
|
||||||
tryLocalhost := !isLoopback(listener.IP) && router.Name() != firewalla.Name
|
tryLocalhost := !isLoopback(listener.IP) && router.CanListenLocalhost()
|
||||||
tryAllPort53 := true
|
tryAllPort53 := true
|
||||||
tryOldIPPort5354 := true
|
tryOldIPPort5354 := true
|
||||||
tryPort5354 := true
|
tryPort5354 := true
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ func resetDNS(iface *net.Interface) (err error) {
|
|||||||
}
|
}
|
||||||
// Start systemd-networkd if present.
|
// Start systemd-networkd if present.
|
||||||
if exe, _ := exec.LookPath("/lib/systemd/systemd-networkd"); exe != "" {
|
if exe, _ := exec.LookPath("/lib/systemd/systemd-networkd"); exe != "" {
|
||||||
_ = exec.Command("systemctl", "restart", "systemd-networkd").Run()
|
_ = exec.Command("systemctl", "start", "systemd-networkd").Run()
|
||||||
}
|
}
|
||||||
if r, oerr := dns.NewOSConfigurator(logf, iface.Name); oerr == nil {
|
if r, oerr := dns.NewOSConfigurator(logf, iface.Name); oerr == nil {
|
||||||
_ = r.SetDNS(dns.OSConfig{})
|
_ = r.SetDNS(dns.OSConfig{})
|
||||||
|
|||||||
+11
-31
@@ -16,9 +16,6 @@ import (
|
|||||||
"github.com/Control-D-Inc/ctrld/internal/clientinfo"
|
"github.com/Control-D-Inc/ctrld/internal/clientinfo"
|
||||||
"github.com/Control-D-Inc/ctrld/internal/dnscache"
|
"github.com/Control-D-Inc/ctrld/internal/dnscache"
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router"
|
"github.com/Control-D-Inc/ctrld/internal/router"
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router/dnsmasq"
|
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router/edgeos"
|
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router/firewalla"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -249,40 +246,23 @@ func (p *prog) setDNS() {
|
|||||||
logger.Error().Err(err).Msg("could not patch NetworkManager")
|
logger.Error().Err(err).Msg("could not patch NetworkManager")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug().Msg("setting DNS for interface")
|
logger.Debug().Msg("setting DNS for interface")
|
||||||
ns := lc.IP
|
ns := lc.IP
|
||||||
if couldBeDirectListener(lc) {
|
switch {
|
||||||
|
case couldBeDirectListener(lc):
|
||||||
// If ctrld is direct listener, use 127.0.0.1 as nameserver.
|
// If ctrld is direct listener, use 127.0.0.1 as nameserver.
|
||||||
ns = "127.0.0.1"
|
ns = "127.0.0.1"
|
||||||
} else if lc.Port != 53 {
|
case lc.Port != 53:
|
||||||
ifaceName := iface
|
ns = "127.0.0.1"
|
||||||
switch router.Name() {
|
if resolver := router.LocalResolverIP(); resolver != "" {
|
||||||
case firewalla.Name:
|
ns = resolver
|
||||||
// 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.
|
|
||||||
ifaceName = "br0"
|
|
||||||
logger.Warn().Msg("using br0 interface IP address as DNS server")
|
|
||||||
case edgeos.Name:
|
|
||||||
// On EdgeOS, dnsmasq is run with "--local-service", so we need to get
|
|
||||||
// the proper interface from dnsmasq config.
|
|
||||||
if name, _ := dnsmasq.InterfaceNameFromConfig("/etc/dnsmasq.conf"); name != "" {
|
|
||||||
ifaceName = name
|
|
||||||
logger.Warn().Msgf("using %s interface IP address as DNS server", ifaceName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.Warn().Msgf("ctrld is not running on port 53, use interface %s IP as DNS server", ifaceName)
|
|
||||||
netIface, err := net.InterfaceByName(ifaceName)
|
|
||||||
if err != nil {
|
|
||||||
mainLog.Fatal().Err(err).Msg("failed to get default route interface")
|
|
||||||
}
|
|
||||||
addrs, _ := netIface.Addrs()
|
|
||||||
for _, addr := range addrs {
|
|
||||||
if netIP, ok := addr.(*net.IPNet); ok && netIP.IP.To4() != nil {
|
|
||||||
ns = netIP.IP.To4().String()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
// If we ever reach here, it means ctrld is running on lc.IP port 53,
|
||||||
|
// so we could just use lc.IP as nameserver.
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := setDNS(netIface, []string{ns}); err != nil {
|
if err := setDNS(netIface, []string{ns}); err != nil {
|
||||||
logger.Error().Err(err).Msgf("could not set DNS for interface")
|
logger.Error().Err(err).Msgf("could not set DNS for interface")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
|
|
||||||
"github.com/Control-D-Inc/ctrld/internal/dns"
|
"github.com/Control-D-Inc/ctrld/internal/dns"
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router"
|
"github.com/Control-D-Inc/ctrld/internal/router"
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router/edgeos"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -29,11 +28,8 @@ func setDependencies(svc *service.Config) {
|
|||||||
"Wants=systemd-networkd-wait-online.service",
|
"Wants=systemd-networkd-wait-online.service",
|
||||||
"After=systemd-networkd-wait-online.service",
|
"After=systemd-networkd-wait-online.service",
|
||||||
}
|
}
|
||||||
// On EdeOS, ctrld needs to start after vyatta-dhcpd, so it can read leases file.
|
if routerDeps := router.ServiceDependencies(); len(routerDeps) > 0 {
|
||||||
if router.Name() == edgeos.Name {
|
svc.Dependencies = append(svc.Dependencies, routerDeps...)
|
||||||
svc.Dependencies = append(svc.Dependencies, "Wants=vyatta-dhcpd.service")
|
|
||||||
svc.Dependencies = append(svc.Dependencies, "After=vyatta-dhcpd.service")
|
|
||||||
svc.Dependencies = append(svc.Dependencies, "Wants=dnsmasq.service")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,19 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/x509"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/kardianos/service"
|
"github.com/kardianos/service"
|
||||||
|
|
||||||
"github.com/Control-D-Inc/ctrld"
|
"github.com/Control-D-Inc/ctrld"
|
||||||
|
"github.com/Control-D-Inc/ctrld/internal/certs"
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router/ddwrt"
|
"github.com/Control-D-Inc/ctrld/internal/router/ddwrt"
|
||||||
|
"github.com/Control-D-Inc/ctrld/internal/router/dnsmasq"
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router/edgeos"
|
"github.com/Control-D-Inc/ctrld/internal/router/edgeos"
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router/firewalla"
|
"github.com/Control-D-Inc/ctrld/internal/router/firewalla"
|
||||||
"github.com/Control-D-Inc/ctrld/internal/router/merlin"
|
"github.com/Control-D-Inc/ctrld/internal/router/merlin"
|
||||||
@@ -99,6 +104,86 @@ func Name() string {
|
|||||||
return r.name
|
return r.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultInterfaceName returns the default interface name of the current router.
|
||||||
|
func DefaultInterfaceName() string {
|
||||||
|
switch Name() {
|
||||||
|
case ubios.Name:
|
||||||
|
return "lo"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalResolverIP returns the IP that could be used as nameserver in /etc/resolv.conf file.
|
||||||
|
func LocalResolverIP() string {
|
||||||
|
var iface string
|
||||||
|
switch Name() {
|
||||||
|
case edgeos.Name:
|
||||||
|
// On EdgeOS, dnsmasq is run with "--local-service", so we need to get
|
||||||
|
// the proper interface from dnsmasq config.
|
||||||
|
if name, _ := dnsmasq.InterfaceNameFromConfig("/etc/dnsmasq.conf"); name != "" {
|
||||||
|
iface = name
|
||||||
|
}
|
||||||
|
case firewalla.Name:
|
||||||
|
// 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.
|
||||||
|
iface = "br0"
|
||||||
|
}
|
||||||
|
if netIface, _ := net.InterfaceByName(iface); netIface != nil {
|
||||||
|
addrs, _ := netIface.Addrs()
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if netIP, ok := addr.(*net.IPNet); ok && netIP.IP.To4() != nil {
|
||||||
|
return netIP.IP.To4().String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// HomeDir returns the home directory of ctrld on current router.
|
||||||
|
func HomeDir() (string, error) {
|
||||||
|
switch Name() {
|
||||||
|
case ddwrt.Name, merlin.Name, tomato.Name:
|
||||||
|
exe, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return filepath.Dir(exe), nil
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CertPool returns the system certificate pool of the current router.
|
||||||
|
func CertPool() *x509.CertPool {
|
||||||
|
if Name() == ddwrt.Name {
|
||||||
|
return certs.CACertPool()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanListenLocalhost reports whether the ctrld can listen on localhost with current host.
|
||||||
|
func CanListenLocalhost() bool {
|
||||||
|
switch {
|
||||||
|
case Name() == firewalla.Name:
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServiceDependencies returns list of dependencies that ctrld services needs on this router.
|
||||||
|
// See https://pkg.go.dev/github.com/kardianos/service#Config for list format.
|
||||||
|
func ServiceDependencies() []string {
|
||||||
|
if Name() == edgeos.Name {
|
||||||
|
// On EdeOS, ctrld needs to start after vyatta-dhcpd, so it can read leases file.
|
||||||
|
return []string{
|
||||||
|
"Wants=vyatta-dhcpd.service",
|
||||||
|
"After=vyatta-dhcpd.service",
|
||||||
|
"Wants=dnsmasq.service",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func distroName() string {
|
func distroName() string {
|
||||||
switch {
|
switch {
|
||||||
case bytes.HasPrefix(unameO(), []byte("DD-WRT")):
|
case bytes.HasPrefix(unameO(), []byte("DD-WRT")):
|
||||||
|
|||||||
Reference in New Issue
Block a user