cmd/ctrld: do set/reset DNS only when start/stop/uninstall

This commit is contained in:
Cuong Manh Le
2023-01-31 11:03:50 +07:00
committed by Cuong Manh Le
parent 4ea1e64795
commit 149941f17f
6 changed files with 89 additions and 58 deletions

View File

@@ -117,10 +117,6 @@ func initCLI() {
}
initCache()
if iface == "auto" {
iface = defaultIfaceName()
}
if daemon {
exe, err := os.Executable()
if err != nil {
@@ -173,8 +169,6 @@ func initCLI() {
runCmd.Flags().StringVarP(&cdUID, "cd", "", "", "Control D resolver uid")
runCmd.Flags().StringVarP(&homedir, "homedir", "", "", "")
_ = runCmd.Flags().MarkHidden("homedir")
runCmd.Flags().StringVarP(&iface, "iface", "", "", `Update DNS setting for iface, "auto" means the default interface gateway`)
_ = runCmd.Flags().MarkHidden("iface")
rootCmd.AddCommand(runCmd)
@@ -214,7 +208,8 @@ func initCLI() {
}
}
s, err := service.New(&prog{}, sc)
prog := &prog{}
s, err := service.New(prog, sc)
if err != nil {
stderrMsg(err.Error())
return
@@ -226,12 +221,12 @@ func initCLI() {
{s.Start, true},
}
if doTasks(tasks) {
stdoutMsg("Service started")
return
mainLog.Info().Msg("Service started")
prog.setDNS()
}
},
}
// Keep these flags in sync with runCmd above, except for "-d".
// Keep these flags in sync with runCmd above, except for "-d", "--iface".
startCmd.Flags().StringVarP(&configPath, "config", "c", "", "Path to config file")
startCmd.Flags().StringVarP(&configBase64, "base64_config", "", "", "Base64 encoded config")
startCmd.Flags().StringVarP(&listenAddress, "listen", "", "", "Listener address and port, in format: address:port")
@@ -249,13 +244,16 @@ func initCLI() {
Short: "Stop the ctrld service",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
s, err := service.New(&prog{}, svcConfig)
prog := &prog{}
s, err := service.New(prog, svcConfig)
if err != nil {
stderrMsg(err.Error())
return
}
initLogging()
if doTasks([]task{{s.Stop, true}}) {
stdoutMsg("Service stopped")
mainLog.Info().Msg("Service stopped")
prog.resetDNS()
}
},
}
@@ -272,6 +270,7 @@ func initCLI() {
stderrMsg(err.Error())
return
}
initLogging()
if doTasks([]task{{s.Restart, true}}) {
stdoutMsg("Service restarted")
}
@@ -310,7 +309,8 @@ func initCLI() {
Short: "Uninstall the ctrld service",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
s, err := service.New(&prog{}, svcConfig)
prog := &prog{}
s, err := service.New(prog, svcConfig)
if err != nil {
stderrMsg(err.Error())
return
@@ -319,8 +319,10 @@ func initCLI() {
{s.Stop, false},
{s.Uninstall, true},
}
initLogging()
if doTasks(tasks) {
stdoutMsg("Service uninstalled")
mainLog.Info().Msg("Service uninstalled")
prog.resetDNS()
return
}
},
@@ -391,9 +393,7 @@ func initCLI() {
Use: "start",
Short: "Quick start service and configure DNS on interface",
Run: func(cmd *cobra.Command, args []string) {
if !cmd.Flags().Changed("iface") {
os.Args = append(os.Args, "--iface="+ifaceStartStop)
}
iface = ifaceStartStop
startCmd.Run(cmd, args)
},
}
@@ -405,9 +405,7 @@ func initCLI() {
Use: "stop",
Short: "Quick stop service and remove DNS from interface",
Run: func(cmd *cobra.Command, args []string) {
if !cmd.Flags().Changed("iface") {
os.Args = append(os.Args, "--iface="+ifaceStartStop)
}
iface = ifaceStartStop
stopCmd.Run(cmd, args)
},
}

View File

@@ -3,7 +3,6 @@ package main
import (
"fmt"
"io"
"net"
"os"
"path/filepath"
"time"
@@ -36,7 +35,6 @@ var (
cdUID string
iface string
netIface *net.Interface
ifaceStartStop string
)

View File

@@ -3,16 +3,18 @@ package main
import (
"bufio"
"bytes"
"context"
"fmt"
"net"
"net/netip"
"os/exec"
"strings"
"syscall"
"time"
"github.com/insomniacslk/dhcp/dhcpv4"
"github.com/insomniacslk/dhcp/dhcpv4/client4"
"github.com/insomniacslk/dhcp/dhcpv4/nclient4"
"github.com/insomniacslk/dhcp/dhcpv6"
"github.com/insomniacslk/dhcp/dhcpv6/client6"
"github.com/insomniacslk/dhcp/dhcpv6/nclient6"
"tailscale.com/net/dns"
"tailscale.com/util/dnsname"
@@ -63,40 +65,56 @@ func setDNS(iface *net.Interface, nameservers []string) error {
func resetDNS(iface *net.Interface) error {
var ns []string
c := client4.NewClient()
conversation, err := c.Exchange(iface.Name)
c, err := nclient4.New(iface.Name)
if err != nil {
return err
return fmt.Errorf("nclient4.New: %w", err)
}
for _, packet := range conversation {
if packet.MessageType() == dhcpv4.MessageTypeAck {
nameservers := packet.DNS()
for _, nameserver := range nameservers {
ns = append(ns, nameserver.String())
}
defer c.Close()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
lease, err := c.Request(ctx)
if err != nil {
return fmt.Errorf("nclient4.Request: %w", err)
}
for _, nameserver := range lease.ACK.DNS() {
if nameserver.Equal(net.IPv4zero) {
continue
}
ns = append(ns, nameserver.String())
}
if supportsIPv6() {
c := client6.NewClient()
conversation, err := c.Exchange(iface.Name)
c, err := nclient6.New(iface.Name)
if err != nil {
mainLog.Warn().Err(err).Msg("could not exchange DHCPv6")
mainLog.Warn().Err(err).Msg("could not create DHCPv6 client")
return nil
}
for _, packet := range conversation {
if packet.Type() == dhcpv6.MessageTypeReply {
msg, err := packet.GetInnerMessage()
if err != nil {
return err
}
nameservers := msg.Options.DNS()
for _, nameserver := range nameservers {
ns = append(ns, nameserver.String())
}
}
}
}
defer c.Close()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
solicit, err := dhcpv6.NewSolicit(iface.HardwareAddr)
if err != nil {
return fmt.Errorf("dhcpv6.NewSolicit: %w", err)
}
advertise, err := dhcpv6.NewAdvertiseFromSolicit(solicit)
if err != nil {
return fmt.Errorf("dhcpv6.NewAdvertiseFromSolicit: %w", err)
}
msg, err := c.Request(ctx, advertise)
if err != nil {
return fmt.Errorf("nclient6.Request: %w", err)
}
nameservers := msg.Options.DNS()
for _, nameserver := range nameservers {
if nameserver.Equal(net.IPv6zero) {
continue
}
ns = append(ns, nameserver.String())
}
}
return ignoringEINTR(func() error {
return setDNS(iface, ns)
})

View File

@@ -35,7 +35,6 @@ func (p *prog) Start(s service.Service) error {
}
func (p *prog) run() {
p.setDNS()
if p.cfg.Service.CacheEnable {
cacher, err := dnscache.NewLRUCache(p.cfg.Service.CacheSize)
if err != nil {
@@ -170,7 +169,6 @@ func (p *prog) Stop(s service.Service) error {
mainLog.Error().Err(err).Msg("de-allocate ip failed")
return err
}
p.resetDNS()
mainLog.Info().Msg("Service stopped")
return nil
}
@@ -195,18 +193,23 @@ func (p *prog) deAllocateIP() error {
}
func (p *prog) setDNS() {
if cfg.Listener == nil || cfg.Listener["0"] == nil {
return
}
if iface == "" {
return
}
if iface == "auto" {
iface = defaultIfaceName()
}
logger := mainLog.With().Str("iface", iface).Logger()
var err error
netIface, err = netInterface(iface)
netIface, err := netInterface(iface)
if err != nil {
logger.Error().Err(err).Msg("could not get interface")
return
}
logger.Debug().Msg("setting DNS for interface")
if err := setDNS(netIface, []string{p.cfg.Listener["0"].IP}); err != nil {
if err := setDNS(netIface, []string{cfg.Listener["0"].IP}); err != nil {
logger.Error().Err(err).Msgf("could not set DNS for interface")
return
}
@@ -214,10 +217,18 @@ func (p *prog) setDNS() {
}
func (p *prog) resetDNS() {
if netIface == nil {
if iface == "" {
return
}
if iface == "auto" {
iface = defaultIfaceName()
}
logger := mainLog.With().Str("iface", iface).Logger()
netIface, err := netInterface(iface)
if err != nil {
logger.Error().Err(err).Msg("could not get interface")
return
}
logger.Debug().Msg("Restoring DNS for interface")
if err := resetDNS(netIface); err != nil {
logger.Error().Err(err).Msgf("could not reset DNS")

6
go.mod
View File

@@ -5,6 +5,7 @@ go 1.19
require (
github.com/go-playground/validator/v10 v10.11.1
github.com/hashicorp/golang-lru/v2 v2.0.1
github.com/insomniacslk/dhcp v0.0.0-20211209223715-7d93572ebe8e
github.com/kardianos/service v1.2.1
github.com/lucas-clemente/quic-go v0.29.1
github.com/miekg/dns v1.1.50
@@ -14,6 +15,7 @@ require (
github.com/spf13/viper v1.14.0
github.com/stretchr/testify v1.8.1
golang.org/x/sys v0.4.0
golang.zx2c4.com/wireguard/windows v0.5.3
tailscale.com v1.34.1
)
@@ -35,7 +37,6 @@ require (
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 // indirect
github.com/illarion/gonotify v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/insomniacslk/dhcp v0.0.0-20211209223715-7d93572ebe8e // indirect
github.com/josharian/native v1.0.0 // indirect
github.com/jsimonetti/rtnetlink v1.1.2-0.20220408201609-d380b505068b // indirect
github.com/leodido/go-urn v1.2.1 // indirect
@@ -45,8 +46,10 @@ require (
github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 // indirect
github.com/mdlayher/genetlink v1.2.0 // indirect
github.com/mdlayher/netlink v1.6.0 // indirect
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065 // indirect
github.com/mdlayher/socket v0.2.3 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/nxadm/tail v1.4.8 // indirect
@@ -72,7 +75,6 @@ require (
golang.org/x/tools v0.1.12 // indirect
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
golang.zx2c4.com/wireguard v0.0.0-20220920152132-bb719d3a6e2c // indirect
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect

4
go.sum
View File

@@ -164,6 +164,7 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 h1:aSVUgRRRtOrZOC1fYmY9gV0e9z/Iu+xNVSASWjsuyGU=
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3/go.mod h1:5PC6ZNPde8bBqU/ewGZig35+UIZtw9Ytxez8/q5ZyFE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8=
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@@ -212,6 +213,7 @@ github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZb
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 h1:lez6TS6aAau+8wXUP3G9I3TGlmPFEq2CTxBaRqY6AGE=
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
github.com/mdlayher/genetlink v1.2.0 h1:4yrIkRV5Wfk1WfpWTcoOlGmsWgQj3OtQN9ZsbrE+XtU=
github.com/mdlayher/genetlink v1.2.0/go.mod h1:ra5LDov2KrUCZJiAtEvXXZBxGMInICMXIwshlJ+qRxQ=
@@ -222,6 +224,7 @@ github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZ
github.com/mdlayher/netlink v1.6.0 h1:rOHX5yl7qnlpiVkFWoqccueppMtXzeziFjWAjLg6sz0=
github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA=
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065 h1:aFkJ6lx4FPip+S+Uw4aTegFMct9shDvP+79PsSxpm3w=
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
github.com/mdlayher/socket v0.2.3 h1:XZA2X2TjdOwNoNPVPclRCURoX/hokBY8nkTmRZFEheM=
@@ -275,6 +278,7 @@ github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=