netfilter ebtables example1
# Howto setup a transparent firewall with ebtables
WARNING: You should be familiar with booting Failsafe mode on your router when using this document. The firewall rules can be tricky, and you can easily lock yourself out.
Background
I work at a university where every computer is connected to the internet with a public IP address. This leaves all computers open to direct attack by hackers/worms on the internet. I have used cheap NAT routers to protect most computers, but I need something a bit smarter to protect my servers.
Why are the servers different?
- The servers must use public IP addresses in order to be accessible to the clients. If I were to use NAT with port forwarding, I would be restricted to one service per port. This is simply not possible with the services we have running, because the cheap NAT routers block all incoming traffic that is not in the NAT table.
- The servers need to have certain ports open for file sharing, printing, etc. But I only want those services available to our local subnet. The cheap NAT routers do not have the ability to port forward packets from the local subnet only.
- The University's 'ISP' restricts each ethernet port to a single MAC address, very much the same way a wireless AP restricts each associated client to a single MAC address. This means that not only do I need a transparent firewall, but I need IP layer bridging and MAC layer NAT.
Network Topology
System Variables
Make sure you have the following two lines in your /etc/sysctl.conf
net.bridge.bridge-nf-call-iptables=1 net.bridge.bridge-nf-filter-vlan-tagged=1 |
layer2 firewall
#!/bin/sh IFCONFIG=/sbin/ifconfig BRCTL=/usr/sbin/brctl EBTABLES=/usr/sbin/ebtables LAN_IF=$(nvram get lan_ifname) LAN_IP=$(nvram get lan_ipaddr) LAN_MASK=$(nvram get lan_netmask) LAN_MAC=$($IFCONFIG $LAN_IF | \ /bin/grep "HWaddr" | \ /bin/sed 's/.*HWaddr \(.*\)/\1/g') WAN_IF=$(nvram get wan_ifname) WAN_IP=$(nvram get wan_ipaddr) WAN_MAC=$($IFCONFIG $WAN_IF | \ /bin/grep "HWaddr" | \ /bin/sed 's/.*HWaddr \(.*\)/\1/g') WAN_GW=$(nvram get wan_gateway) BR_IF=br0 BR_STP=off # Required kernel modules # Choose relocatable ebtables-modules and # dont turn off possible error messages! /sbin/insmod /lib/modules/2.4.30/ebtables /sbin/insmod /lib/modules/2.4.30/ebtable_broute /sbin/insmod /lib/modules/2.4.30/ebtable_filter /sbin/insmod /lib/modules/2.4.30/ebtable_nat /sbin/insmod /lib/modules/2.4.30/ebt_ip /sbin/insmod /lib/modules/2.4.30/ebt_snat # =================================================== # ORDER IS CRITICAL IN BRIDGE SETUP, DONT MUCK IT UP! # =================================================== $IFCONFIG $BR_IF > /dev/null 2> /dev/null if [ $? != 0 ]; then echo "Creating bridge interface:" echo " Creating bridge..." $BRCTL addbr $BR_IF $BRCTL stp $BR_IF $BR_STP echo " Adding WAN interface..." $IFCONFIG $WAN_IF inet 0.0.0.0 $BRCTL addif $BR_IF $WAN_IF echo " Adding LAN interface..." $IFCONFIG $LAN_IF down hw ether $WAN_MAC $IFCONFIG $LAN_IF inet 0.0.0.0 $BRCTL addif $BR_IF $LAN_IF echo " Configuring Bridge interface..." $IFCONFIG $BR_IF inet 0.0.0.0 up echo " Configuring WAN outside interface..." $IFCONFIG $WAN_IF inet $WAN_IP netmask $WAN_MASK echo " Configuring WAN inside interface..." $IFCONFIG $LAN_IF inet $WAN_IP netmask $WAN_MASK echo " Configuring LAN interface..." $IFCONFIG $LAN_IF:0 inet $LAN_IP netmask $LAN_MASK echo " Adding default route..." /sbin/route add default gw $WAN_GW dev $WAN_IF else echo "Bridge already configured." fi echo "Configuring bridge firewall..." for T in filter nat broute; do $EBTABLES -t $T -F $EBTABLES -t $T -X done # force ARP requests/replies and IP traffic to be routed on layer3 $EBTABLES -t broute -A BROUTING -p 0x0806 -j DROP # Route LAN DHCP requests $EBTABLES -t broute -A BROUTING -p 0x0800 -i $LAN_IF --ip-protocol 17 \ --ip-source-port 67:68 --ip-destination-port 67:68 -j DROP # Route LAN packets $EBTABLES -t broute -A BROUTING -p 0x0800 -i $LAN_IF \ --ip-source $LAN_IP/$LAN_MASK -j DROP # Route IP traffic sourced outside the LAN subnet (blocked later) $EBTABLES -t filter -A FORWARD -i $WAN_IF \ -p 0x0800 --ip-src ! $WAN_IP/$WAN_MASK -j DROP # Defined accept rule for accounting purposes $EBTABLES -t filter -A FORWARD -j ACCEPT # force all outgoing packets to have router's MAC address $EBTABLES -t nat -A POSTROUTING -o $WAN_IF -j snat --to-source $WAN_MAC
layer3 firewall
#!/bin/sh echo "Configuring layer3 firewall..." IFCONFIG=/sbin/ifconfig BRCTL=/usr/sbin/brctl IPTABLES=/usr/sbin/iptables LAN_IF=$(nvram get lan_ifname) LAN_IP=$(nvram get lan_ipaddr) LAN_MASK=$(nvram get lan_netmask) WAN_IF=$(nvram get wan_ifname) WAN_IP=$(nvram get wan_ipaddr) WAN_MASK=$(nvram get wan_netmask) BR_IF=br0 BR_STP=off # Required kernel modules /sbin/insmod ipt_recent.o 2> /dev/null /sbin/insmod ipt_ttl.o 2> /dev/null /sbin/insmod ipt_TTL.o 2> /dev/null for T in filter nat mangle; do iptables -t $T -F iptables -t $T -X done echo " Configuring INPUT chain..." # accept dhcp packets first, they dont have source IP yet iptables -A INPUT -i $LAN_IF -p UDP --sport 68 --dport 67 -j ACCEPT # stateful packets allowed iptables -A INPUT -m state --state INVALID -j DROP iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT # allow packets from the private NAT LAN iptables -A INPUT -i ppp+ -s $LAN_IP/$LAN_MASK -j ACCEPT iptables -A INPUT -i $LAN_IF -s $LAN_IP/$LAN_MASK -j ACCEPT # allow packets from loopback iptables -A INPUT -i lo -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT # Connections allowed to firewall from WAN # ICMP iptables -A INPUT -p ICMP -j ACCEPT # allow IP packets from the WAN iptables -A INPUT -s $WAN_IP/$WAN_MASK -j ACCEPT # SSH iptables -A INPUT -p TCP --dport 22 \ -m recent --name ROUTER-SSH --update --hitcount 5 --seconds 180 -j DROP iptables -A INPUT -p TCP --dport 22 \ -m recent --name ROUTER-SSH --set -j ACCEPT # PPTP iptables -A INPUT -p TCP --dport 1723 \ -m recent --name ROUTER-PPTP --update --hitcount 5 --seconds 180 -j DROP iptables -A INPUT -p TCP --dport 1723 \ -m recent --name ROUTER-PPTP --set -j ACCEPT iptables -A INPUT -d $LAN_IP -p 47 -j ACCEPT # FTP iptables -A INPUT -p TCP --dport 21 \ -m recent --name ROUTER-FTP --update --hitcount 5 --seconds 180 -j DROP iptables -A INPUT -p TCP --dport 21 \ -m recent --name ROUTER-FTP --set -j ACCEPT # Deny the rest iptables -A INPUT -j DROP echo " Configuring OUTPUT table..." iptables -A OUTPUT -o $WAN_IF -p ICMP --icmp-type 0 -j ACCEPT iptables -A OUTPUT -o $WAN_IF -p ICMP --icmp-type 8 -j ACCEPT iptables -A OUTPUT -o $WAN_IF -p ICMP -j DROP echo " Configuring NAT table..." # apply NAT to local packets headed to the WAN iptables -t nat -A POSTROUTING -o $WAN_IF -s $LAN_IP/$LAN_MASK -j MASQUERADE iptables -t nat -A POSTROUTING -o $LAN_IF -s $LAN_IP/$LAN_MASK -j MASQUERADE iptables -A PREROUTING -t mangle -d ! $LAN_IP -j TTL --ttl-inc 1 echo " Configuring FORWARD chain..." # statefull packets allowed iptables -A FORWARD -m state --state INVALID -j DROP iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT # allow IP packets from the LAN to the LAN iptables -A FORWARD -s $WAN_IP/$WAN_MASK -d $WAN_IP/$WAN_MASK -j ACCEPT # allow LAN and PPP connections to LAN iptables -A FORWARD -i ppp+ -o $LAN_IF -j ACCEPT iptables -A FORWARD -i $LAN_IF -o $LAN_IF -j ACCEPT # allow outbound connections iptables -A FORWARD -i ppp+ -o $WAN_IF -j ACCEPT iptables -A FORWARD -i $LAN_IF -o $WAN_IF -j ACCEPT iptables -A FORWARD -i $BR_IF -o $WAN_IF -s $LAN_IP/$LAN_MASK -j ACCEPT # Deny the rest iptables -A FORWARD -j DROP
Performance
Before implementing this your own, here are some performance results based on a WRT54GL using OpenWrt 0.9. Task was to transfer a file through the bridge. The server providing the file was right behind the bridge-device. The test ran in two variants with netfilter-ebtables-modules turned on/off (via rmmod).
- Download-Speed without ebtables (just plain bridge): 8,5 MB/s.
- By turning ebtables on via "insmod…" rate drops down to 3,45 MB/s.
Although the maximum speed depends on hardware, it is expectable that the loss-rate of around 50% is scalable/proportional to the maximum speed.
doc/howto/netfilter/netfilter.ebtables.example1.txt · Last modified: 2011/02/24 17:27 by orca
