I'm trying to get this iptables firewall script to run from init.d on a Debian Lenny x64 server, but it keeps locking me out entirely. Recently I added connlimit and anti-brute force rules, but ever since I did that, the problems started.. I suspect it has to do with the ordering of rules, or a missing character. Any expert wanting to take a look and help correct the mistake( s )?
Code:
#!/bin/bash
# chkconfig: 2345 18 92
# description: iptables interface script 2009
IPTABLES="/sbin/iptables"
SERVER_IPS=`/sbin/ifconfig | grep inet | cut -d : -f 2 | cut -d \ -f 1 | grep -v 127.0.0.1`
IP_W1="88.x.x.1"
IP_W2="88.x.x.2"
IP_W3="88.x.x.3"
SSHP="22322"
WMNP="22381"
XTRP="22344"
FWIN="${IPTABLES} -A INPUT"
FWOUT="${IPTABLES} -A OUTPUT"
OK="-j ACCEPT"
NO="-j DROP"
BLDB="/www/site/list_of_blocked_ips.txt"
# Flush tables and change default policy to DROP
function initialize() {
local TABLE="${1}"
${IPTABLES} -F ${TABLE}
${IPTABLES} -P ${TABLE} DROP
}
# Flush tables and change default policy to ACCEPT
function stop() {
local TABLE="${1}"
${IPTABLES} -F ${TABLE}
${IPTABLES} -P ${TABLE} ACCEPT
}
# Verify call switch
case "$1" in
start|restart)
initialize INPUT
initialize OUTPUT
initialize FORWARD
## before all others, drop the manually added list of IPs
IPS=$(grep -Ev "^#" $BLDB)
for i in $IPS
do
${IPTABLES} -A INPUT -s $i ${NO}
${IPTABLES} -A OUTPUT -d $i ${NO}
done
# INPUT
# 1) loopback
${FWIN} -i lo ${OK}
${FWIN} -d 127.0.0.0/8 ${NO}
# incoming SSH connections, answers to our own SSH connections, anti brute force:
for OURIP in ${IP_W3}; do
${IPTABLES} -p tcp --syn --dport ${SSHP} -m connlimit --connlimit-above 2 -j REJECT
${FWIN} -p tcp --dport ${SSHP} -m state --state NEW -m recent --set
${FWIN} -p tcp --dport ${SSHP} -m state --state NEW -m recent --update --seconds 120 --hitcount 4 ${NO}
${FWIN} -p tcp --dport ${SSHP} ${OK}
${FWIN} -p tcp -d ${OURIP} --dport ${SSHP} ${OK}
${FWIN} -p tcp --sport ${SSHP} -d ${OURIP} "!" --syn ${OK}
done
# We allow incoming DNS queries as well as answers to our DNS queries.
for OURIP in ${SERVER_IPS}; do
# ${FWIN} -p tcp -d ${OURIP} --dport 53 ${OK}
# ${FWIN} -p udp -d ${OURIP} --dport 53 ${OK}
${FWIN} -p tcp --sport 53 -d ${OURIP} --dport 1024: "!" --syn ${OK}
${FWIN} -p udp --sport 53 -d ${OURIP} --dport 1024: ${OK}
done
# We allow access to our SMTP server, as well as smtp TLS and answers
# to our SMTP connections and, temporarily, identd stuff:
for OURIP in ${IP_W1}; do
${IPTABLES} -t nat -A PREROUTING -p tcp -d ${OURIP} --dport 587 -j REDIRECT --to-ports 25
${FWIN} -p tcp -d ${OURIP} --dport 25 ${OK}
${FWIN} -p tcp --sport 25 -d ${OURIP} --dport 1024: "!" --syn ${OK}
${FWIN} -p tcp --sport 1024: -d ${OURIP} --dport 113 ${OK}
${FWIN} -p udp --sport 1024: -d ${OURIP} --dport 113 ${OK}
${FWIN} -p tcp --sport 113 -d ${OURIP} --dport 1024: "!" --syn ${OK}
${FWIN} -p udp --sport 113 -d ${OURIP} --dport 1024: ${OK}
done
# 5) We also allow access to our POP/sPOP server.
for OURIP in ${IP_W1}; do
${FWIN} -p tcp -d ${OURIP} --dport 110 ${OK}
${FWIN} -p tcp -d ${OURIP} --dport 995 ${OK}
done
# 6) and to IMAP/IMAPs
for OURIP in ${IP_W1}; do
${FWIN} -p tcp -d ${OURIP} --dport 143 ${OK}
${FWIN} -p tcp -d ${OURIP} --dport 993 ${OK}
done
# We allow incoming echo replies/requests from everywhere:
for OURIP in ${SERVER_IPS}; do
${FWIN} -p icmp -d ${OURIP} --icmp-type 0 ${OK}
${FWIN} -p icmp -d ${OURIP} --icmp-type 3 ${OK}
${FWIN} -p icmp -d ${OURIP} --icmp-type 8 ${OK}
${FWIN} -p icmp -d ${OURIP} --icmp-type 11 ${OK}
done
# but we do ping-flood-protect
${FWIN} -p icmp --icmp-type echo-request -m limit --limit 5/s -j ACCEPT
${FWIN} -p icmp --icmp-type echo-request -j DROP
# syn-flood-protect
${FWIN} -p tcp --syn -m limit --limit 10/s -j ACCEPT
${FWIN} -p tcp --syn -j DROP
# port-scanner-limitation
${FWIN} -p tcp -i eth0 --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 5/s -j ACCEPT
${FWIN} -p tcp -i eth0 --tcp-flags SYN,ACK,FIN,RST RST -j DROP
# and limit parallel http requests to 18 per class C sized network (24 bit netmask), fight Slowloris etc.
${IPTABLES} -p tcp --syn --dport 80 -m connlimit --connlimit-above 16 --connlimit-mask 24 -j REJECT
# We also would like to allow access to our web server:
for OURIP in ${IP_W1}; do
${FWIN} -p tcp -d ${OURIP} --dport 80 ${OK}
${FWIN} -p udp -d ${OURIP} --dport 80 ${OK}
${FWIN} -p tcp -d ${OURIP} --dport 81 ${OK}
${FWIN} -p udp -d ${OURIP} --dport 81 ${OK}
${FWIN} -p tcp -d ${OURIP} --dport 443 ${OK}
${FWIN} -p udp -d ${OURIP} --dport 443 ${OK}
${FWIN} -p tcp -d ${OURIP} --dport ${XTRP} ${OK}
${FWIN} -p udp -d ${OURIP} --dport ${XTRP} ${OK}
done
# We also would like to allow access to our web server2 IP:
for OURIP in ${IP_W2}; do
${FWIN} -p tcp -d ${OURIP} --dport 80 ${OK}
${FWIN} -p udp -d ${OURIP} --dport 80 ${OK}
done
# people are still smart enough to use vsFTPd:
for OURIP in ${IP_W2}; do
for PORT in 20 21; do
${FWIN} -p tcp -d ${OURIP} --dport ${PORT} ${OK}
${FWIN} -p tcp --sport ${PORT} -d ${OURIP} --dport 1024: "!" --syn ${OK}
${FWIN} -p udp -d ${OURIP} --dport ${PORT} ${OK}
${FWIN} -p udp --sport ${PORT} -d ${OURIP} --dport 1024: ${OK}
done
done
# allow answers on high ports
${FWIN} -p tcp -m tcp --dport 1024:65535 ! --tcp-flags SYN,RST,ACK SYN ${OK}
${FWIN} -p udp -m udp --dport 1024:65535 ${OK}
# passive ftp
# configure ftp server to allow passive ftp on ports
# outside of the local range. Check local range with
# cat /proc/sys/net/ipv4/ip_local_port_range
# in /etc/vsftpd/vsftpd.conf
${FWIN} -p tcp -m tcp --dport 50000:65000 ${OK}
# miniserv/webmin
# lock out brute force shit
for OURIP in ${IP_W3}; do
${IPTABLES} -p tcp --syn -d ${OURIP} --dport ${WMNP} -m connlimit --connlimit-above 2 -j REJECT
${FWIN} -p tcp -d ${OURIP} --dport ${WMNP} -m state --state NEW -m recent --set
${FWIN} -p tcp -d ${OURIP} --dport ${WMNP} -m state --state NEW -m recent --update --seconds 90 --hitcount 4 ${NO}
${FWIN} -p tcp -d ${OURIP} --dport ${WMNP} ${OK}
${FWIN} -p tcp --sport ${WMNP} -d ${OURIP} --dport 1024: "!" --syn ${OK}
done
# Everything else is denied by default - policy is DROP.
# OUTPUT
# 1) Loopback packets.
${FWOUT} -o lo ${OK}
${FWOUT} -s 127.0.0.0/8 ${NO}
# 2) We allow all outgoing traffic:
for OURIP in ${SERVER_IPS}; do
${FWOUT} -s ${OURIP} ${OK}
done
;;
stop)
# turn off the firewall, flush all rules
echo "Flushing rulesets.."
stop INPUT
stop OUTPUT
stop FORWARD
;;
status)
# display the current status - both firewall rules and masquerading
# connections
# list rules. -n avoids DNS lookups
$IPTABLES -nL
;;
*)
echo "Usage: firewall {start|stop|restart|status}"
exit 1
esac
exit 0
Sorry for the messy code here and there, it's a merge from a couple of rules that went in and out over a long period of time.
Thanks in advance!