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.
