This simple firewall achieves the following:
- Drops all layer-2 ARP traffic from being forwarded between bridged clients (WiFi)
- Security: Prevents ARP cache poisoning attacks between clients only
- Note: This breaks the ability for clients to learn about each others addresses to talk to each other
- Trick: Clients could still talk to each other by setting static ARP entries to the MAC of the router with each others IP addresses
- Router loops through the DHCP lease table and sets a static ARP entry for each IP / MAC combo found for every client
- Security: Prevents ARP cache poisoning attacks coming from a client into the router
- Note: This does not prevent attackers with Rogue DHCP servers from answering other clients first
- Drops all layer-3 UDP-DHCP traffic from being broadcasted between clients (WiFi)
- Security: Prevents rogue DHCP server traffic from being sent between clients
- General firewalling rules
- Allows specific inbound traffic only: lo/dhcp/ssh/related/established – drops all else
- Allow a Destination-NAT port forwarding to a given server IP/Port
- Allow a Source-NAT for clients of the router to get out
- Note: Does not prevent DHCP starvation DoS attacks
- Routing rules to direct traffic to the main VLANs
- 192.168.0.0/18 is used for the local DHCP VLSM
- 192.168.96.0/19 -> 192.168.64.2/24 (Part of the 192.168.64.0/18 VLSM)
- 192.168.160.0/19 -> 192.168.128.2/24 (Part of the 192.168.128.0/18 VLSM)
- 192.168.192.0/18 is a free VLSM block
LAN="br-lan"
WAN="eth0.2"
SRV="192.168.161.2:22"
ROU="192.168.96.0/19:192.168.64.2 192.168.160.0/19:192.168.128.2"
C=`/usr/sbin/ebtables -L FORWARD | grep -i '.p ARP.*.j DROP'`
if [ "$C" == "" ] ; then
echo "Setting ebtables"
/usr/sbin/ebtables -F
for INTF in -i -o ; do
/usr/sbin/ebtables -A FORWARD "$INTF" "$LAN" -p ARP -j DROP
for PORT in 67 68 ; do
for TYPE in sport dport ; do
/usr/sbin/ebtables -A FORWARD "$INTF" "$LAN" -p ip --ip-protocol udp --ip-"$TYPE" "$PORT" -j DROP
done
done
done
fi
while read E ; do
M=`echo "$E" | awk '{ print $2 }'`
I=`echo "$E" | awk '{ print $3 }'`
/usr/sbin/ip neighbor change "$I" lladdr "$M" dev "$LAN" nud permanent
done < /tmp/dhcp.leases
C=`/usr/sbin/iptables -nvL | grep -i '^chain' | tail -n +4`
if [ "$C" != "" ] ; then
echo "Setting iptables"
/usr/sbin/iptables -F ; /usr/sbin/iptables -X
/usr/sbin/iptables -t nat -F ; /usr/sbin/iptables -t nat -X
/usr/sbin/iptables -t mangle -F ; /usr/sbin/iptables -t mangle -X
/usr/sbin/iptables -t raw -F ; /usr/sbin/iptables -t raw -X
/usr/sbin/iptables -P INPUT ACCEPT
/usr/sbin/iptables -A INPUT -i lo -j ACCEPT
/usr/sbin/iptables -A INPUT -p udp --dport 67 -j ACCEPT
/usr/sbin/iptables -A INPUT -p tcp --dport 22 -j ACCEPT
/usr/sbin/iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
/usr/sbin/iptables -A INPUT -j DROP
/usr/sbin/iptables -P FORWARD ACCEPT
/usr/sbin/iptables -P OUTPUT ACCEPT
if [ "$WAN" != "" ] ; then
if [ "$SRV" != "" ] ; then
/usr/sbin/iptables -t nat -A PREROUTING -i "$WAN" -p tcp --dport 443 -j DNAT --to "$SRV"
fi
/usr/sbin/iptables -t nat -A POSTROUTING -o "$WAN" -j MASQUERADE
fi
fi
for ROUTE in $ROU ; do
SRC=`echo "$ROUTE" | awk -F':' '{ print $1 }'`
DST=`echo "$ROUTE" | awk -F':' '{ print $2 }'`
C=`/usr/sbin/ip route | grep -i "$SRC"`
if [ "$C" == "" ] ; then
echo "Adding route [$SRC] -> [$DST]"
/usr/sbin/ip route add "$SRC" via "$DST"
fi
done
2 thoughts on “A Simple Server/Router Firewall”