cmd/ctrld: spoofing client IP on routers

This commit is contained in:
Cuong Manh Le
2023-05-30 00:52:04 +07:00
committed by Cuong Manh Le
parent b143e46eb0
commit 2d950eecdf
2 changed files with 40 additions and 2 deletions

View File

@@ -50,11 +50,12 @@ func (p *prog) serveDNS(listenerNum string) error {
q := m.Question[0]
domain := canonicalName(q.Name)
reqId := requestID()
fmtSrcToDest := fmtRemoteToLocal(listenerNum, w.RemoteAddr().String(), w.LocalAddr().String())
remoteAddr := spoofRemoteAddr(w.RemoteAddr(), router.GetClientInfoByMac(macFromMsg(m)))
fmtSrcToDest := fmtRemoteToLocal(listenerNum, remoteAddr.String(), w.LocalAddr().String())
t := time.Now()
ctx := context.WithValue(context.Background(), ctrld.ReqIdCtxKey{}, reqId)
ctrld.Log(ctx, mainLog.Debug(), "%s received query: %s %s", fmtSrcToDest, dns.TypeToString[q.Qtype], domain)
upstreams, matched := p.upstreamFor(ctx, listenerNum, listenerConfig, w.RemoteAddr(), domain)
upstreams, matched := p.upstreamFor(ctx, listenerNum, listenerConfig, remoteAddr, domain)
var answer *dns.Msg
if !matched && listenerConfig.Restricted {
answer = new(dns.Msg)
@@ -418,6 +419,18 @@ func macFromMsg(msg *dns.Msg) string {
return ""
}
func spoofRemoteAddr(addr net.Addr, ci *ctrld.ClientInfo) net.Addr {
if ci != nil && ci.IP != "" {
switch addr := addr.(type) {
case *net.UDPAddr:
addr.IP = net.ParseIP(ci.IP)
case *net.TCPAddr:
addr.IP = net.ParseIP(ci.IP)
}
}
return addr
}
// runDNSServer starts a DNS server for given address and network,
// with the given handler. It ensures the server has started listening.
// Any error will be reported to the caller via returned channel.

View File

@@ -191,3 +191,28 @@ func Test_macFromMsg(t *testing.T) {
})
}
}
func Test_remoteAddrFromMsg(t *testing.T) {
loopbackIP := net.ParseIP("127.0.0.1")
tests := []struct {
name string
addr net.Addr
ci *ctrld.ClientInfo
want string
}{
{"tcp", &net.TCPAddr{IP: loopbackIP, Port: 12345}, &ctrld.ClientInfo{IP: "192.168.1.10"}, "192.168.1.10:12345"},
{"udp", &net.UDPAddr{IP: loopbackIP, Port: 12345}, &ctrld.ClientInfo{IP: "192.168.1.11"}, "192.168.1.11:12345"},
{"nil client info", &net.UDPAddr{IP: loopbackIP, Port: 12345}, nil, "127.0.0.1:12345"},
{"empty ip", &net.UDPAddr{IP: loopbackIP, Port: 12345}, &ctrld.ClientInfo{}, "127.0.0.1:12345"},
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
addr := spoofRemoteAddr(tc.addr, tc.ci)
if addr.String() != tc.want {
t.Errorf("unexpected result, want: %q, got: %q", tc.want, addr.String())
}
})
}
}