iptables -I INPUT -s 180.178.99.69 -j DROP
This script configures netfilter for use in a router/firewall.
At first, I set some variables to make the rest of the script more readable and more flexible:
#!/bin/sh LanPrefix=192.168.0 # This script is using an IP-address scheme like 192.168.0.x LANif=eth0 # this interface serves the local network WANif=eth1 # this interface connects to the cable modem
The modprobe commands load additional extensions for netfilter:
modprobe ip_tables modprobe iptable_filter #modprobe ip_conntrack #modprobe ip_conntrack_ftp modprobe ipt_state modprobe iptable_nat modprobe ip_nat_ftp modprobe ipt_MASQUERADE #modprobe ipt_LOG #modprobe ipt_REJECT modprobe xt_TCPMSS modprobe ipt_recent
After the kernel modules have been inserted, we need to activate a few things:
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts # Enable broadcast echo Protection echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route # Disable Source Routed Packets #not installed yet! echo 1 > /proc/sys/net/ipv4/tcp_syncookies # Enable TCP SYN Cookie Protection echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects # Disable ICMP Redirect Acceptance echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects # Don't send Redirect Messages echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter # Drop Spoofed Packets coming in on an # interface where responses would result # in the reply going out a different IF echo 1 > /proc/sys/net/ipv4/conf/all/log_martians # Log packets with impossible addresses echo 2 > /proc/sys/net/ipv4/ip_dynaddr # Be verbose on dynamic ip-addresses # not needed with static ip echo 0 > /proc/sys/net/ipv4/tcp_ecn # Disable Explicit Congestion Notification # Too many routers are still ignorant
Before declaring the actual firewall rules, it is a good idea to create a known state. I want the firewall to reject everything, except I allowed it explicitly:
# Clear everything iptables -F # flush (delete all rules) iptables -X # delete user-defined chains iptables -Z # reset packet and byte counters in all chains to zero iptables -t nat -F # delete and zero above doesn't apply to nat # Set initial state iptables -P INPUT DROP iptables -P FORWARD DROP # default = drop every packet iptables -P OUTPUT DROP
After the firewall is set to "paranoid", we need to allow things, we want to use. This is mostly about servers (services) on the router box itself, as also about port forwards to services on computers behind the firewall. This example shows rules for VNC (a remote desktop server), the Torrent client "Transmission" (which wants to be "available" to the net for getting better download rates) and the game "Armagetron", which might start a service ("host a game"):
# Port forwards to LAN iptables -t nat -A PREROUTING -p tcp --dport 5900 -j DNAT --to $LanPrefix.1:5900 # VNC iptables -A FORWARD -p tcp --dport 5900 -j ACCEPT iptables -t nat -A PREROUTING -p tcp --dport 5800 -j DNAT --to $LanPrefix.1:5800 # VNC-http iptables -A FORWARD -p tcp --dport 5800 -j ACCEPT iptables -t nat -A PREROUTING -p tcp --dport 51413 -j DNAT --to $LanPrefix.1:51413 # Transmission Torrent iptables -A FORWARD -p tcp --dport 51413 -j ACCEPT iptables -t nat -A PREROUTING -p udp --dport 4534 -j DNAT --to $LanPrefix.1:4534 # Armagetron iptables -A FORWARD -p udp --dport 4534 -j ACCEPT
Connections to localhost are internal connections (router accesses "itself"), so we can safely allow all of them. Computers in our LAN are also allowed to connect to any service, that might be running on the router/firewall box:
iptables -A INPUT -i lo -j ACCEPT # Allow any from/to local host iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i $LANif -j ACCEPT # Allow any from/to LAN iptables -A OUTPUT -o $LANif -j ACCEPT
Connections from the router to services on the internet are allowed without restrictions:
iptables -A OUTPUT -o $WANif -j ACCEPT # Allow all outgoing to WAN iptables -A INPUT -i $WANif -m state --state ESTABLISHED,RELATED -j ACCEPT # Allow incoming from WAN, if already established
SSHport=22 # against SSH Brute-Force iptables -A INPUT -i $WANif -p tcp --dport $SSHport -m state --state NEW -m recent --set --name SSH ## Eintrag im syslog iptables -A INPUT -i ppp+ -p tcp --dport 22 -m recent --update --seconds 60 --hitcount 4 --name SSH -j LOG --log-prefix "SSH_brute_force " iptables -A INPUT -i $WANif -p tcp --dport $SSHport -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP iptables -A INPUT -i $WANif -p tcp --dport $SSHport -j ACCEPT # Open SSH to WAN iptables -A INPUT -i $WANif -p tcp --dport 80 -j ACCEPT # Open HTTP to WAN iptables -A INPUT -i $WANif -p icmp -j ACCEPT # Let us be pinged iptables -A FORWARD -i ! $WANif -m state --state NEW -j ACCEPT # Forward initializations not from WAN iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # Forward all already established connections
If you are using a DSL Modem with PPPoE (That is "PPP over Ethernet" - the modem is connected to the router with a RJ45 Network-Cable), we need to shrink the Ethernet packet size by 8 bytes (which are needed for the additional layer), because certain servers out there are too silly to enable certain ICMP methods (sic?) for automatic adjustments. Yes, paranoia can be exaggerated.
#iptables -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu # Adjust MTU for PPPoE
Finally, we start the forwarding:
iptables -t nat -A POSTROUTING -o $WANif -j MASQUERADE # guess what # Log everything for debugging (last of all rules, but before policy rules) #iptables -A INPUT -j LOG --log-prefix "FIREWALL:INPUT " #iptables -A FORWARD -j LOG --log-prefix "FIREWALL:FORWARD" #iptables -A OUTPUT -j LOG --log-prefix "FIREWALL:OUTPUT " echo 1 > /proc/sys/net/ipv4/ip_forward # Finally, enable IP Forwarding