A home NAT/Gateway using FreeBSD

Grenville 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 FreeBSD4.6 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 -> portmap tcp/udp 40000:65000
map xl0 ->

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).

NOTE: tcpwrapper 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.