Thanks to my colleague Jeroen, details to setup a simple iptables based firewall which only allows external access using ssh, http and https (easily modifiable to add access on other ports).
Create a file “/etc/init.d/firewall” with following content.
#!/bin/sh
# iptables setup script for a firewall. Locks down all external access except a
# few selected services like ssh, http end https.
# The script behaves like any normal init.d service start/stop script. It
# is "started" after the network interfaces have been brought up, so all
# interface IP addresses are known. "Restart" or "reload" means "start". It
# is "stopped" during the shutdown process.
# NOTICE: the firewall does not go up and down with the interfaces! It is
# not linked to ifup/ifdown, but treated as a init.d service.
##### HOUSEKEEPING ##########
# Abort after first script error.
set -e
# The iptables command. Shorter and sure.
ipt=/sbin/iptables
# The network interface.
if=eth0
##### FIREWALL STOP ##########
if [ "$1" = "stop" ]; then
# Stopping the firewall means taking it down; everything is allowed
# through, except forwarding. So the local network still is isolated from
# the wild internet.
echo "Taking down firewall (no blocking at all)..."
# Flush current rules.
$ipt -F INPUT
$ipt -F OUTPUT
$ipt -F FORWARD
$ipt -t nat -F PREROUTING
$ipt -t nat -F POSTROUTING
$ipt -t nat -F OUTPUT
# Set default to allow everything, but don't do forwarding.
$ipt -P INPUT ACCEPT
$ipt -P OUTPUT ACCEPT
$ipt -P FORWARD DROP
# Disable forwarding in the kernel.
echo "0" > /proc/sys/net/ipv4/ip_forward
echo " Done."
exit
fi
##### FIREWALL START/RELOAD/RESTART ##########
echo "Building firewall..."
# Flush current rules.
$ipt -F INPUT
$ipt -F OUTPUT
$ipt -F FORWARD
$ipt -t nat -F PREROUTING
$ipt -t nat -F POSTROUTING
$ipt -t nat -F OUTPUT
# Set default Black Knight policies; No One Shall Pass.
$ipt -P INPUT DROP
$ipt -P OUTPUT DROP
$ipt -P FORWARD DROP
##### INPUT RULE CHAIN ##########
# For packets into and destined for the gateway itself. Not for masquerading.
# Everything from loopback interface is ok.
$ipt -A INPUT -i lo -j ACCEPT
# Everything from the network on a known connection is ok.
$ipt -A INPUT -i $if -m state --state ESTABLISHED,RELATED -j ACCEPT
# Everything from the network that tries to open a ssh connection is ok.
$ipt -A INPUT -i $if -m state --state NEW -p tcp --dport ssh -j ACCEPT
# Everything from the network that tries to open a http connection is ok.
$ipt -A INPUT -i $if -m state --state NEW -p tcp --dport http -j ACCEPT
# Everything from the network that tries to open a https connection is ok.
$ipt -A INPUT -i $if -m state --state NEW -p tcp --dport https -j ACCEPT
# The rest is dropped. We don't even bother to log it.
$ipt -A INPUT -j DROP
##### OUTPUT RULE CHAIN ##########
# For packets destined for something out there. Not for masquerading.
# Everything to loopback interface is ok.
$ipt -A OUTPUT -o lo -j ACCEPT
# Everything going out on the network is ok.
$ipt -A OUTPUT -o $if -j ACCEPT
##### FORWARD RULE CHAIN ##########
# For packets that are routed through the gateway. We do not use this
# feature at all so this block is empty.
echo " Done."
# EOF
Now links this into the system using the following commands (as root).
chown root:root /etc/init.d/firewall
chmod 0700 /etc/init.d/firewall
update-rc.d firewall defaults 19
/etc/init.d/firewall start
I always found iptables syntax cumbersome and counter intuitive, and used things like shorewall for more elaborated stuff. I recently started working with pf (BSD), which is confirmed to be very nice to work with.
I am always interested to hear about alternative (better?) ways to solve the problem at hand.