NAT / Firewall

Repository for NAT and firewall
ideas

Inexpensive hardware that can perform NAT

We purchased a LinkSys Etherfast Cable/DSL router (model BEFSR11) at Fry's for about $100.00. This model has two network interfaces, one 10 baseT WAN or public network connection, and one 10/100 baseT private LAN connection. This same device can be purchased with either 4 or 8 switched 10/100 baseT ports on the private, or LAN side for about $50.00 to $100.00 more.

Features

All configuration is done through a web browser on a computer on the LAN side. The LAN side can have a mixture of IP addresses that are either statically assigned or assigned by an internal DHCP server. The LAN side consists of one class C subnet (192.168.1.0). Typically, the box itself take the first IP address (192.168.1.1). The WAN side can either have it's IP address assigned statically, or via DHCP. Up to 8 TCP ports on the WAN side can be forwarded to IP addresses on the LAN side. I measured the throughput at about 350 kbytes/second. The router itself was stable over the duration of my testing, but I was able to reboot it by repeated syn scans from nmap. The only items that we wished for were syslog logging (logging of any sort) and the ability to forward UDP.

Solaris firewalls with IPfilter

IPfilter  can be used to construct firewalls (or just to filter and/or log packets) on all supported
operating systems, which includes Solaris. I've installed ipfilter on roswell.sdsu.edu with
the configuration given below. Note that no packets are currently being blocked, just logged. My plan is run this for several days to "tune" it and then convert it to block unwanted packets. My concerns for tuning include udp services, passive ftp connections, and web servers not included below. If you are interested in the IPfilter howto, I have a local copy here.

#
# tcp philosophy is to allow all outbound & keep state for return
#	AND
# to allow anything from two local class B's
#	AND
# to allow connections on a specified set of services
# 
# pass all local ... no state ... udp and tcp
pass in quick on hme0 from 130.191.0.0/16 to any
pass in quick on hme0 from 146.244.0.0/16 to any
pass out quick on hme0 from any to 130.191.0.0/16
pass out quick on hme0 from any to 146.244.0.0/16
# allowed remote services ... telnet (23) ftp (21) pop (110) ssh (22)
# smtp (25)
# ftp / ftp-data
pass in quick on hme0 proto tcp from any to any port = 20 flags S keep state keep frags
pass in quick on hme0 proto tcp from any to any port = 21 flags S keep state keep frags
# ssh
pass in quick on hme0 proto tcp from any to any port = 22 flags S keep state keep frags
# telnet
pass in quick on hme0 proto tcp from any to any port = 23 flags S keep state keep frags
# smtp
pass in quick on hme0 proto tcp from any to any port = 25 flags S keep state keep frags
# time
pass in quick on hme0 proto tcp from any to any port = 37 flags S keep state keep frags
# dns
pass in quick on hme0 proto tcp from any to any port = 53 flags S keep state keep frags
# finger
pass in quick on hme0 proto tcp from any to any port = 79 flags S keep state keep frags
# web servers
pass in quick on hme0 proto tcp from any to any port = 80 flags S keep state keep frags
# alternate http servers
pass in quick on hme0 proto tcp from any to any port = 443 flags S keep state keep frags
pass in quick on hme0 proto tcp from any to any port = 7171 flags S keep state keep frags
pass in quick on hme0 proto tcp from any to any port = 8080 flags S keep state keep frags
pass in quick on hme0 proto tcp from any to any port = 8888 flags S keep state keep frags
pass in quick on hme0 proto tcp from any to any port = 9090 flags S keep state keep frags
pass in quick on hme0 proto tcp from any to any port = 9191 flags S keep state keep frags
# pop
pass in quick on hme0 proto tcp from any to any port = 109 flags S keep state keep frags
pass in quick on hme0 proto tcp from any to any port = 110 flags S keep state keep frags
# ident
pass in quick on hme0 proto tcp from any to any port = 113 flags S keep state keep frags
# necessary (keep state) for return part of outgoing connections
pass out quick on hme0 proto tcp from any to any flags S keep state keep frags
# nuke all TCP that does not fit above critera (SDSU class B, allowed ports)
#block return-rst in log quick on hme0 proto tcp all
block in log quick on hme0 proto tcp all
# udp
pass in quick on hme0 proto udp from 0.0.0.0/32 to 255.255.255.255/32
pass in quick on hme0 proto udp from any to any port = 37
pass in quick on hme0 proto udp from any to any port = 53
pass out quick on hme0 proto udp from any to any keep state
block in log quick on hme0 proto udp all

This ruleset has an obvious problem with active ftp clients (like command
line ftp). Basically, the ftp client opens up a random high numbered
port and communicates this to the ftp server. The ftp server then opens
a connection from it's ftp-data port to the agreed upon high numbered
port on the ftp client. The above configuration of IP filter will not
allow this connection, and the number of ports that would need to be
opened up to allow this to work would be large. It's the job for
an application proxy, which IP filter provides as part of it's NAT
service. The configuration file for NAT to provide this application
proxy follows:
# proxy ftp
map hme0 0/0 -> 0/32 proxy port 21 ftp/tcp
Linux based firewall/NAT

The current (2.2x) linux firewall code is called ipchains. I've used ipchains to implement a NAT box (similar to the box above) and to firewall a computer with one network interface.

A simple firewall

Here is an example that uses ipchains to filter a host with one network interface. The rules are to allow all connections originating on the host itself, and to allow inbound TCP connections on port 22 (ssh) and 113 (ident). Inbound UDP packets originating on port 53 are assumed to be DNS replies and are also allowed.

#!/bin/sh -x
# logging
#LOG=-l

# constants
ANYWHERE=0.0.0.0/0
EXT_IF=eth0

# interfaces
ME=130.191.xxx.yyy/32

# disable forwarding
echo 0 > /proc/sys/net/ipv4/ip_forward

# flush all rules
/sbin/ipchains -F input
/sbin/ipchains -F output
/sbin/ipchains -F forward

# deny all by default
/sbin/ipchains -P input DENY
/sbin/ipchains -P output DENY
/sbin/ipchains -P forward DENY

# accept to/from localhost on lo interface
/sbin/ipchains -A input -j ACCEPT -p all -s localhost -d localhost -i lo $LOG
/sbin/ipchains -A output -j ACCEPT -p all -s localhost -d localhost -i lo $LOG

# already established
/sbin/ipchains -A input -j ACCEPT -p tcp -s $ANYWHERE -d $ME -i $EXT_IF ! -y $LOG

# inbound
/sbin/ipchains -A input -j ACCEPT -p tcp -d $ME 22 -s $ANYWHERE -i $EXT_IF $LOG
/sbin/ipchains -A input -j ACCEPT -p tcp -d $ME 113 -s $ANYWHERE -i $EXT_IF $LOG
/sbin/ipchains -A input -j ACCEPT -p udp -d $ME -s $ANYWHERE 53 -i $EXT_IF $LOG

# outbound
/sbin/ipchains -A output -j ACCEPT -p all -s $ME -d $ANYWHERE -i $EXT_IF $LOG

# icmp
/sbin/ipchains -A input -j ACCEPT -p icmp -s $ANYWHERE -d $ME -i $EXT_IF --icmp-type destination-unreachable $LOG
/sbin/ipchains -A output -j ACCEPT -p icmp -s $ME -d $ANYWHERE -i $EXT_IF --icmp-type destination-unreachable $LOG
A simple NAT plus firewall example

This example does masquerading from an internal class B LAN (192.168.0.0/16) to an external network. All inbound packets destined for the external interface are allowed (there is not much filtering happening here).

#!/bin/sh
#
# rc.firewall ... firewall and masquerade
#
# load modules
/sbin/depmod -a
# masq. ftp
/sbin/modprobe ip_masq_ftp
#
# enable forwarding
echo "1" > /proc/sys/net/ipv4/ip_forward
#
# log ?
#log="-l"
log=""
# 
# IP's
#
# external IF
extip="130.191.xxx.yyy"
extint="eth0"
#
# internal IF/net
intnet="192.168.0.0/16"
intint="eth1"
#
# MASQ timeouts
# 2 hrs for TCP
# 10 sec for traffic after TCP "FIN" received
# 160 sec for UDP
/sbin/ipchains -M -S 7200 10 160
#
# FW and MASQ rules

# input rules
#
/sbin/ipchains -F input
/sbin/ipchains -P input REJECT

# local interface, local hosts, anywhere is valid
/sbin/ipchains -A input -i $intint -s $intnet -d 0.0.0.0/0 -j ACCEPT

# remote interface, claiming to be local, IP spoofing
/sbin/ipchains -A input -i $extint -s $intnet -d 0.0.0.0/0 $log -j REJECT

# remote interface, any source, going to external IP, valid
/sbin/ipchains -A input -i $extint -s 0.0.0.0/0 -d $extip/32 -j ACCEPT

# loopback ... valid
/sbin/ipchains -A input -i lo -s 0.0.0.0/0 -d 0.0.0.0/0 -j ACCEPT

# catch-all, deny and log
/sbin/ipchains -A input -s 0.0.0.0/0 -d 0.0.0.0/0 $log -j REJECT

# output rules
#
/sbin/ipchains -F output
/sbin/ipchains -P output REJECT

# local interface, any source to local net is OK
/sbin/ipchains -A output -i $intint -s 0.0.0.0/0 -d $intnet -j ACCEPT

# outgoing to local net on remote interface deny
/sbin/ipchains -A output -i $extint -s 0.0.0.0/0 -d $intnet $log -j REJECT

# outgoing from local net on remote interface, stuffed masquerading, deny
/sbin/ipchains -A output -i $extint -s $intnet -d 0.0.0.0/0 $log -j REJECT

# remote interface, any source, going to external IP, valid
/sbin/ipchains -A output -i $extint -s $extip/32 -d 0.0.0.0/0 -j ACCEPT

# loopback ... valid
/sbin/ipchains -A output -i lo -s 0.0.0.0/0 -d 0.0.0.0/0 -j ACCEPT

# catch-all, deny and log
/sbin/ipchains -A output -s 0.0.0.0/0 -d 0.0.0.0/0 $log -j REJECT

# forwarding
#
/sbin/ipchains -F forward
/sbin/ipchains -P forward DENY

# masquerade
#
/sbin/ipchains -A forward -i $extint -s $intnet -d 0.0.0.0/0 -j MASQ

# catch-all
/sbin/ipchains -A forward -s 0.0.0.0/0 -d 0.0.0.0/0 $log -j REJECT