How to block devices connecting to a specific wireless interface from accessing the internet?

Solution 1:

OpenWRT is running a Linux kernel, but as an embedded system, some features might not be available, so I can't know if this answer, intended to work on a Linux system with a configuration similar to OP will work on it. This requires:

  • ebtables: available

and depending on the chosen solution this might also require some of:

  • filtering IPv4 with ebtables
  • setting marks with ebtables
  • checking marks with ebtables

In the end the system is routing packets from the br-lan interface to the br-wan interface. At this step the fact that a frame entered the br-lan interface using the wlan0-1 interface bridge port was lost once the frame left the initial bridge to have its payload: IPv4, routed. So the initial action must happen before this information is lost: in the bridge path when the frame is still in the br-lan bridge.

Documentation might hint (bridge is mentioned) it's possible to handle bridge firewalling with OpenWRT's firewall application, but I don't have any knowledge about this part. So I'll use directly ebtables.

If one can rely on knowing the IP LAN topology on br-lan (192.168.1.0/24) then this can all be done simply in one single ebtables rule:

ebtables -A INPUT -p IPv4 -i wlan0-1 --ip-dst ! 192.168.1.0/24 -j DROP

which drops any IPv4 frame received from the wlan0-1 bridge port and bridged to the host (possibly for it or for further routing) that doesn't have a destination IP address within 192.168.1.0/24.

One could optionally insert before an exception for OpenWRT's public IP address if it's static and known in advance (eg: 192.0.2.2):

ebtables -I INPUT -p IPv4 -i wlan0-1 --ip-dst 192.0.2.2 -j ACCEPT

If this is fine, no need to use the following alternative.


Else if the rule has to stay generic without also involving the LAN IP addresses but only the interfaces (or needs to accept as destination the WAN IP address without knowing its value), routing has to be involved and I suggest to mark the frame using ebtables in the bridge path where the information is available, right before the frame's payload (IPv4) is about to be routed, and then drop later the marked packet/frame once it's certain it was routed toward Internet. The mark is preserved when decapsulating frames or encapsulating packets. OP's current iptables rules don't use any mark so chances are there won't be unfortunate interactions.

As in OP's case the egress interface used for routing is also a bridge (br-wan), to limit interactions with the higher level tool (firewall3) managing the firewall with iptables, one can drop the marked frame in the bridge path instead of dropping the marked packet in the routing path: no interaction with iptables rules.

Flow from LAN to Internet is as follow:

                                            πŸ „β”€β”€β”€β”€β”€ eth0.1 πŸ „β”€β”€β”€β”€β”€β”€β”€ good
bad  β”€β”€β”€β”€β”€β”€πŸ † wlan0-1 β”€β”€β”€β”€β”€β”€πŸ † br-lan bridge πŸ „β”€β”€β”€β”€β”€β”€ wlan0 πŸ „β”€β”€β”€β”€β”€β”€β”€ good
                                 β”‚
                                 β”‚
                      Ethernet frame INPUT  (ebtables firewall here)
frame marked when from wlan0-1   M
                                 β”‚ 
                                 πŸ ‡
                               br-lan      frame is decapsulated to
                           self interface  IPv4. Mark is preserved
                                 β”‚
                                 β”‚
                         IPv4 packet routing (iptables firewall here)
                                 β”‚
                                 β”‚
                                 πŸ ‡ 
                               br-wan      packet is encapsulated in
                           self interface  Ethernet. Mark is preserved
                                 β”‚
                                 β”‚
                      Ethernet frame OUTPUT (ebtables firewall here)
      frame dropped if marked    X
                                 β”‚
                                 πŸ ‡
                           br-wan bridge β”€β”€β”€β”€β”€β”€πŸ † eth0.2 β”€β”€β”€β”€β”€β”€πŸ † Internet

This will mark frames received from the wlan0-1 bridge port:

ebtables -A INPUT -i wlan0-1 -j mark --mark-set 0xbad

Then this will match and drop when emitting from host through the br-wan bridge a frame/packet previously marked:

ebtables -A OUTPUT --logical-out br-wan --mark 0xbad -j DROP

If --logical-out is not available for some reason, with the current topology it can be changed into br-wan's single output bridge port:

ebtables -A OUTPUT -o eth0.2 --mark 0xbad -j DROP

In this case as the packet is seen entering and leaving the routing stack, conntrack will create an entry for it even if it will dropped just after. Such entry will never reach the ESTABLISHED state since nothing will receive this packet and reply (see also notes).


Notes:

  • if OpenWRT was configured to have two distinct LANs (not bridged or on separate bridges each participating in routing), one for wlan0 and eth0.1 and another one for wlan0-1 with distinct IP addresses on them, then standard routing would apply everywhere and this problem could be solved easily all in iptables probably with configuration in firewall3 and with ebtables not needed.

  • current iptables rules suggest eth0.2 could be used (or used to be used) as a standard (non bridge-port) interface. If such was the case, the second solution would have to be changed and involve an equivalent rule in iptables which should be integrated in firewall3 if possible. It's also possible to use it for br-wan (but again is worth it only if integration with firewall3 is possible):

    This rule can currently work instead of the ebtables OUTPUT rule above:

    iptables -I FORWARD -o br-wan -m mark --mark 0xbad -j DROP
    

    and with eth0.2 directly a routing interface instead of a bridge port:

    iptables -I FORWARD -o eth0.2 -m mark --mark 0xbad -j DROP
    

    Both could be put at the same time, as it appears is currently done in other iptables rules with br-wan and eth0.2.

    Here since the packet is dropped in the routing path with iptables, the conntrack entry won't be committed and will not appear (eg: cat /proc/net/nf_conntrack won't show the attempt).

  • Using iptables in the bridge path by relying on br_netfilter features is usually a bad idea when not having total control of the configuration, and is disabled by default in OpenWRT. So iptables' physdev match which depends on this feature should not be used (and is probably not available) to solve this problem.

  • As this isn't stateful, incoming traffic from Internet to a system using wlan0-1 will still be allowed, but no reply will be possible. Anyway as the LAN is private this would require DNAT rules on the firewall to have this possibility (or for the 2nd solution where conntrack entries are still created, a remote 3rd party blindly synchronized to dropped attempts). It's possible to also drop the opposite direction: Internet traffic to wlan0-1 using the same methods as presented, if really needed.