Score:1

Prevent routing of DHCP traffic

ng flag

First, I'm aware that similar questions to mine have been asked elsewhere (I've read many of those posts!) but I've not been able to figure out a solution to my problem, so I'm asking for help.

My setup

I have two networks on my LAN, 192.168.0.0/24 and 10.11.12.0/24. The former has DHCP running on my WAN router, the latter runs dnsmasq on Ubuntu Server 20.04 on a box that also serves as a router between the two subnets. I've configured dnsmasq to only serve DHCP on the 10.11.12.0/24 network with the no-dhcp-interface=wlp3s0 option, wlp3s0 being the interface on the 192.168.0.0/24 side.

To summarise:

WAN Router (gateway to WAN) is 192.168.0.1/24
  Runs DHCP for clients on 192.168.0.0/24

Router (b/w subnets):
  Ubuntu Server 20.04 with two interfaces
    wlp3s0: 192.168.0.2/24 (static IP)
    eno1:  10.11.12.1/24 (static IP)

I've configured iptables to FWD and NAT like so.

iptables -t nat -A POSTROUTING -o wlp3s0 -j MASQUERADE  
iptables -A FORWARD -i wlp3s0 -o eno1 -m state --state RELATED,ESTABLISHED -j ACCEPT  
iptables -A FORWARD -i eno1 -o wlp3s0 -j ACCEPT

I've allowed DHCP through my firewall with ufw allow 67/udp:

To                         Action      From
--                         ------      ----
67/udp                     ALLOW IN    Anywhere

Everything appears to be working fine. However, from experience I know that running two DHCP servers like this can cause conflicts unless they are kept strictly separate. (Clients intended for the 192.168.0.0/24 network wouldn't be all too pleased if DHCP gave them an IP address on the 10.11.12.0/24 network!)

Discovering the problem

So I did the following to test it out. I set up a tcpdump listening on the wlp3s0 interface (192.168.0.2) and used nmap to simulate a DHCP Discover request originating on the eno1 interface (10.11.12.1/24), like so:

sudo tcpdump -i wlp3s0 -n udp port 67 or port 68

sudo nmap --script broadcast-dhcp-discover -e eno1

As expected I get a DHCP offer from dnsmasq running on 10.11.12.1. So far so good!

Some detail omitted from the output for brevity (he said)

Starting Nmap 7.80 ( https://nmap.org ) at 2021-12-22 16:19 UTC
Pre-scan script results:
| broadcast-dhcp-discover:
|   Response 1 of 1:
|     IP Offered: 10.11.12.53
|     DHCP Message Type: DHCPOFFER
|     Server Identifier: 10.11.12.1
|     Broadcast Address: 10.11.12.255
|     Subnet Mask: 255.255.255.0
|     Domain Name Server: 10.11.12.1
|_    Router: 10.11.12.1

However, tcpdump shows that both DHCP servers respond to the discover request. (In fact, my WAN router sends 2 replies!)

16:19:43.517029 IP 10.11.12.1.68 > 255.255.255.255.67: BOOTP/DHCP, Request from de:ad:c0:de:ca:fe, length 316
16:19:46.486227 IP 10.11.12.1.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 321
16:19:46.794207 IP 192.168.0.1.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 323
16:19:46.794207 IP 192.168.0.1.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 323

It seems the DHCP discover request is forwarded to the 192.168.0.0/24 network via the wlp3s0 interface. Looking at my iptables and firewall rules I see no reason to be surprised by this. However, what I'm really struggling with is figuring out how to prevent it.

What I've tried

I've tried various permutations of rules in both ufw and iptables but to no avail, likely because I don't fully understand either iptables or ufw. A few examples of what I tried:

(All ufw/iptables rules were added at the top of the respective ruleset/chain to ensure they were hit.)

ufw:

# Restrict 67/udp to one interface
ufw allow in on eno1 proto udp from 0.0.0.0/0 to 0.0.0.0/0 port 67

# Deny routing
ufw route deny in on eno1 out on wlp3s0 to 0.0.0.0/0 port 67 proto udp

iptables:

# Prevent forwarding of UDP port 67/68
iptables -I FORWARD 1 -p udp --match multiport --dports 67,68 -j DROP

# Drop outbound UDP port 67
iptables -I OUTPUT 1 -p udp --match multiport --dports 67,68 -o wlp3s0 -j DROP

I must be missing some fundamental understanding of how this works since none of the above prevents the WAN router DHCP from receiving the discover and offering an IP on the 192.168.0.0/24 subnet.

I did read somewhere that DHCP servers may listen on a raw (or packet?) socket, which isn't subject to iptables. That isn't the case with dnsmasq as documented here https://github.com/imp/dnsmasq/blob/master/FAQ#L195. I also proved that by deleting the allow 67/udp rule in ufw, after which dnsmasq stops responding to DHCP discover. Perhaps surprisingly (or not), even with the allow rule deleted in ufw my WAN router continues to receive and respond to DHCP discover. Presumably because I have iptables rules configured to forward all traffic, but no equivalent INPUT rule (until I add one using ufw).

What I'd like to achieve

Preferably I'd like to prevent the DHCP discover broadcast on the 10.11.12.0/24 network from even reaching the 192.168.0.0/24 network.

If that proves difficult, I'd be happy to just prevent DHCP offers from my WAN router from reaching the 10.11.12.0/24 network.

Note that I do not have a problem on the 192.168.0.0/24 network since I've configured dnsmasq to not offer DHCP on the wlp3s0 interface (192.168.0.2). That appears to be working and DHCP discover on wlp3s0 (192.168.0.2/24) do not get a reply from dnsmasq.

So what am I missing? Am I going about this entirely wrong or am I just not getting it quite right? Any help is much appreciated.

Happy holidays!

Update

In response to a question in the comments from @sleepyhead, here is my iptables nat setup.

Chain PREROUTING (policy ACCEPT 13452 packets, 4312K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain INPUT (policy ACCEPT 48 packets, 12715 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 87 packets, 10884 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 55 packets, 8622 bytes)
 pkts bytes target     prot opt in     out     source               destination
   32  2262 MASQUERADE  all  --  *      wlp3s0  0.0.0.0/0            0.0.0.0/0

Update 2

Is it possible that this is an artefact of how I conduct my test? What makes me suspicious is the source IP of the tcpdump output. Could it be that running DHCP Discover on an interface that already has an IP produces a different result than if it didn't? Anyway, if I can repurpose one of my Raspberry Pis I'll run this test with it as a DHCP client and see if I get the same output, though I suspect I will.

ru flag
What you need to do is disable one of the DHCP servers and use a DHCP Relay mechanism to relay DHCP from one network to another. The only way to do that is with specialized NATting which can be problematic or setting up DHCP Relays on the segments of the network you *want* to not have a DHCP server and relay to another DHCP server. This is, by the way, how it's done in the normal world when you have a DHCP server on a different subnet from the network you're doing DHCP for.
sleepyhead avatar
in flag
The 2 replies you see from the wan router is the same one, you see the incoming and outgoing, somehow your interfaces seem bridged, because a broadcast to 255.255.255.255 should not jump network boundaries, but yours does. If you keep the bridge, you have to L2 firewall with ebtables. Don't let the raw socket discussion confuse you, it's more of an implementation debate between os'es than describing your issue. ``` ip addr brctl show ``` These will show you the bridge between interfaces
ng flag
Thanks for responding, but according to brctl show there is no bridge (there is no output from that command).
ng flag
I was hoping to avoid that. My main reason for having the secondary DHCP is to provide PXE boot on the 10.11.12.0 network. There is also the added complication that the wi-fi interface on that box is pretty flaky so I wouldn't want to rely on it to provide DHCP services for my main (192) network. Worst case I may be able to get away with what I have since there seems to be sufficient lag between the two DHCP offers that my preferred DHCP looks likely to always (?) win on the 10.11.12.0 network and the 192.168.0.0 network has no conflict with my setup.
sleepyhead avatar
in flag
If it is not a bridge then somehow traffic is nat'ted, including broadcasts, that's would neet dropping, can you post the iptables output? iptable -L v -n -t nat
ng flag
I've added the output to my question above, thanks.
Score:0
ng flag

All sorted, @sleepyhead was onto something about the routing but the issue was much more mundane (or idiotic!) than bridged interfaces etc. There's a switch on the 10.11.12.0/24 network and it turns out I'd left a cable in it that was connected to one of my mesh routers! So there were in fact two routes out of the box to the 192.168.0.0/24 network, one via the wlp3s0 interface (correctly blocked in iptables) and another out via eno1, which obviously was open. This explains why I kept receiving responses from the WAN router and also, I think, why they were duplicated.

Well, blunders aside I hope this will be helpful to someone given how many questions are asked about DHCP and routing.

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.