I'm testing something with IP masquerade on locally generated traffic but it seems to be breaking DNS lookups. Everything else works fine--all IP traffic without DNS queries work.
$ iptables -t mangle -A OUTPUT -j MARK --set-mark 2
$ iptables -t nat -A POSTROUTING -m mark --mark 0x2 -j MASQUERADE
Why does this work with all IP traffic except DNS queries?
Results of requested commands below:
# ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp2s0f1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
link/ether 54:21:c6:28:99:1f brd ff:ff:ff:ff:ff:ff
3: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether c1:b2:a1:55:34:d2 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.108/24 brd 192.168.1.255 scope global dynamic noprefixroute wlp3s0
valid_lft 242078sec preferred_lft 242078sec
inet6 fe80::1dd6:f094:be8d:ef51/64 scope link noprefixroute
valid_lft forever preferred_lft forever
# ip route
default via 192.168.1.1 dev wlp3s0 proto dhcp metric 600
169.254.0.0/16 dev wlp3s0 scope link metric 1000
192.168.1.0/24 dev wlp3s0 proto kernel scope link src 192.168.1.108 metric 600
In a surprise twist, systemd is acting as a DNS server on 127.0.0.53.
systemctl status systemd-resolved
is reporting "systemd-resolved[3315]: Got packet on unexpected IP range, refusing." after enabling the two commands.
I believe this issue may be related.
- https://github.com/kubernetes/kubernetes/issues/66067
- https://github.com/kontena/pharos-cluster/issues/482
The relevant portions of those two links are:
all queries to 127.0.0.53:53 goes not from 127.0.0.0/8, but from interface with default route due to masquerading, and systemd-resolved rejects all of these requests with
systemd-resolved[21366]: Got packet on unexpected IP range, refusing.
systemd-resolved
goes to the extra effort of validating the stub resolver source/dest addresses, and thus MASQUERADE rule breaks those assumptions:
if (in_addr_is_localhost(p->family, &p->sender) <= 0 ||
in_addr_is_localhost(p->family, &p->destination) <= 0) {
log_error("Got packet on unexpected IP range, refusing.");
dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false);
goto fail;
}
any
or eg 127.0.1.1 and superseding the dhcp's dns setting in /etc/resolv.conf, then doing a query to 127.0.1.1 (anything else than 127.0.0.1) can go wrong, eg (conntrack -E
):[NEW] udp 17 30 src=127.0.0.1 dst=127.0.1.1 sport=38781 dport=53 [UNREPLIED] src=127.0.1.1 dst=10.0.3.66 sport=53 dport=38781
. Answer fails (EINVAL) if answering with sendto(). I have some theories, but first there are a lot of ifs that OP should confirm. doesn't involve mark. btw avoiding it is simple: state the interface in iptables to filter outlo
.