익명 04:27

How to prevent DHCP leakage?

How to prevent DHCP leakage?

I have a Raspberry Pi 5 (Raspbian Trixie, Linux 6.18) running a Wi-Fi AP with clients on their own 10.10.3.x subnet, DHCP-served with [static] addresses from the Raspberry Pi. The Wi-Fi AP is driven by hostapd and created as a bridge under systemd-networkd in order that everyone gets access to everything. The Raspberry Pi is connected to my main LAN via Ethernet on a 10.10.2.x address which is statically allocated by the main router on the LAN and the Ethernet port on which the Raspberry Pi joins the main router is firewall protected.

My problem is that, with the bridge arrangement on the Raspberry Pi, its DHCP server sees not only the DHCP requests from the Wi-Fi clients but also sees any DHCP requests on the main network via eth0, and serves them [a 10.10.3.x address], which is causing some chaos. I've tried ebtables and iptables (to block DHCP traffic coming in from eth0, but not all DHCP traffic as the Raspberry Pi needs to be able to obtain its own static address for eth0), I've tried using dnsmasq or isc-dhcp-server (to bind to specific interfaces) instead of systemd-networkd's built-in DHCP server but nothing works: DHCP requests seem to get into the bridge from eth0 without passing through ebtables or iptables, so they hit the bridge and, once in the bridge, no-one can tell where they came from in order to serve wlan0 differently to eth0.

It has been suggested that I don't have a bridge and instead NAT Wi-Fi stuff across to eth0, but then I lose flexibility because, as far as the main router is concerned, everything attached to the Raspberry Pi is coming from the Raspberry Pi's IP address. I would have no way of letting a particular Wi-Fi attached device out to the internet if I wanted to. Okay, I don't currently need this but I can see that it would be a useful thing to do for the future.

Is there a way to keep the bridge and stop it serving everyone their DHCP requests?



Top Answer/Comment:

First of all, if you have the Wi-Fi clients on their own subnet, that already brings you the that routing (with NAT or without) would bring.

It's not the absence of a bridge per se that that brings the need for NAT, but rather the main router's lack of knowledge about where to direct packets meant for 10.10.3.x or other non-local destinations.

So if your Wi-Fi clients have a completely different IP address range, then having the bridge doesn't really do you much help anyway. What happens if 10.10.3.7 sends a packet to the Internet? If it has learned 10.0.3.1 (the Raspberry Pi) as its gateway via DHCP, it'll send packets to the Pi, which then routes them (exactly as without a bridge) via the main LAN gateway – and when it's time for the LAN gateway to deliver packets back to 10.10.3.7, it'll have no idea where to send them (since it's a non-local address), again exactly like without the bridge.

The only difference is that the two can happen to figure out a direct path through the bridge, bypassing the Raspberry Pi's routing (thanks to ICMP redirects), but that also means they'll be bypassing the Raspberry Pi's firewall too, which is something you don't want (and which wouldn't happen if there were no bridge).

So in the end you will have all of the "non-bridge" problems in addition to those caused by the bridge.

DHCP requests seem to get into the bridge from eth0 without passing through ebtables or iptables, so they hit the bridge and, once in the bridge, no-one can tell where they came from in order to serve wlan0 differently to eth0.

That's the bridge doing its job as expected. But it might be that you're using the wrong ebtables chain (INPUT vs PREROUTING). Keep in mind that DHCPv4 clients and sometimes servers use "raw sockets" which pick up packets at an early state (due to them lacking regular IP source/destination), so while I'm not sure if that bypasses ebtables, it will indeed bypass regular iptables.

Nftables supports a few more hooks at which filtering may happen, e.g. the "ingress" hook can drop packets at a very early stage, so it might be able to achieve the filtering you want (but it has no equivalent for egress).

If you must have a bridge, a much easier option might to remove the second DHCP server entirely — have a single IP range and a single DHCP server handling the whole network – and instead use ebtables to filter the actual device traffic when it's crossing the bridge. For example, use ebtables to prevent your lightbulb's IP or MAC address from talking to non-LAN IPs and/or to your gateway's MAC.

On Linux, you can even enable iptables processing for bridged traffic (there is a sysctl knob for that).

(Still, my general opinion is that you shouldn't have a bridge.)

It has been suggested that I don't have a bridge and instead NAT Wi-Fi stuff across to eth0, but then I lose flexibility because, as far as the main router is concerned, everything attached to the Raspberry Pi is coming from the Raspberry Pi's IP address. I would have no way of letting a particular Wi-Fi attached device out to the internet if I wanted to. Okay, I don't currently need this but I can see that it would be a useful thing to do for the future.

Keep in mind that NAT isn't the thing that forwards packets through a router (i.e. the Pi). The router already forwards packets by nature of being a router, while NAT is something that's optionally added on top of that, typically as a workaround for something – it isn't automatically mandatory to have when not bridging.

The main purpose of NAT in this case would be to to work around the inability to define routes from your main router (towards other subnets). But if your main router can do that, then you don't need NAT at all – you can route across subnets while preserving the source address (i.e. the default way IP routing works).

If your main router doesn't allow you to customize its routes – replace it with a better one that does.

Alternatively, NAT rules in iptables support all of the matching operators filter rules do. So if the main router doesn't allow custom routes, there's still a middle ground where you NAT traffic if it goes to the Internet (towards your main router), but don't NAT traffic if it goes to your PCs or home servers (in which you can practically always define routes, it's just more of a bother doing it on every PC).

There's also yet another option that works without bridging. The Pi can use proxy ARP to answer ARP queries on the "main" side on behalf of all the devices it has on the WLAN side. This way it can "attract" traffic for some IP addresses within the same subnet, allowing the Pi to route them further (and apply firewall rules). (Some dedicated access points even do proxy ARP over a bridge for efficiency reasons.)

With ARP proxying, both sides could appear to be in the same subnet and share an IP address range (while in reality being different subnets with their own DHCP servers), and the main router – or your PCs on the main side – wouldn't need to know or care that there's another gateway in the middle.

상단 광고의 [X] 버튼을 누르면 내용이 보입니다