iptables simple firewall

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

2 Comments

  1. 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.

  2. joachim says:

    I am always interested to hear about alternative (better?) ways to solve the problem at hand.

Leave a Reply

Your email address will not be published. Required fields are marked *

question razz sad evil exclaim smile redface biggrin surprised eek confused cool lol mad twisted rolleyes wink idea arrow neutral cry mrgreen

*