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.
