Improving Mac discovery

This commit is contained in:
Cuong Manh Le
2023-07-14 16:53:17 +00:00
committed by Cuong Manh Le
parent 3007cb86ec
commit 76d2e2c226
22 changed files with 1229 additions and 291 deletions
+3
View File
@@ -1138,6 +1138,7 @@ func validateConfig(cfg *ctrld.Config) {
os.Exit(1)
}
// NOTE: Add more case here once new validation tag is used in ctrld.Config struct.
func fieldErrorMsg(fe validator.FieldError) string {
switch fe.Tag() {
case "oneof":
@@ -1165,6 +1166,8 @@ func fieldErrorMsg(fe validator.FieldError) string {
return fmt.Sprintf("must be one of: %q", strings.Join(ipStacks, " "))
case "iporempty":
return fmt.Sprintf("invalid IP format: %s", fe.Value())
case "file":
return fmt.Sprintf("filed does not exist: %s", fe.Value())
}
return ""
}
+22 -9
View File
@@ -55,7 +55,10 @@ func (p *prog) serveDNS(listenerNum string) error {
q := m.Question[0]
domain := canonicalName(q.Name)
reqId := requestID()
remoteAddr := spoofRemoteAddr(w.RemoteAddr(), p.mt.GetClientInfoByMac(macFromMsg(m)))
remoteIP, _, _ := net.SplitHostPort(w.RemoteAddr().String())
mac := macFromMsg(m)
ci := p.getClientInfo(remoteIP, mac)
remoteAddr := spoofRemoteAddr(w.RemoteAddr(), ci)
fmtSrcToDest := fmtRemoteToLocal(listenerNum, remoteAddr.String(), w.LocalAddr().String())
t := time.Now()
ctx := context.WithValue(context.Background(), ctrld.ReqIdCtxKey{}, reqId)
@@ -66,7 +69,7 @@ func (p *prog) serveDNS(listenerNum string) error {
answer = new(dns.Msg)
answer.SetRcode(m, dns.RcodeRefused)
} else {
answer = p.proxy(ctx, upstreams, failoverRcodes, m)
answer = p.proxy(ctx, upstreams, failoverRcodes, m, ci)
rtt := time.Since(t)
ctrld.Log(ctx, mainLog.Debug(), "received response of %d bytes in %s", answer.Len(), rtt)
}
@@ -202,7 +205,7 @@ networkRules:
return upstreams, matched
}
func (p *prog) proxy(ctx context.Context, upstreams []string, failoverRcodes []int, msg *dns.Msg) *dns.Msg {
func (p *prog) proxy(ctx context.Context, upstreams []string, failoverRcodes []int, msg *dns.Msg, ci *ctrld.ClientInfo) *dns.Msg {
var staleAnswer *dns.Msg
serveStaleCache := p.cache != nil && p.cfg.Service.CacheServeStale
upstreamConfigs := p.upstreamConfigsFromUpstreamNumbers(upstreams)
@@ -245,12 +248,9 @@ func (p *prog) proxy(ctx context.Context, upstreams []string, failoverRcodes []i
return dnsResolver.Resolve(resolveCtx, msg)
}
resolve := func(n int, upstreamConfig *ctrld.UpstreamConfig, msg *dns.Msg) *dns.Msg {
if upstreamConfig.UpstreamSendClientInfo() {
ci := p.mt.GetClientInfoByMac(macFromMsg(msg))
if ci != nil {
ctrld.Log(ctx, mainLog.Debug(), "including client info with the request")
ctx = context.WithValue(ctx, ctrld.ClientInfoCtxKey{}, ci)
}
if upstreamConfig.UpstreamSendClientInfo() && ci != nil {
ctrld.Log(ctx, mainLog.Debug(), "including client info with the request")
ctx = context.WithValue(ctx, ctrld.ClientInfoCtxKey{}, ci)
}
answer, err := resolve1(n, upstreamConfig, msg)
if err != nil {
@@ -510,3 +510,16 @@ func inContainer() bool {
})
return ret
}
func (p *prog) getClientInfo(ip, mac string) *ctrld.ClientInfo {
ci := &ctrld.ClientInfo{}
if mac != "" {
ci.Mac = mac
ci.IP = p.ciTable.LookupIP(mac)
} else {
ci.IP = ip
ci.Mac = p.ciTable.LookupMac(ip)
}
ci.Hostname = p.ciTable.LookupHostname(ci.IP, ci.Mac)
return ci
}
+2 -2
View File
@@ -149,8 +149,8 @@ func TestCache(t *testing.T) {
answer2.SetRcode(msg, dns.RcodeRefused)
prog.cache.Add(dnscache.NewKey(msg, "upstream.0"), dnscache.NewValue(answer2, time.Now().Add(time.Minute)))
got1 := prog.proxy(context.Background(), []string{"upstream.1"}, nil, msg)
got2 := prog.proxy(context.Background(), []string{"upstream.0"}, nil, msg)
got1 := prog.proxy(context.Background(), []string{"upstream.1"}, nil, msg, nil)
got2 := prog.proxy(context.Background(), []string{"upstream.0"}, nil, msg, nil)
assert.NotSame(t, got1, got2)
assert.Equal(t, answer1.Rcode, got1.Rcode)
assert.Equal(t, answer2.Rcode, got2.Rcode)
+16 -18
View File
@@ -48,11 +48,11 @@ type prog struct {
logConn net.Conn
cs *controlServer
cfg *ctrld.Config
cache dnscache.Cacher
sema semaphore
mt *clientinfo.MacTable
router router.Router
cfg *ctrld.Config
cache dnscache.Cacher
sema semaphore
ciTable *clientinfo.Table
router router.Router
started chan struct{}
onStarted []func()
@@ -106,24 +106,22 @@ func (p *prog) run() {
uc.Init()
if uc.BootstrapIP == "" {
uc.SetupBootstrapIP()
mainLog.Info().Msgf("Bootstrap IPs for upstream.%s: %q", n, uc.BootstrapIPs())
mainLog.Info().Msgf("bootstrap IPs for upstream.%s: %q", n, uc.BootstrapIPs())
} else {
mainLog.Info().Str("bootstrap_ip", uc.BootstrapIP).Msgf("Using bootstrap IP for upstream.%s", n)
mainLog.Info().Str("bootstrap_ip", uc.BootstrapIP).Msgf("using bootstrap IP for upstream.%s", n)
}
uc.SetCertPool(rootCertPool)
go uc.Ping()
}
p.mt = clientinfo.NewMacTable()
if p.cfg.HasUpstreamSendClientInfo() {
mainLog.Debug().Msg("Sending client info enabled")
if err := p.mt.Init(); err == nil {
mainLog.Debug().Msg("Start watching client info changes")
go p.mt.WatchLeaseFiles()
} else {
mainLog.Warn().Err(err).Msg("could not record client info")
}
p.ciTable = clientinfo.NewTable(&cfg)
if leaseFile := p.cfg.Service.DHCPLeaseFile; leaseFile != "" {
mainLog.Debug().Msgf("watching custom lease file: %s", leaseFile)
format := ctrld.LeaseFileFormat(p.cfg.Service.DHCPLeaseFileFormat)
p.ciTable.AddLeaseFile(leaseFile, format)
}
p.ciTable.Init()
go p.ciTable.RefreshLoop(p.stopCh)
go p.watchLinkState()
for listenerNum := range p.cfg.Listener {
@@ -136,7 +134,7 @@ func (p *prog) run() {
mainLog.Warn().Msgf("no default upstream for: [listener.%s]", listenerNum)
}
addr := net.JoinHostPort(listenerConfig.IP, strconv.Itoa(listenerConfig.Port))
mainLog.Info().Msgf("Starting DNS server on listener.%s: %s", listenerNum, addr)
mainLog.Info().Msgf("starting DNS server on listener.%s: %s", listenerNum, addr)
err := p.serveDNS(listenerNum)
if err != nil && !defaultConfigWritten && cdUID == "" {
mainLog.Fatal().Err(err).Msgf("Unable to start dns proxy on listener.%s", listenerNum)
@@ -162,7 +160,7 @@ func (p *prog) run() {
p.cfg.Service.AllocateIP = true
p.mu.Unlock()
p.preRun()
mainLog.Info().Msgf("Starting DNS server on listener.%s: %s", listenerNum, net.JoinHostPort(ip, strconv.Itoa(port)))
mainLog.Info().Msgf("starting DNS server on listener.%s: %s", listenerNum, net.JoinHostPort(ip, strconv.Itoa(port)))
if err := p.serveDNS(listenerNum); err != nil {
mainLog.Fatal().Err(err).Msgf("Unable to start dns proxy on listener.%s", listenerNum)
return