Ebtables

From AAISP Support Site

Firewalling with Ethernet Tables

On AAISP I have decided to run a NAT-free home network, but some recent additions to the network need both internet access to function at the same time as any IPv4 address that can access them to control them.

In addition to all that, I assigned v4 addresses dynamically to conserve the address space. This means that IPtables rules to control inward access on their own would not do, so I am using ebtables to control access.

I have an external interface ppp0 (towards AAISP) and an internal interface eth0.20 which is in fact a VLAN on eth0.

To use ebtables, the internal interface must be enslaved to an ethernet bridge

I didn’t need Spanning Tree unless the bridge is part of a loop, which it could not be with only the one ethernet interface attached. If more than one interface is used, then STP may be needed.

/etc/network/interfaces

Valid if eth0.20 used IEEE's example of AC-DE-48-23-45-67

iface int0 inet static
 # configure IP addresses here
 address 192.0.2.0
 netmask 255.255.255.0
 up /sbin/ifconfig int0 del fe80::aede:48ff:fe23:4567/64
 up /sbin/ifconfig int0 add fe80::aede:48ff:fe23:4567/64
 up /sbin/ifconfig int0 add 2001:db8:cafe:1:aede:48ff:fe23:4567/64
 bridge_ports eth0.20
 bridge_stp off
 bridge_ageing 0
 bridge_bridgeprio 34000
 bridge_fd 0
 bridge_gcint 0
 bridge_hello 0
 bridge_maxage 0
 bridge_maxwait 0

It is also possible to do this directly with brctl if you run a GNU/Linux system that has not got /etc/network/interfaces

I had also disabled the callout of iptables from within ebtables via sysctl at this point. The feature seems to be broken in Linux 2.6.32-5-amd64 causing IPv6’s address resolution to break amongst other things. IP6tables is still working independently.

In /etc/sysctl.conf

net.bridge.bridge-nf-call-arptables=0 net.bridge.bridge-nf-call-ip6tables=0 net.bridge.bridge-nf-call-iptables=0

Ebtables and IPtables rules

I use the netfilter mark to communicate between ebtables and iptables that has 32 bits to use and each can be independently set. The 2 type of device I want to filter are Freesat boxes, which want to access BBC iPlayer, and Sonos which will access radio stations via Tunein/Radiotime, so I am using 3 of my bits for now, as I also do MAC address based accounting.

MINET=$'0x4'
MSONOS=$'0x1'
MFREESAT=$'0x2'

The flag is set on outgoing frames from the devices by ebtables to say they want to access a particular IP address. IPtables then remembers that destination address for the packet in a recents list.

For incoming packets, netfilter flags are set on all packets unless they are from an IP address that has been approved in the corresponding recents list. When the packets are converted to frames and reach ebtables, they are DROPPED unless the netfilter flag of the device is cleared. I would have liked to REJECT instead but ebtables does not offer that.

# first let’s do some accounting.
# These rules need only match, not do anything, as we are interested in the Ebtables counters.
ebtables -N accounting -P RETURN
ebtables -A accounting --destination AC:DE:48:23:45:67/ff:ff:ff:ff:ff:ff
ebtables -A accounting --destination AC:DE:48:23:45:67/ff:ff:ff:ff:ff:ff
ebtables -A OUTPUT -o eth0.20 -p 0x0800 --mark $MINET/$MINET -j accounting
ebtables -A OUTPUT -o eth0.20 -p 0x86DD --mark $MINET/$MINET -j accounting

# freesat devices.
ebtables -A INPUT -i eth0.20 --source 00:03:78:00:00:00/ff:ff:ff:00:00:00 -p 0x0800 -j mark --mark-or $MFREESAT --mark-target CONTINUE
ebtables -A INPUT -i eth0.20 --source 00:06:f4:00:00:00/ff:ff:ff:00:00:00 -p 0x0800 -j mark --mark-or $MFREESAT --mark-target CONTINUE
iptables -A FORWARD -i int0 -o ppp0 -m mark --mark $MFREESAT/$MFREESAT -m recent --rdest --set --name freesat
iptables -A FORWARD -i ppp0 -o int0 -m recent --rsource ! --update --name freesat -j MARK --or-mark $MFREESAT 
ebtables -A OUTPUT -o eth0.20 --destination 00:03:78:00:00:00/ff:ff:ff:00:00:00 -p 0x0800 --mark /$MFREESAT -j DROP 
ebtables -A OUTPUT -o eth0.20 --destination 00:06:f4:00:00:00/ff:ff:ff:00:00:00 -p 0x0800 --mark /$MFREESAT -j DROP

# sonos devices.
ebtables -A INPUT -i eth0.20 --source 00:0e:58:00:00:00/ff:ff:ff:00:00:00 -p 0x0800 -j mark --mark-or $MSONOS --mark-target CONTINUE
iptables -A FORWARD -i int0 -o ppp0 -m mark --mark $MSONOS/$MSONOS -m recent --rdest --set --name sonos
iptables -A FORWARD -i ppp0 -o int0 -m recent --rsource ! --update --name sonos -j MARK --or-mark $MSONOS
ebtables -A OUTPUT -o eth0.20 --destination 00:0e:58:00:00:00/ff:ff:ff:00:00:00 -p 0x0800 --mark $MSONOS/$MSONOS -j DROP

# mark incoming data so that we can account it.
iptables -A FORWARD -i ppp0     -o int0     -j MARK --or-mark $MINET