A home NAT/Gateway using FreeBSD
Armitage, Dec.29th 2002
This documentation is largely
for my own benefit. With any luck, this information will be useful to others (like
you, if you're reading this page and you aren't me).
A low powered PC (in this case a 450MHz PIII, Dell XPS T450) running
is the NAT/Gateway between my home LAN and my broadband service provider
(in 2002 this was cable internet from Telstra Broadband). FreeBSD makes it
easy to turn almost any old PC into a decent NAT/Gateway. Machines with less
than 32MB of RAM are quite acceptable in this sort of role.
First, you'll need at least two ethernet ports on your machine. In my case the XPS T450 has an onboard 3Com ethernet device and
an additional Intel PCI ethernet card. FreeBSD names these two interfaces
xl0 and fxp0 ('xl' is the driver that handles 3Com cards, 'fxp' handles Intel
cards - these drivers are pre-installed in the default FreeBSD kernel). Assuming FreeBSD 4.6 (or later) is already installed, here are the specific additional configuration steps you'll need:
To /etc/rc.conf add these lines:
This configures xl0 as
the port attached to my broadband ISP service (who use DHCP to assign each customer's network-facing IP address)
and fxp0 as the port attached to my home LAN (a 192.168.0/24 network). Forwarding
and NAT functionality are turned on. There is no need to add an explicit default router, since DHCP's autoconfiguration
of xl0 will install the correct default route out of xl0 towards my ISP.
To /etc/ipnat.rules add these lines:
map xl0 192.168.0.0/24 -> 0.0.0.0/32 portmap tcp/udp 40000:65000
map xl0 192.168.0.0/24 -> 0.0.0.0/32
The rules in /etc/ipnat.rules
cause NAT translation to be applied to packets arriving on fxp0 from my local
LAN that are destined to be forwarded out xl0 (towards the wider Internet).
Specifically, TCP and UDP traffic will have their ports translated up into
the 40000 to 65000 range.
[Despite what I'd read elsewhere, the kernel did not have to be recompiled to enable support for the above NAT functionality.]
Protecting local services
Simply turning on NAT does provide some small amount of protection -
a kind of security-through-obscurity - for machines on your home LAN, but
does not help your NAT gateway itself. If your home gateway machine serves
other purposes (e.g. as your home fileserver on its inside-facing network
interface) you should consider adding firewall and tcpwrapper rules.
For example, inetd's default behavior is to 'wrap' TCP applications according to the tcpwrapper filter rules in /etc/hosts.allow
[see hosts_options(5) man page]. This allows me to customise the host's reaction
to TCP connection requests coming in over xl0 and fxp0.
A simple /etc/hosts.allow might contain:
fingerd: 192.168. : allow
fingerd: ALL \
: twist /bin/echo Sorry %h, you cannot finger me
telnetd: 192.168. : allow
telnetd: ALL \
: twist /bin/echo Sorry %h, you cannot telnet to me
portmap : 192.168.0. : allow
portmap : ALL : deny
ALL : ALL : allow
Finger and telnet requests
from inside my home LAN (192.168/16) are allowed through to the appropriate
daemons on the local machine, while requests from anywhere else are rejected
with an explicit text message response. Requests to the portmapper are silently
blocked unless they come from hosts on my home LAN. All other services are
passed through (in which case they should be disabled in /etc/inetd.conf,
or have their own filtering mechanisms).
rules only protect services launched from inetd or that have tcpwrapper support
compiled into them. Other applications may need to be protected using more sophisticated firewalling functionality of the kernel-resident ipfilter.