For this script to work, you need a lot of stuff in the kernel netfilter configuration. Just compile all of it as modules or something. The only things you don't need is the ipchains-compatibility module, and the ipfwadm-compatibility module.
Just edit the three variables EXT_IF, INT_IF, and OPEN_TCP_PORTS at the top, save as /etc/rc.d/rc.firewall, and run it.
If you have any site-specific rules, put them in a file /etc/rc.d/rc.firewall.local and make it executable, and it will be run at the end of this script.
I also use a couple of scripts to easily open and close ports. See Kreigers firewall-tools.
#!/bin/sh
#
# /etc/rc.d/rc.firewall: Sets up firewall and ip-masquerading
#
# The external interface
EXT_IF=eth0
# The internal interface
INT_IF=eth1
# tcp-ports to open
OPEN_TCP_PORTS='ssh www auth cvspserver'
IPTABLES=/usr/sbin/iptables
get_address_of_interface () {
IF=$1
ifconfig $IF|grep 'inet addr:'|sed -e 's/ Bcast.*//;s/.*://'
}
get_netmask_of_interface () {
IF=$1
ifconfig $IF|grep 'inet addr:'|sed -e 's/.*://'
}
EXT_IP=`get_address_of_interface $EXT_IF`
INT_IP=`get_address_of_interface $INT_IF`
INT_NET=$INT_IP/`get_netmask_of_interface $INT_IF`
echo "The external ip is $EXT_IP."
echo "The internal ip is $INT_IP."
echo "The internal network is $INT_NET."
echo "Setting up firewall."
# Support for ftp
echo "Loading modules for NAT of ftp and irc"
/sbin/modprobe ip_nat_ftp
/sbin/modprobe ip_nat_irc
# First, set default policy to DROP,
# which means all packets are dropped unless
# one of the rules says otherwise
echo "Dropping all incoming and forwarded packets by default."
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
# Flush tables filter and nat
echo "Deleting all previous rules from tables filter, nat, and mangle."
$IPTABLES -F -t filter
$IPTABLES -F -t nat
$IPTABLES -F -t mangle
# Allow everything in from the loopback interface.
echo "Allowing packages from localhost."
$IPTABLES -A INPUT -i lo -j ACCEPT
# Allow everything in and forwarded from the internal interface.
$IPTABLES -A INPUT -i $INT_IF -j ACCEPT
$IPTABLES -A FORWARD -i $INT_IF -j ACCEPT
# Allow only incoming and forwarded packets belonging to
# ESTABLISHED and RELATED connections from external interface.
# (disallow NEW and INVALID connections)
echo "Allowing incoming packets belonging to or related to already established connections."
$IPTABLES -A INPUT -i $EXT_IF -j ACCEPT -m state --state ESTABLISHED,RELATED
echo "Allowing forwarded packets belonging to or related to already established connections."
$IPTABLES -A FORWARD -i $EXT_IF -j ACCEPT -m state --state ESTABLISHED,RELATED
# Set up masquerading from internal net to external interface
echo "Enabling masquerading of internal net $INT_NET to external interface $EXT_IF."
$IPTABLES -A POSTROUTING -t nat -s $INT_NET -o $EXT_IF -j MASQUERADE
## Use SNAT instead of MASQUERADE if you have a static IP.
#echo "Enabling source NAT of internal net $INT_NET to address $EXT_IP on external interface $EXT_IF."
#$IPTABLES -A POSTROUTING -t nat -s $INT_NET -o $EXT_IF -j SNAT --to-source $EXT_IP
# Open one tcp port
open_tcp_port () {
PORT=$1
$IPTABLES -A INPUT -i $EXT_IF -p tcp --dport $PORT -j ACCEPT -m state --state NEW
}
# Open all tcp ports in OPEN_TCP_PORTS
if [ -n "$OPEN_TCP_PORTS" ]; then
echo -n "Opening tcp ports"
for PORT in $OPEN_TCP_PORTS; do
echo -n " $PORT"
open_tcp_port $PORT
done
echo
fi
# Function to forward one port to an internal machine.
forward_tcp_port () {
PORT=$1
TO_IP=$2
TO_PORT=$3
# Forward packets coming in from the outside
$IPTABLES -A PREROUTING -t nat -p tcp -d $EXT_IP --dport $PORT -j DNAT --to-destination $TO_IP:$TO_PORT
# Make it work from the firewall itself
$IPTABLES -A OUTPUT -t nat -p tcp -d $EXT_IP --dport $PORT -j DNAT --to-destination $TO_IP:$TO_PORT
# Make responses on the internal network go through the firewall
$IPTABLES -A POSTROUTING -t nat -p tcp -d $TO_IP --dport $TO_PORT -j SNAT --to-source $INT_IP
# Allow the forwarded packets
$IPTABLES -A FORWARD -p tcp -d $TO_IP --dport $TO_PORT -j ACCEPT -m state --state NEW,ESTABLISHED,RELATED
}
# Run the local additions
if [ -x /etc/rc.d/rc.firewall.local ]; then
echo "Enabling local firewall rules."
. /etc/rc.d/rc.firewall.local
fi
echo "Done setting up firewall."
Here follows my own rc.firewall.local. Firewall-rules specific to my own setup You probably don't want this. Make your own.
#!/bin/sh # # /etc/rc.d/rc.firewall.local - Kreigers site-specific firewall-rules. # # Minimize delay of outgoing ssh-packets echo "Minimizing delay of outgoing packets in ssh connections." $IPTABLES -A OUTPUT -t mangle -p tcp --sport ssh -j TOS --set-tos Minimize-Delay # Allow dhcp packets from telias net echo "Allowing dhcp packets from telias net." $IPTABLES -A INPUT -i $EXT_IF -p udp --dport dhcpc --sport dhcps -s 10.0.0.0/8 -j ACCEPT # Drop netbios-name packets (just to get a specific packet-counter for dropped netbios-name packets). $IPTABLES -A INPUT -i $EXT_IF -p udp --dport netbios-ns -j DROP # Drop 'unclean' packets. $IPTABLES -A INPUT -i $EXT_IF -j DROP -m unclean ## log unsolicited tcp and udp packets #$IPTABLES -A INPUT -i $EXT_IF -p tcp -j LOG -m limit --limit 2/minute --log-prefix 'firewall-tcp ' --log-level info #$IPTABLES -A INPUT -i $EXT_IF -p udp -j LOG -m limit --limit 2/minute --log-prefix 'firewall-udp ' --log-level info ## log icmp packets #$IPTABLES -A INPUT -i $EXT_IF -p icmp -j LOG -m limit --limit 2/minute --log-prefix 'firewall-icmp ' --log-level info # Drop pings #$IPTABLES -A INPUT -i $EXT_IF -p icmp --icmp-type ping -j DROP # Accept other icmp packets # Note that icmp packets related to connections should be caught by the state ESTABLISHED,RELATED rule above. $IPTABLES -A INPUT -i $EXT_IF -p icmp -j ACCEPT echo "Forwarding tcp-port gnutella to internal address 192.168.0.2." forward_tcp_port gnutella 192.168.0.2 6346