Firewalls
For a brief introduction see Filtering Firewalls in Linux.ppt
If you are using Ubuntu, you should look at the ubuntul Iptables Howto. Take special note of the iptables-apply script that you should use to test your connection.
This page includes firewall examples that were used on an actual (although now non-existent) network. It successfully protected some 16 static IPs for six years. At one time I recorded a 3-way coordinated attack from university networks in Italy, France and Germany. Through all this time, the bridging firewall was used successfully to protect a small business with several computers. The script that follows is final form.
Bridge Setup
# /etc/rc.d/init.d/bridge # return=$rc_done case "$1" in start) echo "Starting service bridge br0" ifconfig eth0 0.0.0.0 promisc ifconfig eth1 0.0.0.0 promisc brctl addbr br0 || return=$rc_failed brctl addif br0 eth0 || return=$rc_failed brctl addif br0 eth1 || return=$rc_failed brctl sethello br0 1 || return=$rc_failed brctl setmaxage br0 4 || return=$rc_failed brctl setfd br0 4 || return=$rc_failed ifconfig br0 promisc up 209.50.17.211 netmask 255.255.255.240 broadcast 209.50.17.223 || return=$rc_failed route add default gw 209.50.17.209 echo -e "$return" ;; stop) echo "Shutting down service bridge br0" ifconfig br0 down || return=$rc_failed brctl delif br0 eth0 || return=$rc_failed brctl delif br0 eth1 || return=$rc_failed brctl delbr br0 || return=$rc_failed ifconfig eth0 down || return=$rc_failed ifconfig eth1 down || return=$rc_failed route del default echo -e "$return" ;; status) ifconfig br0 brctl show br0 ;; restart) $0 stop && $0 start || return=$rc_failed ;; *) echo "Usage: $0 {start|stop|status|restart}" exit 1 esac test "$return" = "$rc_done" || exit 1 exit 0
Firewall Setup
# /etc/init.d/firewall # return=$rc_done case "$1" in start) ############################################################################### #SETUP INFORMATION INTERNET="eth0" DMZ="eth1" LOOPBACK_INTERFACE="lo" CONNECTION_TRACKING="1" ICMP_STRICT="1" L2TP="0" INET_SSH="0" BRAIN="209.50.17.210" BRAIN2="209.50.17.212" CISCO="209.50.17.209" YAKKO="209.50.17.215" CSE="129.93.165.2" TIMESERVER1="132.163.4.101" TIMESERVER2="132.163.4.102" TIMESERVER3="132.163.4.103" DMZ_NETWORK="209.50.17.213-222" SUBNET_BROADCAST="209.50.17.223" SUBNET_NETWORK="209.50.17.208" LOOPBACK="127.0.0.0/8" CLASS_A="10.0.0.0/8" CLASS_B="172.16.0.0/12" CLASS_C="192.168.0.0/16" CLASS_D_MULTICAST="224.0.0.0/4" CLASS_E_RESERVED_NET="240.0.0.0/5" BROADCAST_SRC="0.0.0.0" BROADCAST_DEST="255.255.255.255" PRIVPORTS="0:1023" UNPRIVPORTS="1024:65535" ############################################################################### # in /proc/sys/net/ipv4 protections available # Enable broadcast echo Protection echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts # Disable Source Routed Packets for f in /proc/sys/net/ipv4/conf/*/accept_source_route; do echo 0 > $f done # Enable TCP SYN Cookie Protection echo 1 > /proc/sys/net/ipv4/tcp_syncookies # Disable ICMP Redirect Acceptance for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do echo 0 > $f done # Don't Send Redirect Messages for f in /proc/sys/net/ipv4/conf/*/send_redirects; do echo 0 > $f done # Drop Spoofed Packets coming in on an interface, which if replied to, # would result in the reply going out a different interface. for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f done # Log packets with impossible addresses. (Do we really want to do this?) #for f in /proc/sys/net/ipv4/conf/*/log_martians; do # echo 1 > $f #done ############################################################################### #FLUSH EVERYTHING AND DELETE CHAINS echo "Flushing all rules and chains ..." /sbin/iptables -F /sbin/iptables -t nat -F /sbin/iptables -t mangle -F /sbin/iptables --delete-chain /sbin/iptables -t nat --delete-chain /sbin/iptables -t mangle --delete-chain #DEFAULT POLICIES #default filter policy /sbin/iptables --policy INPUT DROP /sbin/iptables --policy OUTPUT DROP /sbin/iptables --policy FORWARD DROP #default nat policy /sbin/iptables -t nat --policy PREROUTING ACCEPT /sbin/iptables -t nat --policy OUTPUT ACCEPT /sbin/iptables -t nat --policy POSTROUTING ACCEPT #default mangle policy /sbin/iptables -t mangle --policy PREROUTING ACCEPT /sbin/iptables -t mangle --policy OUTPUT ACCEPT #Allow loopback /sbin/iptables -A INPUT -m physdev --physdev-in lo -j ACCEPT /sbin/iptables -A OUTPUT -m physdev --physdev-out lo -j ACCEPT ############################################################################### #CREATE VALIDATION CHAINS iptables -N TCP-STF iptables -N CON-TRK iptables -N SRC-CHK iptables -N FWL-OUT #CREATE TRAFFIC CHAINS iptables -N INET-SVRS iptables -N SVRS-INET #CREATE ICMP CHAINS iptables -N passicmp ############################################################################### echo "Creating firewall rules..." #INSERT A PACKET INTO THE APPROPRIATE CHAIN ## Allow SSH to DMZ /sbin/iptables -A INPUT -m physdev --physdev-in $DMZ -p tcp --destination-port 22 -j ACCEPT /sbin/iptables -A INPUT -m physdev --physdev-in $DMZ -p udp --destination-port 22 -j ACCEPT if [ $INET_SSH = 1 ] ; then /sbin/iptables -A INPUT -m physdev --physdev-in $INTERNET -p tcp --destination-port 22 -j ACCEPT /sbin/iptables -A INPUT -m physdev --physdev-in $INTERNET -p udp --destination-port 22 -j ACCEPT fi /sbin/iptables -A INPUT -d $SUBNET_BROADCAST -j DROP /sbin/iptables -A INPUT -p icmp -j passicmp /sbin/iptables -A INPUT -j TCP-STF /sbin/iptables -A INPUT -j CON-TRK /sbin/iptables -A INPUT -j SRC-CHK #/sbin/iptables -A INPUT -p tcp --destination-port 22 -j ACCEPT ################################################################################ # On 9/28/03 we denied these idiots who are just hammering our site! /sbin/iptables -A INPUT -s 216.39.48.0/24 -j DROP /sbin/iptables -A FORWARD -s 216.39.48.0/24 -j DROP /sbin/iptables -A FORWARD -s 68.116.156.85 -j DROP /sbin/iptables -A FORWARD -s 213.37.82.0/24 -j DROP /sbin/iptables -A FORWARD -s 63.107.252.0/24 -p tcp --destination-port 25 -j DROP /sbin/iptables -A FORWARD -s 63.107.252.0/24 -p udp --destination-port 25 -j DROP /sbin/iptables -A FORWARD -s 65.212.41.0/24 -p tcp --destination-port 25 -j DROP /sbin/iptables -A FORWARD -s 65.212.41.0/24 -p udp --destination-port 25 -j DROP /sbin/iptables -A FORWARD -s 65.186.8.0/24 -j DROP # ################################################################################ /sbin/iptables -A FORWARD -p icmp -j passicmp /sbin/iptables -A FORWARD -j TCP-STF /sbin/iptables -A FORWARD -j CON-TRK /sbin/iptables -A FORWARD -j SRC-CHK /sbin/iptables -A FORWARD -m physdev --physdev-in $INTERNET --physdev-out $DMZ -j INET-SVRS /sbin/iptables -A FORWARD -m physdev --physdev-in $DMZ --physdev-out $INTERNET -j SVRS-INET # Allow the firewall to talk to the DMZ /sbin/iptables -A OUTPUT -m physdev --physdev-out $DMZ -j ACCEPT # Otherwise do the normal check /sbin/iptables -A OUTPUT -p icmp -j passicmp /sbin/iptables -A OUTPUT -j TCP-STF /sbin/iptables -A OUTPUT -j CON-TRK /sbin/iptables -A OUTPUT -j SRC-CHK /sbin/iptables -A OUTPUT -m physdev --physdev-out $INTERNET -j FWL-OUT ############################################################################## # FWL-OUT What we allow the firewall to talk to # Allow this machine to talk to the internet over SSH /sbin/iptables -A FWL-OUT -p tcp --destination-port 22 -j ACCEPT /sbin/iptables -A FWL-OUT -p tcp -d 209.50.17.209 -j ACCEPT /sbin/iptables -A FWL-OUT -j DROP ############################################################################### # the ICMP chain # strict version: if [ $ICMP_STRICT = 1 ] ; then /sbin/iptables -A passicmp -p icmp --icmp-type destination-unreachable -j ACCEPT /sbin/iptables -A passicmp -p icmp --icmp-type source-quench -j ACCEPT /sbin/iptables -A passicmp -p icmp --icmp-type time-exceeded -j ACCEPT /sbin/iptables -A passicmp -p icmp -j DROP else /sbin/iptables -A passicmp -p icmp -j ACCEPT fi ############################################################################### #TCP-STATE-FLAGES # All of the bits are cleared iptables -A TCP-STF -p tcp --tcp-flags ALL NONE -j DROP # SYN and FIN are both set iptables -A TCP-STF -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP # SYN and RST are both set iptables -A TCP-STF -p tcp --tcp-flags SYN,RST SYN,RST -j DROP # FIN and RST are both set iptables -A TCP-STF -p tcp --tcp-flags FIN,RST FIN,RST -j DROP # FIN is the only bit set, without the expected accompanying ACK iptables -A TCP-STF -p tcp --tcp-flags ACK,FIN FIN -j DROP #PSH is the only bit set, without the expected accompanying ACK iptables -A TCP-STF -p tcp --tcp-flags ACK,PSH PSH -j DROP #URG is the only bit set, without the expected accompanyin iptables -A TCP-STF -p tcp --tcp-flags ACK,URG URG -j DROP ############################################################################### # Allows established and related connections through if [ $CONNECTION_TRACKING = 1 ] ; then iptables -A CON-TRK -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A CON-TRK -m state --state INVALID -j LOG --log-level info --log-prefix "CS" iptables -A CON-TRK -m state --state INVALID -j DROP fi ############################################################################### #Refuse various invalid sources # Refuse spoofed packets pretending to be from the external interface’s IP address iptables -A SRC-CHK -m physdev --physdev-in $INTERNET -s $BRAIN -j DROP #Refuse packets claiming to be from a Class A,B,C private network iptables -A SRC-CHK -s $CLASS_A -j DROP iptables -A SRC-CHK -s $CLASS_B -j DROP iptables -A SRC-CHK -s $CLASS_C -j DROP #Refuse multicast packets iptables -A SRC-CHK -s $CLASS_D_MULTICAST -j DROP iptables -A SRC-CHK -s $CLASS_E_RESERVED_NET -j DROP iptables -A SRC-CHK -d $BROADCAST_DEST -j DROP #Refuse packets claiming to be from loopback iptables -A SRC-CHK -m physdev --physdev-in $INTERNET -s $LOOPBACK -j DROP #Refuse malformed broadcast packests iptables -A SRC-CHK -s $BROADCAST_DEST -j DROP iptables -A SRC-CHK -s $BROADCAST_SRC -j DROP #Refuse directed broadcasts iptables -A SRC-CHK -m physdev --physdev-in $INTERNET -s $SUBNET_NETWORK -j DROP iptables -A SRC-CHK -m physdev --physdev-in $INTERNET -s $SUBNET_BROADCAST -j DROP ############################################################################### # Brain/Gateway Server Table # Currently we accept FTP, SMTP, DNS, WWW, POP3, NTP* # We have also added the private forwards at the bottom # this is for servers that on the private IP range # SMTP /sbin/iptables -A INET-SVRS -d $BRAIN -p tcp --destination-port 25 -j ACCEPT /sbin/iptables -A INET-SVRS -d $BRAIN -p udp --destination-port 25 -j ACCEPT # Domain/Nameserver as of 9/28 this service is not available - no longer serving Inviationsource.com /sbin/iptables -A INET-SVRS -d $BRAIN -p tcp --destination-port 42 -j ACCEPT /sbin/iptables -A INET-SVRS -d $BRAIN -p udp --destination-port 42 -j ACCEPT /sbin/iptables -A INET-SVRS -d $BRAIN -p tcp --destination-port 53 -j ACCEPT /sbin/iptables -A INET-SVRS -d $BRAIN -p udp --destination-port 53 -j ACCEPT # WWW /sbin/iptables -A INET-SVRS -d $BRAIN -p tcp --destination-port 80 -j ACCEPT /sbin/iptables -A INET-SVRS -d $BRAIN -p udp --destination-port 80 -j ACCEPT # WWW/SSL /sbin/iptables -A INET-SVRS -d $BRAIN -p tcp --destination-port 443 -j ACCEPT /sbin/iptables -A INET-SVRS -d $BRAIN -p udp --destination-port 443 -j ACCEPT # Allow time server to gateway /sbin/iptables -A INET-SVRS -s $TIMESERVER1 -d $BRAIN -p udp --destination-port 123 -j ACCEPT /sbin/iptables -A INET-SVRS -s $TIMESERVER2 -d $BRAIN -p udp --destination-port 123 -j ACCEPT /sbin/iptables -A INET-SVRS -s $TIMESERVER3 -d $BRAIN -p udp --destination-port 123 -j ACCEPT /sbin/iptables -A INET-SVRS -s $TIMESERVER1 -d $BRAIN2 -p udp --destination-port 123 -j ACCEPT /sbin/iptables -A INET-SVRS -s $TIMESERVER2 -d $BRAIN2 -p udp --destination-port 123 -j ACCEPT /sbin/iptables -A INET-SVRS -s $TIMESERVER3 -d $BRAIN2 -p udp --destination-port 123 -j ACCEPT # PPTP # /sbin/iptables -A INET-SVRS -d $BRAIN -p 47 -j ACCEPT # /sbin/iptables -A INET-SVRS -d $BRAIN -p tcp --destination-port 1723 -j ACCEPT # /sbin/iptables -A INET-SVRS -d $BRAIN2 -p 47 -j ACCEPT # /sbin/iptables -A INET-SVRS -d $BRAIN2 -p tcp --destination-port 1723 -j ACCEPT # L2TP/IPSec if [ $L2TP = 1 ] ; then /sbin/iptables -A INET-SVRS -d $BRAIN -p 50 -j ACCEPT /sbin/iptables -A INET-SVRS -d $BRAIN -p 51 -j ACCEPT /sbin/iptables -A INET-SVRS -d $BRAIN -p udp --destination-port 500 -j ACCEPT /sbin/iptables -A INET-SVRS -d $BRAIN2 -p 50 -j ACCEPT /sbin/iptables -A INET-SVRS -d $BRAIN2 -p 51 -j ACCEPT /sbin/iptables -A INET-SVRS -d $BRAIN2 -p udp --destination-port 500 -j ACCEPT fi # ALLOW X Apps from cse.unl.edu to yakko /sbin/iptables -A INET-SVRS -s $CSE -d $YAKKO -p tcp --destination-port 6000 -j ACCEPT #/sbin/iptables -A INET-SVRS -s $CSE -d $YAKKO -p udp --destination-port 6000 -j ACCEPT # PACKETS THAT MAKE IT THIS FAR ARE LOGGED AND DROPPED BY POLICY /sbin/iptables -A INET-SVRS -j LOG --log-level info --log-prefix "SC: " /sbin/iptables -A INET-SVRS -j DROP ############################################################################### # SVRS-INET' # Allow out SMTP /sbin/iptables -A SVRS-INET -s $BRAIN -p tcp --source-port 25 -j ACCEPT /sbin/iptables -A SVRS-INET -s $BRAIN -p udp --source-port 25 -j ACCEPT # Allow out nameserver /sbin/iptables -A SVRS-INET -s $BRAIN -p tcp --source-port 42 -j ACCEPT /sbin/iptables -A SVRS-INET -s $BRAIN -p udp --source-port 42 -j ACCEPT # Allow out Domain (DNS) /sbin/iptables -A SVRS-INET -s $BRAIN -p tcp --source-port 53 -j ACCEPT /sbin/iptables -A SVRS-INET -s $BRAIN -p udp --source-port 53 -j ACCEPT # Allow out HTTP(s) /sbin/iptables -A SVRS-INET -s $BRAIN -p tcp --source-port 80 -j ACCEPT /sbin/iptables -A SVRS-INET -s $BRAIN -p udp --source-port 80 -j ACCEPT /sbin/iptables -A SVRS-INET -s $BRAIN -p tcp --source-port 443 -j ACCEPT /sbin/iptables -A SVRS-INET -s $BRAIN -p udp --source-port 443 -j ACCEPT # Allow NTP requests out /sbin/iptables -A SVRS-INET -s $BRAIN -d $TIMESERVER1 -p udp --source-port 123 -j ACCEPT /sbin/iptables -A SVRS-INET -s $BRAIN -d $TIMESERVER2 -p udp --source-port 123 -j ACCEPT /sbin/iptables -A SVRS-INET -s $BRAIN -d $TIMESERVER3 -p udp --source-port 123 -j ACCEPT /sbin/iptables -A SVRS-INET -s $BRAIN2 -d $TIMESERVER1 -p udp --source-port 123 -j ACCEPT /sbin/iptables -A SVRS-INET -s $BRAIN2 -d $TIMESERVER2 -p udp --source-port 123 -j ACCEPT /sbin/iptables -A SVRS-INET -s $BRAIN2 -d $TIMESERVER3 -p udp --source-port 123 -j ACCEPT # PPTP Is currently not allowed instead use L2TP # /sbin/iptables -A SVRS-INET -s $BRAIN -p 47 -j ACCEPT # /sbin/iptables -A SVRS-INET -s $BRAIN -p tcp --destination-port 1723 -j ACCEPT # /sbin/iptables -A SVRS-INET -s $BRAIN2 -p 47 -j ACCEPT # /sbin/iptables -A SVRS-INET -s $BRAIN2 -p tcp --destination-port 1723 -j ACCEPT # Next four lines stop anyone except our mail server from sending mail /sbin/iptables -A SVRS-INET -s $BRAIN -p tcp --destination-port 25 -j ACCEPT /sbin/iptables -A SVRS-INET -s $BRAIN -p udp --destination-port 25 -j ACCEPT /sbin/iptables -A SVRS-INET -s 0.0.0.0 -p tcp --destination-port 25 -j DROP /sbin/iptables -A SVRS-INET -s 0.0.0.0 -p udp --destination-port 25 -j DROP # These lines allow any activity outbound on unprivileged ports all # other outbound traffic is denied by policy /sbin/iptables -A SVRS-INET -p tcp --source-port 1024:65535 -j ACCEPT /sbin/iptables -A SVRS-INET -p udp --source-port 1024:65535 -j ACCEPT echo "Finished Firewall setup." ;; stop) echo "Flushing all rules and chains ..." /sbin/iptables -F /sbin/iptables -t nat -F /sbin/iptables -t mangle -F /sbin/iptables --delete-chain /sbin/iptables -t nat --delete-chain /sbin/iptables -t mangle --delete-chain /sbin/iptables --policy INPUT ACCEPT /sbin/iptables --policy OUTPUT ACCEPT /sbin/iptables --policy FORWARD ACCEPT #default nat policy /sbin/iptables -t nat --policy PREROUTING ACCEPT /sbin/iptables -t nat --policy OUTPUT ACCEPT /sbin/iptables -t nat --policy POSTROUTING ACCEPT #default mangle policy /sbin/iptables -t mangle --policy PREROUTING ACCEPT /sbin/iptables -t mangle --policy OUTPUT ACCEPT ;; restart) /etc/init.d/firewall stop && /etc/init.d/firewall start ;; *) echo "use firewall [start|stop]" exit 1 esac test "$return" = "$rc_done" || exit 1 exit 0
At times, I have also used NAT
In this extremely simple NAT setup I do not forward anthing to the interior of the network, although I have some commented lines that had been used to do that. This too is from a long since dead network.
#Postrouting nat stuff from 10.0.0.0 iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j SNAT --to-source x.y.z.21 # DON'T DO IT ANYMORE BECAUSE WE GOT A REGUALR IP FOR PINKY 220 - 5/30/03 #Pre routing stuff to Pinky #iptables -t nat -A PREROUTING -i eth0 -p tcp -d x.y.z.22 --sport 1024:65535 --dport 80 -j DNAT --to-destination 10.0.0.2 #iptables -t nat -A PREROUTING -i eth1 -p tcp -d x.y.z.22 --sport 1024:65535 --dport 80 -j DNAT --to-destination 10.0.0.2
Once you have NAT setup, there really isn't much difference in how the firewall is setup. You can use the one listed above.
Blocking SSH repeated login attempts
Obviously a person should use a package where appropriate, like fail2ban. But if you want to play with the nuts and bolts of your iptables firewall a bit, you might try the following:
First: Configure /etc/ssh/sshd_config to contain MaxAuthTries 1.
Second: Add a new chain to your firewall:
iptables -N SSHDENY iptables -A SSHDENY -j LOG --log-prefix "Possible ssh attack. " --log-level 7 iptables -A SSHDENY -j DROP
You also need to put an entry point for your new chain.
iptables -A INPUT -i eth0 -p tcp -m state --dport 22 --state NEW -m recent --set iptables -A INPUT -i eth0 -p tcp -m state --dport 22 --state NEW -m recent --update --seconds 120 --hitcount 7 -j SSHDENY
Third: watch /var/log/syslog for entries that include your log line.
Fourth: If you see some idiot just killing your machine with logs, consider adding the IP or range of IPs to your block list.