You are not logged in.

#1 2011-02-16 01:48:55

simongmzlj
Member
From: Canada
Registered: 2008-11-06
Posts: 135

Yet Another Firewalling Script

Recently I was hacking about trying to write a new firewall script to replace my old, aging, and somewhat unmaintainable scripts. Taking pointers from Arch's, Gentoo's, and other resources on the internet I came up with this and figured I might as well share it in its current state if anyone is interested.

I would like get some input on my techniques. I will, over reading week, get this code up on github and work at extending it. I have a grand idea of a makepkg/PKGCONFIG (fwgen/FWCONFIG?) like script that can generate firewall rule sets on the fly to be used with netcfg. I would like to have per-network firewalls on my laptop as there some networks I connect to that I trust more than others.

I aimed to keep this script dead simple: a config file and a firewall script. Any more advanced features can get tacked on by putting them in a firewall.d/ subfolder. As an example, I have attached a ssh brute force filter and rtorrent port forwarding "plugins".

config:

#! vim: ft=sh

# External facing interface
EXTERNAL=eth0

# Internal facing interface
INTERNAL=br0

# NAT type: static for SNAT, dynamic for MASQURADE, none for none
NAT=static

# External IP for SNAT
#EXTERNAL_IP=

# Local network
NETWORK='10.0.0.0/24'

# IPs or services (from /etc/services) to forward
SERVICES_TCP=(http https)
SERVICES_UDP=()

# Enable stealth mode. Under stealth mode, all unsolicited traffic is dropped instead of rejected
#STEALTH=no

firewall:

#!/bin/bash

# This script must be run as root. If sudo exists, auto-elevate
[[ "$(id -u)" != 0 ]] && exec sudo -E $0

iptables() {
  echo "iptables $*"
  /usr/sbin/iptables $* || exit 1
}

. ./config

# Reset iptables
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -F
iptables -X

# FORWARD chain
# --------------

iptables -P FORWARD DROP
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -m state --state INVALID -j DROP
iptables -A FORWARD -m state --state NEW -i ${INTERNAL} -j ACCEPT

# OUTPUT chain
# -------------

# INPUT chain
# ------------

iptables -P INPUT DROP
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A INPUT -m state --state NEW ! -i ${EXTERNAL} -j ACCEPT

# Allow only pings
iptables -A INPUT -p icmp --icmp-type 8 -m state --state NEW -j ACCEPT

# If STEALTH mode isn't set,
#  - Reject TCP connections with TCP RST packages
#  - Reject UDP streams with ICMP port unreachable messages
# othersiwe all communication will get dropped
if [[ "$STEALTH" != "yes" ]]
then
  iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreach
  iptables -A INPUT -p tcp -j REJECT --reject-with tcp-rst
fi

# Block external use of local addresses
iptables -I INPUT -i ${EXTERNAL} -s ${NETWORK} -j DROP

# POSTROUTING
# ------------

case ${NAT-none} in
  dynamic)
    iptables -t nat -A POSTROUTING -o ${EXTERNAL} \
                                   -s ${NETWORK} -j MASQUERADE
  ;;
  static)
    if [[ -n "$EXTERNAL_IP" ]]; then
      iptables -t nat -A POSTROUTING -o ${EXTERNAL} \
                                     -s ${NETWORK} -j SNAT \
                                     --to ${EXTERNAL_IP}
    fi
  ;;
esac

[[ "$BASIC" == "yes" ]] && exit 0

# OPENING SERVICES
# -----------------

if [[ -n "${SERVICES_TCP[@]}" ]]
then
  iptables -N TCP
  iptables -A INPUT -p tcp --syn -m state --state NEW -j TCP

  for SERVICE in ${SERVICES_TCP[@]}
  do
    iptables -A TCP -p tcp --dport ${SERVICE} -j ACCEPT
  done
fi

if [[ -n "${SERVICES_UDP[@]}" ]]
then
  iptables -N UDP
  iptables -A INPUT -p udp -m state --state NEW -j UDP

  for SERVICE in ${SERVICES_UDP[@]}
  do
    iptables -A UDP -p udp --dport ${SERVICE} -j ACCEPT
  done
fi

# EXTRAS (firewall.d/)
# ---------------------

find firewall.d -type f | while read FILE
do
  ( . "${FILE}" )
done

firewall.d/ssh-bruteforce:

#! vim: ft=sh
# from http://www.ducea.com/2006/06/28/using-iptables-to-block-brute-force-attacks/

#WHITELIST=()

iptables -N SSHSCAN
iptables -A INPUT -p tcp --dport ssh -m state --state NEW -j SSHSCAN

for IP in ${WHITELIST[@]}
do
  iptables -A SSHSCAN -s ${IP} -j ACCEPT
done

iptables -A SSHSCAN -m recent --update --seconds 300 \
                                       --hitcount 3 \
                                       --name SSH -j LOG \
                                       --log-level info --log-prefix "SSHSCAN: "
iptables -A SSHSCAN -m recent --update --seconds 300 \
                                       --hitcount 3 \
                                       --name SSH -j DROP
iptables -A SSHSCAN -m recent --set --name SSH -j ACCEPT

firewall.d/torrents:

#! vim: ft=sh

iptables -N TORRENTS
iptables -A INPUT -p tcp --syn -m state --state NEW -j TORRENTS
iptables -A INPUT -p udp -m state --state NEW -j TORRENTS

iptables -A TORRENTS -p tcp --dport 49164:49164 -i ${EXTERNAL} -j ACCEPT
iptables -A TORRENTS -p udp --dport 6881 -i ${EXTERNAL} -j ACCEPT

EDIT: Fixed ssh-bruteforce rules

Last edited by simongmzlj (2011-02-16 02:24:59)

Offline

#2 2011-02-16 04:50:17

fukawi2
Ex-Administratorino
From: .vic.au
Registered: 2007-09-28
Posts: 6,226
Website

Re: Yet Another Firewalling Script

As well as "Echo Request", you should allow ICMP "Destination Unreachable", "TTL Exceeded" and possibly "Source Quench"

Offline

Board footer

Powered by FluxBB