#!/bin/sh 
# 
# firewall script for WRT54GS router running openwrt.
#
# By Robert W. Brewer rwb123 at gmail dot com
#
# This script is placed in the public domain.
# 
# TODO:
#   clarify overall structure... input rules, output rules, accepted, etc.
#   use iptables recent module for port triggering -- see recent home page
#     looks like that may not work for port triggering, may need to 
#     have iptables communicate with a userspace daemon, or have a 
#     daemon monitor the recent list (somewhere in /proc) 
#     and open the ports that way.  Maybe the packets could be logged
#     and a realtime log analysis daemon could be used to 
#     maintain the additional iptables rules for the port triggering.
#   add rules to mangle the TCP timestamp fields to prevent the 
#     recent identification attacks noted for that
#

cd /etc || exit 1

. /etc/functions.sh
export WAN=$(nvram get wan_ifname)
export LAN=$(nvram get lan_ifname)


# set policy of all tables to DROP by default
iptables -P OUTPUT  DROP
iptables -P INPUT   DROP
iptables -P FORWARD DROP

for T in filter nat mangle; do
  iptables -t $T -F
  iptables -t $T -X
done


# ensure needed modules are loaded
#insmod ipt_conntrack
#insmod ipt_limit

# turn off forwarding while we build the rules
# we will turn it on in the end when everything is set up
FWD=`cat /proc/sys/net/ipv4/ip_forward`
echo "0" > /proc/sys/net/ipv4/ip_forward

# set some other params
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_intvl

# create log and drop rule with rate-limited logging 
iptables -N LOGDROP
#iptables -A LOGDROP -j LOG  --log-level info --log-prefix "DROP: "  -m limit --limit 5/minute --limit-burst 5
iptables -A LOGDROP -j DROP

# IP masquerading of everything destined to the internet
# this is like SNAT (source network address translation)
# but works properly with a dynamic WAN address, such as 
# assigned by DHCP or dialup
iptables -t nat -A POSTROUTING -o $WAN -j MASQUERADE

# allow any connections already allowed, no questions asked.
# note that we put this first in our tables for better performance...
# long-running flows will hit these rules right away without further 
# rule processing
iptables -A INPUT   -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT  -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

# argh, according to http://www.faqs.org/docs/iptables/newnotsyn.html
# there is some weirdness with the way the NEW state works which means
# sometimes non-SYN TCP packets will slip through as NEW
# so we explicitly check for them
iptables -A INPUT   -p tcp ! --syn -m state --state NEW -j LOGDROP
iptables -A OUTPUT  -p tcp ! --syn -m state --state NEW -j LOGDROP
iptables -A FORWARD -p tcp ! --syn -m state --state NEW -j LOGDROP

# allow everything inbound on loopback
iptables -A INPUT -i lo -j ACCEPT

# allow all new outgoing connections from the router
iptables -A OUTPUT -m state --state NEW -j ACCEPT 

# allow all LAN routed connections through router
iptables -A FORWARD -i \! $WAN -m state --state NEW -j ACCEPT
# allow all new routed connections outbound to internet
#iptables -A FORWARD -o $WAN -m state --state NEW -j ACCEPT 

# forward incoming ssh port to server box
iptables -t nat -A PREROUTING -i $WAN -p tcp --dport 22 -j DNAT --to 192.168.0.10
# allow new connections through on that port forward
iptables -A FORWARD -i $WAN -d 192.168.0.10 -p tcp --dport 22 -m state --state NEW -j ACCEPT


# limit incoming internet ping request rate from anywhere
iptables -A INPUT -p icmp --icmp-type 8/0 -m limit --limit 4/second --limit-burst 5 -j ACCEPT 

# allow incoming ssh from anywhere but WAN
iptables -A INPUT -i \! $WAN -p tcp --dport 22 -m state --state NEW -j ACCEPT 

# allow incoming mDNS (rendezvous) from anywhere but WAN
iptables -A INPUT -i \! $WAN -p udp --dport 5353 -d 224.0.0.251 -m state --state NEW -j ACCEPT

# allow incoming DNS from anywhere but WAN
iptables -A INPUT -i \! $WAN -p udp --dport 53 -m state --state NEW -j ACCEPT

# allow incoming dhcp anywhere but WAN
iptables -A INPUT -i \! $WAN -p udp --dport 67:68 -m state --state NEW -j ACCEPT

# allow incoming telnet from anywhere but WAN
iptables -A INPUT -i \! $WAN -p tcp --dport 23 -m state --state NEW -j ACCEPT

# allow incoming ntp from anywhere but WAN
iptables -A INPUT -i \! $WAN -p udp --dport 123 -m state --state NEW -j ACCEPT

# log and drop everything not explicitly allowed
iptables -A INPUT   -j LOGDROP
iptables -A FORWARD -j LOGDROP
iptables -A OUTPUT  -j LOGDROP


# now activate routing (if it was enabled elsewhere)
echo "$FWD" > /proc/sys/net/ipv4/ip_forward


