#!/bin/bash
# PFWAFW - Precreated firewallscripts are for wussies 
# Copyright (C) 2009 Kristian Lyngstol <kristian@bohemians.org>
# 
# Use for whatever. Except alien invasions. In case of alien invasions, this
# script can not be used to stop the aliens.


# Host: Nihilus. 

# Tillaete tjenester: 
#  SSH fra: pluto,firewall,kjeks
#  Ntp: Fra firewall.
#  Port80: Tillat for alle.
# Tillate andre ting: ESTABLISHED,RELATED
# Forward er litt løsere men ikke mye.
# Tillat web, dns, ssh, ftp og dhcp alle veier
# Tillat MySQL mot en MySQL server fra enkelte IPer
# Tillat apt-cacher 
# Tillat Munin (4949) (både input og forward) fra munin-masters.

# Who am I?
ME="192.168.1.29"

# LOCAL
SSH_SOURCES="192.168.1.1 192.168.1.2 192.168.1.20 192.168.1.44"
VM_NET="192.168.122.0/24"
MUNIN_MASTERS="192.168.1.29 127.0.0.1"
PUBLIC_TCP="80 49153"
PUBLIC_UDP="1900"
TCP_FORWARD_PORTS="80 22 53 21"
UDP_FORWARD_PORTS="53 68 67" # DNS and DHCP
MYSQL_SERVERS="192.168.1.51"
MYSQL_CLIENTS="192.168.1.51 192.168.1.52 192.168.1.53"

# Flush
iptables -F INPUT
iptables -F FORWARD

# Basic stuff - Related. 
iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -m comment --comment "idINACBasicEstabRel"
iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT -m comment --comment "idFOACBasicEstabRel"
iptables -I INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT -m comment --comment "idINACBasicLocal"
iptables -P INPUT DROP
iptables -P FORWARD DROP

# Allow 100 ICMP's a minute. Log 15/minute that exceeds that and drop.
iptables -A INPUT -p icmp -m limit --limit 100/minute -j ACCEPT -m comment --comment "idINACICMPLimit"
iptables -A INPUT -p icmp -m limit --limit 15/minute -j LOG --log-prefix "ICMP flood? " -m comment --comment "idINLOICMPLimit"
iptables -A INPUT -p icmp -j DROP -m comment --comment "idINDRICMP"

# Ignore DHCP requests incomming. We're not a DHCP server.
iptables -A INPUT -p udp --sport 68 --dport 67 -d 255.255.255.255 -j DROP -m comment --comment "idINDRDHCPServer"

for a in $PUBLIC_TCP; do
	iptables -I INPUT -p tcp --dport $a -j ACCEPT -m comment --comment "idINACPubTCP$a"
done

for a in $PUBLIC_UDP; do
	iptables -I INPUT -p udp --dport $a -j ACCEPT -m comment --comment "idINACPubUDP$a"
done

# SSH
for a in $SSH_SOURCES; do
	printsrc=`echo $a | sed 's/\.//g'`
	iptables -I INPUT -p tcp -s $a --dport 22 -j ACCEPT -m comment --comment "idINACSSH${printsrc}"
done

# VM
# Allow dhcp-related traffic.
iptables -I INPUT -p udp --dport 67 -i 'vnet+' -j ACCEPT -m comment --comment "idINACDHCPVirt"
for a in $VM_NET; do
	printsrc=`echo $a | sed 's/[\.\/]//g'`
	iptables -I FORWARD -s $a -j ACCEPT -m comment --comment "idFOACVM${printsrc}"
	# DNS queries for dnsmasq.
	iptables -I INPUT -p tcp -s $a --dport 53 -j ACCEPT -m comment --comment "idINACTCPDNSVM${printsrc}"
	iptables -I INPUT -p udp -s $a --dport 53 -j ACCEPT -m comment --comment "idINACUDPDNSVM${printsrc}"
done


# Munin 
for a in $MUNIN_MASTERS; do
	printsrc=`echo $a | sed 's/[\.\/]//g'`
	iptables -I INPUT -p tcp -s $a --dport 4949 -j ACCEPT -m comment --comment "idINACMunin${printsrc}"
	iptables -I FORWARD -p tcp -s $a --dport 4949 -j ACCEPT -m comment --comment "idFOACMunin${printsrc}"
done


# Forwarding
# Allow apt-cacher
iptables -I FORWARD -o br0 -d 192.168.1.2 -p tcp --dport 3142 -j ACCEPT -m comment --comment "idFOACaptcacher"

for a in $TCP_FORWARD_PORTS; do
	iptables -I FORWARD -p tcp --dport $a -j ACCEPT -m comment --comment "idFOACTCP$a";
done
for a in $UDP_FORWARD_PORTS; do
	iptables -I FORWARD -p udp --dport $a -j ACCEPT -m comment --comment "idFOACUDP$a";
done

for server in $MYSQL_SERVERS; do 
	for client in $MYSQL_CLIENTS; do
		printsrv=`echo $server | sed 's/[\.\/]//g'`
		printcli=`echo $client | sed 's/[\.\/]//g'`
		iptables -I FORWARD -p tcp --dport 3306 -s $client -d $server -j ACCEPT -m comment --comment "idFOACMySQL${printsrv}${printcli}"
	done
done

# Explicitly drop broadcasts for SMB
# This stuff is irrelevant to us but happens and we don't want to spam 
# the logs with it.
iptables -I INPUT -p udp --dport 138 --sport 138 -d 192.168.1.255 -j DROP -m comment --comment "idINDRUDP138138brloc"
iptables -I INPUT -p udp --dport 137 --sport 137 -d 192.168.1.255 -j DROP -m comment --comment "idINDRUDP137137brloc"
iptables -I INPUT -p udp --dport 138 --sport 138 -d 255.255.255.255 -j DROP -m comment --comment "idINDRUDP138138brtot"
iptables -I INPUT -p udp --dport 137 --sport 137 -d 255.255.255.255 -j DROP -m comment --comment "idINDRUDP138138brtot"

iptables -F LOGLIMIT
iptables -X LOGLIMIT
iptables -N LOGLIMIT
iptables -A INPUT -j LOGLIMIT -m comment --comment "idINLLLogLimit"

# Only log limited amounts of broadcast crap. No need to fill logs with stuff
# we don't care about.
iptables -A LOGLIMIT -m limit -p udp -d 255.255.255.255 --limit 5/hour -j LOG --log-prefix "Blocked UDP broadcast " -m comment --comment "idLLLODropUDPBroadcast"
iptables -A LOGLIMIT -p udp -d 255.255.255.255 -j DROP -m comment --comment "idLLDRUDPBroadcast"

# Log TCP and UDP directed at me more agressively.
iptables -A LOGLIMIT -m limit --limit 25/minute -d $ME -j LOG --log-prefix "Blocked to us " -m comment --comment "idLLLODropToMe"
iptables -A LOGLIMIT -d $ME -j DROP -m comment --comment "idLLDRDropToMe"

# Catch-all
iptables -A LOGLIMIT -m limit --limit 5/minute -j LOG --log-prefix "Blocked unknown " -m comment --comment "idLLLODropUnknown"

# Ensure that fail2ban is set up correctly after fw-reload
fail2ban-client reload
