Score:0

Using iptables and hostapd to create isolated guest AP

za flag

I'm trying to setup my raspberry pi as an access point for guests to be able to connect to, that should allow them internet access but not access to the rest of my network, the pi also is my DHCP and DNS server, for which I am using hostapd, dnsmasq & iptables all running on alpine linux.

My network interfaces create a bridge and assign the ethernet port to it, as well as a static IP:

auto lo
iface lo inet loopback

auto br0
iface br0 inet static
        bridge_ports eth0
        gateway 192.168.1.1
        address 192.168.1.32
        netmask 255.255.255.0

HostAPd then sets up an access point using the usb wifi adapter, and adds it to the bridge

interface=wlan0
driver=nl80211
ssid=myssid

bridge=br0
channel=6
hw_mode=g
macaddr_acl=0

DNSmasq assigns DHCP ip addresses in the 100-200 range

dhcp-range= 192.168.1.100, 192.168.1.200, 24h

Up to here everything works OK, I can connect to the AP and have full internet access. However I also have full private network access, what I want to achieve is to still have internet access but block internal network access except for DHCP/DNS for which I have tried the following iptables rules:

--append INPUT --protocol tcp -m physdev --physdev-in wlan0 --sport 22 --dst 192.168.1.32 --jump DROP
--append INPUT --protocol tcp -m physdev --physdev-in wlan0 --sport 22 --dst 192.168.1.1 --jump DROP
--append INPUT --protocol all -m physdev --physdev-in wlan0 --dst 192.168.1.32 --jump ACCEPT
--append INPUT --protocol all -m physdev --physdev-in wlan0 --dst 192.168.1.1 --jump ACCEPT
--append INPUT --protocol all -m physdev --physdev-in wlan0 --dst 192.168.1.0 --jump DROP
--append INPUT --protocol all -m physdev --physdev-in wlan0 --dst 0.0.0.0 --jump ACCEPT

I have also tried using IP address ranges

--append INPUT --protocol tcp -m iprange --src-range 192.168.1.100-192.168.1.200 --sport 22 --dst 192.168.1.32 --jump DROP
--append INPUT --protocol tcp -m iprange --src-range 192.168.1.100-192.168.1.200 --sport 22 --dst 192.168.1.1 --jump DROP
--append INPUT --protocol all -m iprange --src-range 192.168.1.100-192.168.1.200 --dst 192.168.1.32 --jump ACCEPT
--append INPUT --protocol all -m iprange --src-range 192.168.1.100-192.168.1.200 --dst 192.168.1.1 --jump ACCEPT
--append INPUT --protocol all -m iprange --src-range 192.168.1.100-192.168.1.200 --dst 192.168.1.0 --jump DROP
--append INPUT --protocol all -m iprange --src-range 192.168.1.100-192.168.1.200 --dst 0.0.0.0 --jump ACCEPT

The idea being I drop ssh, allow all other connections to the gateway and the DNS/DHCP servers, and drop any other internal connections, allowing all other network connections.

But with all of this I still am able to access internal services, so I am kind of stumped now as to how else to proceed

I have enabled br_netfilter and have echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables

Score:1
id flag

I think the thing that's throwing you off here is the bridge interface.

Once you create a bridge interface and bridge 2 ports together, iptables has no way of restricting the traffic going between those ports.

A bridge interface is essentially a layer 2 connection, meaning your wifi hosts on wlan0 are effectively connected to a switch, with all the hosts on your eth0 interface. No routing happens here; the IP packet headers is not even checked -- traffic is forwarded solely based on MAC-layer frame headers.

Iptables would be able to block ssh connections to the pi itself, since as it is the destination it would look at the IP packet headers and thus see that it has a rule to block this type of traffic. It would also be able to block anything trying to leave the network as it is the gateway and has to do routing there. For any traffic that doesn't fall into one of these 2 categories though, it can't do anything.

Some normal home Wi-Fi routers have this feature where you can block Wi-Fi clients from accessing the wired network even though they share the same address range, but I don't know the details of how they implement that.
If it is doable with the setup you have though, I suspect it's some configuration with bridge itself that would be how you get it done, not iptables.

Take a look at this question and see if any of those responses have what you want. I myself am not familiar with ebtables/nftables but it seems like it might be what you're looking for.

RichyHBM avatar
za flag
I'm not set on keeping the bridge if there is a different way you can suggest of doing it? The bridge was just the method used in most of the hostapd tutorials
A. Trevelyan avatar
id flag
The other way would be to just keep them isolated - remove the bridge and have wlan0 & eth0 as separate interfaces in separate networks. eth0 could be 192.168.1.0/24, wlan0 could be 192.168.2.0/24. You would also need to configure 2 DHCP scopes - 1 for each network/interface, but this topology would give iptables authority over what traffic passes between those networks (and to internet), so your rules would actually have an impact. *Actually* - it doesn't look like you're using DHCP for the wired network are you? If it's just for guests then you just do it on the wlan0 interface.
RichyHBM avatar
za flag
I have DHCP enabled on my current network, but everything that I currently connect on to it is using static IP's anyway, so you are right, I could do it that way! Thanks
A. Trevelyan avatar
id flag
No prob, don't forget to accept or upvote the answer if you found it helpful.
A. Trevelyan avatar
id flag
Something I just noticed as well -- I was reading up on nftables to learn what it that was about and after reading, it seems like you were actually on the right track before, it should be able to do exactly what you want. After checking again, it seems you misconfigured your iptables rules - you have `--sport 22` in the 2 DROP rules at the top, but it should be `--dport 22`, that's probably why it wasn't blocking before. If you haven't changed anything significant yet, I'd suggest fixing those 2 rules and seeing if it's working as you want.
RichyHBM avatar
za flag
I had tried that but no luck. I have since managed to have the wlan on a new subnet with dhcp serving that, and set the pi as the router for both networks. My original .1.X still had internet, but the new .2.X didnt, I also couldn't ping beyond the pi's interface when pinging from one subnet to the next. So from a device on the 1.X network I could ping the eth0 and wlan0 of the pi, but not beyond that. So I think for now I'm going to look up more articles about setting up a pi as a full on router
A. Trevelyan avatar
id flag
What does the default route on the pi use as next hop? It might just be that you were missing a static route on your actual internet gateway telling it to use the pi to reach 2.X. Or if the network is more complex than just that, a MASQUERADE rule might have been sufficient.
I sit in a Tesla and translated this thread with Ai:

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.