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/tcpLinux 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 $LOGA 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