Score:0

How to redirect DNS request to a remote systemd-resolved?

ve flag

I was trying to make system-resolved as a remote DNS caching server (I know it is not intended to do so). I added the changed the net.ipv4.conf.br0.route_localnet to 1 and added the following nftable rules:

table ip nat {
    chain prerouting {
        type nat hook prerouting priority 100; policy accept;
        iif "br0" udp dport 53 counter packets 6 bytes 366 dnat to 127.0.0.53
    }

    chain postrouting {
        type nat hook postrouting priority -100; policy accept;
        ip saddr 127.0.0.53 oif "br0" counter packets 0 bytes 0 snat to 192.168.1.2
    }
}

The prerouting rule seems working as there are packets matching the rules. However there is no packet out of the host, what is the problem?

How can I redirect DNS request from 192.168.1.0/24 to systemd-resolved hosted on 192.168.1.2's lo device with IP 127.0.0.53?

Score:1
cl flag
A.B

systemd-resolved binds to the lo interface:

# ss -aunp src == 127.0.0.53 sport == 53
State  Recv-Q Send-Q Local Address:Port  Peer Address:Port 
UNCONN 0      0      127.0.0.53%lo:53         0.0.0.0:*     users:(("systemd-resolve",pid=44157,fd=17))

This limits available routes even once net.ipv4.conf.br0.route_localnet=1 is applied to those set on the lo interface:

$ ip -4 route show table all dev lo
broadcast 127.0.0.0 table local proto kernel scope link src 127.0.0.1 
local 127.0.0.0/8 table local proto kernel scope host src 127.0.0.1 
local 127.0.0.1 table local proto kernel scope host src 127.0.0.1 
broadcast 127.255.255.255 table local proto kernel scope link src 127.0.0.1 

None will match.

The source address would need to be changed. While the rarely used type nat hook input chain type would allow to change the source address before the application received it, it's already too late: this happens after routing was done and packet is already dropped. So stateful NAT can't handle this case.


Instead a proxy could be used for this (after removing all the specific nat settings). Here's an example using socat. socat not being a dedicated application, there are caveats especially for UDP.

  • TCP handling (OP forgot that DNS uses TCP too)

    socat TCP4-LISTEN:53,bind=192.168.1.2,reuseaddr,fork TCP4:127.0.0.53:53
    

    Can't bind to IN_ADDR_ANY because 127.0.0.53:53 is already bound, so bind to OP's provided address (for the wrong reasons): 192.168.1.2. Beside this, it's quite simple.

  • UDP handling

    socat -T 20 UDP4-LISTEN:53,bind=192.168.1.2,reuseaddr,fork UDP4:127.0.0.53:53
    

    The 20s timeout is here because socat can't be told to cease right after receiving the single UDP packet answer and would keep all the forked socat commands accumulating over time.

    While UDP doesn't have to bind to an address in this case, binding to an address using UDP avoids the caveat related to multi-homing and the need to use the IP_PKTINFO socket option.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.