This document is subject to the terms and conditions set forth in the GPL,
or Gnu Public License, a copy of which can be found at
It can be freely distributed in it's entirety as long as this notice
remains intact and the terms of the license are adhered to.
A text version of this HOW-TO is posted here.
This page is documentation and directions to take a standard Linux Distribution
and turn it into a fully functional, Enterprise level router with VPN and NAT
(Network Address Translation) capabilities.
Why do this?
2. How to use this document
Conventions used and assumptions made by the author
3. Hardware info
What to use
How to set up your system for use as a router
4. General Networking info
How to add/ set up more than one NIC
How to ensure that your networking is set up right
5. General Security stuff
Link to CERT.org site
Where to go for Distribution related security updates
6. Actual config of OS as router:
I. Compile the kernel to include the advanced IP stuff...
II. Ensure all necessary packages are installed (iproute2 etc.)
III. Turn on IP Forwarding (2 methods)
IV.Turn off any IPCHAINS filters that are running. <- DANGEROUS!
7. Set up your NAT addresses
I. Define your NAT addresses:
a. Using [ip] - command ref...
II. Setting up your rules and priority levels.
8. Config of router as a firewall/ packet filtering device:
I. IPCHAINS Overview
II. Description of how the system views traffic
a. Outbound Traffic from Internal net
b. Inbound traffic from Internet
9. Config of Firewall as VPN server
I. Linux -> Linux VPN (VPND)
II. Windows -> Linux VPN (PoPToP)
10. IP Command overview
11. Additional Resources
Why do this? The answer in my case was a number of factors, not the least of
which was the cost of a commercial "out of the box" or "all in one" type of
system. A typical system for roughly 100 users was somewhere on the order of
$5,000 - $10,000. Additionally in my experience, the VPN modules to those
NAT/ Masquerade/ Firewall boxes is difficult to set up and administer, and
usually costs extra above and beyond the original purchase price of the system.
Besides, Linux is cool, and is by far the most flexible and adaptable
Operating system that I've had the pleasure to use. Given the choice
between a less flexible and adaptable (and much more expensive) commercial
option and "rolling your own" based on the Linux OS, it was a fairly easy
decision. After doing much research to make sure that all the features
the customer needed, of course!
A further note on building a firewall from "scratch": Obviously, this is a
somewhat involved undertaking. Let me preface your experience with this
observation: This (probably) won't just work for you. Your hardware/
networking environment/ mindset/ yin and yang or whatever won't exactly match
mine. Maybe the sun won't be in perfect alignment when you undertake this
project. Whatever. No matter what, remember that if you're persistent and
methodical, you WILL get it to work; it just might take a little effort.
One last issue: a firewall is a security device. It's designed to keep the
bad guys out and police what the "good guys" can do. Being that we are in
the real word, the "bad guys" are forever coming up with new tricks and
methods to bypass whatever security measures you put in place. To that end,
a firewall is not a "set it and forget it" piece of equipment. It will
require maintenance, and in the case of a "roll your own" system, a fairly
experienced hand at the wheel to ensure that you don't leave yourself
vulnerable to the newest sleaze method.
2. How to use this document:
I've tried to make this document as simple as possible; there aren't a lot of
conventions to follow. Just read carefully and follow the steps provided and
you'll be fine.
I have made a number of assumptions that you should be aware of: I assume
that the reader has a fair to good working knowledge of the Linux OS, and are
comfortable doing fun stuff like Kernel re-compiles etc.. I also assume that
you have a decent background in the basics of TCP/IP networking, and
understand concepts like routing and packet filtering.
If you aren't super comfortable with those concepts, you will probably still
be successful; just be prepared to work for it a little. The biggest single
piece of advice that I can give you is to use the resources available to you;
the Linux Documentation http://www.linuxdoc.org project is a great place
to start any search for more info. Beyond that there are huge numbers of
websites and newsgroups and mailing lists out there where you can get answers
to your questions. For the most part, Linux newsgroups are pretty friendly
places, we're all there to help.
3. Hardware Info:
OK, let's start with the hardware: You'll need a system. I've used a couple
of different platforms- one was an IBM 300GL desktop system (p-166mmx, 64MB
RAM, 4Gb drive, 2 NetGear FA310-tx NIC's. The other (more of a production
type platform) is a standard Intel Desktop board, P-III 650, 128MB RAM, 10Gb
drive, and 1 3Com 3c905c 10/100NIC plus the on board Intel pro 100/plus.
Generally, any PC Based system with a couple of NIC's should work.
A Note: Get your hardware working right before you go one step further!!! I
can't stress this enough- if your hardware is flaky, you'll never know where
to start when things go wrong. If you need a hand getting your hardware to
work, check out the hardware section of the Net HOWTO at
4. General Networking:
Throughout this document, I'm assuming you have at least a decent working
knowledge of Linux and Networking. If you don't have a good understanding
of TCP/IP and network protocols (DNS in particular), you will probably still
be successful in your endeavor, but you should be prepared to muck around
with things a lot as you work.
I use my routers as general network servers: I generally set up things like
VPN's and name service on those systems as well. Be advised that name
service (at least until very recently) was famous for being vulnerable to
hack attempts. On that note, I would strongly recommend that you not allow
Internet traffic to communicate with your DNS Server (block port 53 inbound
to the firewall).
Going forward from this point, I'm making the assumption that you can
communicate with your system (ping it and / or telnet to it) from both the
outside and inside networks, and that things like name service are working
right (you don't have to set up name service on the firewall, but it does
need to be able to resolve names via some other nameserver). If you aren't
sure how to do this, I'll refer you again to the Net HOWTO.
5. General Security Stuff:
As noted above in my reference to DNS and it's vulnerabilities to hack
attempts, there are a HUGE number of "holes" out there that can be
exploited in some way or another. Rather than duplicate efforts by
attempting to list the possible vulnerabilities out there, I'm going to
point you to another useful site: http://www.cert.org. Also check out
the sites of your particular distibution; Redhat has a very usefull page
at http://www.redhat.com/errata that has all sorts of notes and advisories
both security related and otherwise.
6. Config of the System as a router/ Firewall:
First, you need to have a clear picture of what traffic goes where on your
network, and a plan for where it will go when all this is done. I can't
recommend enough to spend the time to create a clear and concise network
diagram (you can use Visio http://www.visio.com, or as more shapes
become available, you could use Dia, an Open Source functional equivalent
I. Re-compile your kernel.
Re-compile your kernel to include a couple of options not included as part
of the stock compile (again, remember I'm coming from the RedHat world;
your kernel config may vary). I generally strip out a lot of stuff I
don't need for a firewall (sound support leaps to mind), and add the
* CONFIG_IP_MULTIPLE_TABLES (AKA Policy Routing)
* CONFIG_IP_ROUTE_NAT (AKA Fast NAT)
Note that there are a few other options that you could include if you so
desire; for more details, go to
http://www.linuxdoc.org/HOWTO/Net-NOWTO/index.html and check the section on
Advanced Networking with Kernel 2.2.
Once you get your kernel recompiled and you've rebooted (yes, you have to do
a reboot- but only this once, and you won't have to do it again *grin*), you
get to start playing with NAT and rules etc..
II. Ensure you have the necessary packages installed.
Make sure you have all the necessary packages installed to manipulate
the newly compiled in Kernel components: You'll need iproute2 (which
is on the RedHat CD, or can be found at http://www.rpmfind.net) and
iputils (same places).
III. Ensure that IP Forwarding is enabled on your system.
There are 2 ways to do this (there is probably more than 2, but I'll
only cover 2 here):
You can add the line FORWARD_IPV4=TRUE in /etc/sysconfig/network, or:
You can put echo "1" > /proc/sys/net/ipv4/ip_forwarding in your
router/ firewall startup file.
IV. Turn off IPChains.
First, can all of your ipchains and set the system to pass all traffic.
This will let us start with a clean slate. Do this by:
ipchains -P input ACCEPT
ipchains -P output ACCEPT
ipchains -P forward ACCEPT
Note: This is EXTREMELY DANGEROUS!!! If your NIC's are configured
properly and you are indeed connected to a live internet feed, you are
WIDE OPEN TO THE ENTIRE WORLD! Let me take this opportunity to recommend
that you DISCONNECT your internet circuit and use a "safe" system hooked
via hub or otherwise for NAT and passthrough testing.
OK, now that I've sufficiently fortified that point, let's proceed.
7. Define your NAT Addresses
I. Each NAT you set up needs 3 steps:
* Tell the system how to deal with packets destined for your NAT'ed
address (Set up the equivelence for INBOUND packets).
SYNTAX: ip route add nat [externalIP] via [internalIP]
* Tell the system what to do with packets from the NATed internal
system that are bound for the Internet.
SYNTAX: ip rule add prio [prio] [internalIP] to [internalNET]
* Tell the router where to store routing information for the NATed
systems connections (Set up the equivalence for OUTBOUND packets).
SYNTAX: ip rule add prio [prio] [internalIP] via [externalIP]
An example network topology:
INTERNET ----| Firewall External NIC Firewall Internal NIC|
: | [123.456.789.012]----+----[172.16.29.2] |
: | [eth0] [eth1]
NAT address of Internal Network
Internal System [172.16.29.0/24]
: NATed System
To add the NAT route, do:
ip route add 123.456.789.125 via 172.16.26.123
ip rule add prio 1000 from 172.16.29.123 to 172.16.29.0/24 table main
ip rule add prio 1001 from 172.16.29.123 nat 123.456.789.125
Note the prio statement; this is a VERY cool feature of the new IP
rules: weighting! Great if you have limited bandwidth (don't we all?)
and want to push things like surfing down the priority scale so that
important things like Napster downloads ;^) can use more!
II. Test it!
At this point, you should be able to ping your NATed address from the
system on the outside. If it's a Unix/linux type system, you should be
able to telnet to it as well (remember, we'll control access later using
IPChains). If you can't, go back through this document and find the step
that didn't work.
8. Configure packet filtering.
I. Here's the 2 second overview of how things work and how the Linux Box views
the world and the traffic it's routing and NATing:
Traffic comes into the "outside" NIC on the firewall/ router. The router
has to evaluate where it came from, where it's going and if it's allowed
to get in. (READ: IPCHAINS Input rules...)
It then has to decide what to do with those packets once they've been
let in; they get forwarded or they get masqueraded, or dumped.
So, you've got packets destined for your external interface that are
bound for an IP other than the systems "real" IP, and you want them to
pop right over the router and be sent to the receiving system "inside"
your internal network.
The way the router sees this set of circumstances is this:
* The packet show up at the external interface with a destination
address that is the Outside "Nat" address of some internal system.
* The router evaluates the destination port and source address for
whether to let it in.
* It then looks to it's internal routing tables for directions on
what to do with the packet; in this case, it is to Forward it to
a system inside specified by the NAT routes it has defined.
* the system inside gets the packet, and (presumeably) sends a
* Once again, the firewall has to decide whether to allow this
traffic that's now knocking on the "inside" interfaces door.
* It allows it to come in,
* Forwards it to the external interface,
* and then re-writes it's source address once again so that the
receiving system knows where to send replies back to.
Sound complicated? It's not really; it (like most things computer) is
quite logical and orderly. It's just that computers are stupid, and
only do exactly what you tell them.
II. IPChains overview
There are 3 types of ipchains rules:
INPUT rules are responsible for allowing packets in to the
firewall system for further processing. If a packet isn't
allowed in, it can't be forwarded or otherwise processed by
OUTPUT rules are responsible for allowing packets out of
FORWARD rules are what allow packets to be passed from one
interface to the other.
Now, the first thing you're going to do to set up your firewall is set a
default policy to reject all traffic. Therefore, every rule you put in
place after that is an exception to the default policy.
Because I'm paranoid, I usually put in a final line that re-iterates the
default policy after all the exceptions as well.
EXAMPLE: Flush all chains and set default policy of REJECT...
ipchains -P input REJECT
ipchains -P output REJECT
ipchains -P forward REJECT
EXAMPLE: Using the diagram above, let's say you want to be able to ping
your firewall's internal NIC from the internal system 172.16.29.123.
To accomplish this, you'll need to enable access from the internal IP
to the firewall.
ipchains -A input -i eth1 -s 172.16.29.123 -d 172.16.29.2 -j ACCEPT
That will allow anything from the internal system into the firewall...
ipchains -A output -i eth1 -s 172.16.29.2 -d 172.16.29.123 -j ACCEPT
That will allow replies to those packets...
Now you should be able to ping the firewall from the internal system.
Now, say you want the internal system to be able to ping some address on
the internet through the firewall.
We already have a rule in place that allows traffic from the internal
system to "talk" to the firewall, so now we have to tell the firewall
what to do with that traffic when it's outbound.
ipchains -A input -i eth0 -p icmp -s 0/0 0 -j ACCEPT
This will allow ping replies from the internet to return.
ipchains -A output -i eth0 -s 123.456.789.012/32 -d 0.0.0.0/0 -j ACCEPT
This allows traffic from the firewall to get out.
ipchains -A forward -i eth0 -s 172.16.29.123 -d 0.0.0.0/0 -j MASQ
Masquerade outbound traffic from the internal system.
A note on what we've done so far: We have been pretty liberal with access
to the firewall from inside. Note, however, that the only traffic that we
allow to come in from the internet is icmp from port 0 on the sender
(which is a ping reply).
9. Config of VPN server
10. An intro to the new IP Commands.
After a long and arduous search for documentation for the IP commands,
I finally found a very fine document by Alexey N Kuznetsov in (of all
places!) the /usr/doc directory on my firewall. Small catch; it is in
PostScript format and copyrighted so I can't include any of it here.
I can, however, tell you where to get it (it really is worth a read if
you're doing anything with the new IP stuff):
Go to /usr/doc/iproute2.x.x (your version).
cat ip-cref.ps | lpr [-P YourPrinterName]
NOTE: This document is 60 pages long!
I would strongly recommend spending some quality time with this document
if you any intention of using the new ip commands for more than what
I've explained in this HOWTO. I don't think I can explain the tools
better that Mr. Kuznetsov already has, so I'll leave well enough alone.
10. Other sources of info:
In my travels, I have come across a number of useful and helpful notes etc.
on this subject. One of particular note was written by Horace J. Pena
. It has a decent overview of some of the non NAT
related ip commands. It can be found at: