On 12/3/25 23:55, Sławomir Zborowski wrote:
 > There's not really such a thing as an "inet interface" or an "inet6
 > interface" an interface, represented by an index, can have multiple
 > addresses, both IPv4 and IPv6.

You're right. That was imprecise mental shortcut.

 > What I would expect to see here is that the interface had both IPv4
 > addresses and IPv6 addresses when it was added to the daemon->interfaces
 > list, so this check will find at least one entry on that list which came
 > from the arrival interface and has the correct address family.

The thing is it only has the IPv6 address. This is how Calico (or the OS
- I'm not entirely sure) configures it.

 > Your description implies that the TCP connection is over IPv4. Does the
 > interface is arrives on have an IP4 address?

Destination is a regular eth0 iface on the server with IPv4 address only.
The connection originates from a Pod that is connected through veth pair.
That veth pair has only IPv6 address in the system.

 > As usual, the most useful resource here is the simplest configuration
 > which demonstrates this problem on the most vanilla kernel network
 > configuration.

I'm not sure if that's the most vanilla way out there, but I believe that
Calico does something along following. I'm not sure if the proxy_arp
thing is necessary. With following I was able to reproduce the problem.

# ip netns add fakepod
# ip link add host-veth type veth peer name pod-veth
# ip link set pod-veth netns fakepod
# ip link set host-veth up
# echo 1 | sudo tee /proc/sys/net/ipv4/conf/host-veth/proxy_arp
# ip netns exec fakepod bash
# ip link set lo up
# ip link set pod-veth up
# ip addr add 10.44.0.51/32 <http://10.44.0.51/32> dev pod-veth
# ip route add default dev pod-veth
# ip route add 169.254.1.1/32 <http://169.254.1.1/32> dev pod-veth
# exit
# ip route add 10.44.0.51/32 <http://10.44.0.51/32> dev host-veth

Now, start dnsmasq on the host:
# sudo ./src/dnsmasq -d --log-debug 2>&1 | tee /tmp/dnsmasq.log

And trigger the behavior:
# ip netns exec fakepod dig duckduckgo.com <http://duckduckgo.com>. A +tcp @[REDACTED: server eth0 physical IPv4 address] ;; communications error to [REDACTED: server eth0 physical IPv4 address]#53: end of file

;; communications error to [REDACTED: server eth0 physical IPv4 address]#53: end of file

This is, by the way, how the iface shows up in the system:
266: host-veth@if265: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
     link/ether d6:35:97:b9:51:f0 brd ff:ff:ff:ff:ff:ff link-netns fakepod
     inet6 fe80::d435:97ff:feb9:51f0/64 scope link
        valid_lft forever preferred_lft forever

And dnsmasq will recognize it as IPv6. I added some debug prints
to verify that it happens. Incoming TCP addr sa_family is 0x2, iface
sa_family is 0xA.

I think the IPv6 address that is attached to the veth host end is added
by the OS.

Hopefully all of the above is helpful.

So basically, dnsmasq receives a TCP connection from 10.44.0.51 to [redacted] through the host-veth interface, but the host-veth interface only have a ipv6 link-local and no ipv4. [redacted] is actually configured on eth0.

It is quite difficult for a TCP server to know from which an interface a request comes from. Finding the interface where the destination address was configured only works on systems with a strong host model, but linux uses a weak host model and your setup rely on it.

A weak host model system will accept packets from 10.44.0.51 to [redacted] regardless of the interface the packet came from. And replies are sent to whatever interface the FIB says should be used and the interface may change over time.

A workaround would be to use RTM_GETROUTE on the source address and consider that as the interface the request came from, but that could cause other problems.

_______________________________________________
Dnsmasq-discuss mailing list
[email protected]
https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss

Reply via email to