OpenBSD/pf Firewalling
For the Less Gifted
Copyright (C) 2011 by Steve Litt,
All
rights reserved. Material
provided as-is, use at your own risk.
DISCLAIMER
The firewall produced
by these instructions is intended to be moderately defensive, not
extremely secure. Your firewall needs are determined by your setup and
what you have to lose. The firewall described in this document may not
be sufficient for your needs.
There may be mistakes in these instructions, and you might make
mistakes following these instructions, and such mistakes might lead to
penetration of your computer or network, which could lead to personal, business
or financial loss. The author is not responsible for the outcome of
your use of this document: Use at your own risk.
|
Contents
Introduction
Sorry about the disclaimer. It's a sign of the time. Now let's switch from law to technology...
If you're a Ninja network administrator this
document offers you nothing. Just go install OpenBSD, enable port
forwarding, set the Internet facing NIC for DHCP and the LAN facing NIC
for a proper address on the LAN, set up a DHCP server with properly set
DNS servers on the LAN facing NIC, and plug it in. Ellapsed time --
probably an hour -- less if you have some ultra fast way to install
OpenBSD. About the only thing you can get from this document is a way
of explaining firewalling to others.
If you're NOT a
Ninja network administrator, this document is for you. It explains in
step by step detail how to set up an OpenBSD/pf firewall to protect
your LAN, plus it details a two level firewall testing framework for
ultimate safety and protection, plus it explains the concepts of
firewalling so if you later have to improve on the generic firewall
described herein, you'll know just how to do it.
This document is very long,
which may lead you to believe that building an OpenBSD/pf firewall is
hugely complicated and not worth the effort. Such a belief is not
accurate. The reason this document is long is so you understand
everything about this firewall, avoid most dead ends, and if you do hit
a dead end, you know how to get out of it.
But why should you hit dead ends? Simple: mistakes happen. Typos
happen. Things are sometimes forgotten. If you were a Ninja network
administrator you could look at the symptom and know the diagnostic
tests necessary to find the problem. And you'd know which diagnostic
tests are safe and which have the potential to let in network
destroying trouble. If you were a Ninja network administrator, you could
build an OpenBSD/pf using a 15 item checklist and reading between the
lines.
But you're not a Ninja network administrator, so when everything
appears to just stop working, you may experience one of those "what do
I do now" moments, or even an "I give up" moment. This document gives
you ideas how to safely diagnose your way out of problems. The Internet
is full of 15 item checklists for BSD/pf. Some of them are
wrong, and all of them are useless without quite a bit of foundational
knowledge. This document takes little for granted, and tells you all.
If you know the basics of networking, this document gives you a great
opportunity to deploy an OpenBSD/pf firewall.
Which brings up the next question: Why would you want to deploy
OpenBSD/pf? You have many options for firewalling. Walmart or CompUSA
can sell you
a decent dedicated low power firewall appliance for what, fifty bucks?
If you want more configurability, there are seemingly endless Linux and
BSD distributions solely dedicated to firewalling (with the obligatory
router, gateway, DHCP server, port forwarding and NATting duties).
IPCop, IPFire, MOnOwall, PfSense, Smoothwall, and many,
many more.
Most of these options are much easier for an inexperienced person to
install and configure than BSD's PF firewall because they put an
abstraction layer between you and PF, or if it's a Linux distribution
between you and IPTables. That's nice, and I definitely recommend using
one of these for your first firewall, but after a while you'll notice
that for less usual needs such as servers on your network, or OpenVPN,
or many other situations, OpenBSD plus PF is the easier and more direct
way to go. You'll notice that with an OpenBSD/pf firewall, almost
anything is possible.You'll notice that although the other alternatives
hold your hand, OpenBSD/pf is actually the simplest and most direct.
You'll also notice that if you go through this document and its
associated checklist outline, you'll understand firewalling. That means
when a new need comes up, you'll have the knowledge to adapt your
firewall to the need. And it means that you've taken one step closer to
network administrator Ninjahood.
This document comes in three parts:
Part I covers the basics so you can understand the instructions and
have enough foundational knowledge to be able to devise diagnostic
tests if you need to troubleshoot. Part II gives the nitty gritty
details on how to build your OpenBSD/pf firewall/router/gateway, but
with enough details and specificity that you know exactly how to do it. Part III is for reference, later, after you've built your OpenBSD/pf.
PART I: CONCEPTS
Part I consists of the following sections:
The assumptions section tells you what's necessary in order to use this
document. The Vocabulary section is a quick review of terminology
necessary to understand this and other firewalling documents. The
Essential Principles section gives you the foundational knowledge to
understand the procedures you'll perform in Part II.
Assumptions
In writing this document I'm making some assumptions:
- You have a fair knowledge of Linux and computer networking
- You
already have a small wired local area network, behind some sort of
NATting firewall, one single subnet (all the IP addresses are similar),
in one of these ranges:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- You already have a firewall/router
- You're not using Wifi, or if you are it's encrypted and you use
it as just another part of your LAN. In other words, your current
firewall has two zones, the LAN zone and the Internet zone. No DMZ, no
special zone for Wifi.
The assumption about an existing firewall/router has two reasons:
- Your first firewall should be more "user friendly" than OpenBSD/pf.
- An existing firewalled LAN enables you to do the two level
testing and troubleshooting that's essential to keeping badguys off
your LAN, both while you're testing and troubleshooting, and forever
after. Remember that if your OpenBSD/pf machine is compromised during
testing, that compromise could come back to bite your whole LAN days,
weeks, or years later.
All the examples in this document use the following IP address characteristics:
- Existing LAN subnet = 192.168.100.0/24
- Existing firewall/router/gateway IP address = 192.168.100.96
- Existing firewall dhcp server lease range = 192.168.100.240-249
- Newly created test LAN subnet = 192.168.200.0/24
- Newly created test LAN firewall/router/gateway IP address (BSD/pf LAN facing NIC address) = 192.168.200.96
- Newly created LAN's DHCP server lease range = 192.168.200.230-239
I suggest you create a chart of all these values as they exist in this
document, and cross reference them to the same values as they exist on
your existing LAN.
Vocabulary
Before going on it's probably a good idea to lay down some definitions.
As described in this document, your OpenBSD/pf box will simultaneously
act as your LAN's firewall, a gateway, a router, and a DHCP server.
Firewall
|
|
Hardware or software that blocks Ethernet packets deemed likely to be dangerous
|
Router
|
|
A device that forwards Ethernet packets between two networks or subnets
|
Gateway
|
|
Pretty much the same thing as a
router, but the point of reference is different, in that the gateway is
seen from the point of reference of its own network. In other words,
your OpenBSD/pf box will be a router, and specifically it will be the
router that's the gateway to the Internet.
|
DHCP
|
|
Dynamic Host Configuration
Protocol. This is a protocol in which a computer gets its IP address
and maybe quite a few other things assigned to it when it plugs into a
network or wirelessly connects to a Wifi access point. Here's how it
works. The computer has a DHCP client, and one computer on the network
has a DHCP server. When the computer plugs in, its DHCP client sends
out a message saying "what's my IP address and other info?" The
network's DHCP server sends back the IP address it assigns to the
computer, along with possibly other optional information:
- Computer's host name
- Computer's DNS client query addresses (/etc/resolv.conf)
- Computer's default gateway (typically the same as that for the network)
You will configure your OpenBSD/pf box to be the network's DHCP server.
|
Private
IP
space
|
|
Three blocks of IP addresses which are disallowed on the Internet, but allowed to be used, without registration,
|
Internet Assigned Numbers Authority |
|
Also called IANA, this is the
organization that distributes blocks of IP addresses to different
entities (usually larger companies who may re-assign smaller blocks and
individual addresses to others). IP addresses used on the Internet MUST be assigned by IANA.
|
Private
IP
addresses
|
|
These
are three blocks of IP addresses which IANA and everyone else has
agreed can be used privately as long as they are kept off the Internet.
They're called "private" because they can be used only privately within
a company, and not in the "public" Internet. The three address blocks
are:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
|
Public
IP
addresses
|
|
Address assigned by IANA to companies to be used on the Internet.
|
Public/
private
paradox
|
|
"Private" addresses can be use
by anyone and everyone, whereas "public" addresses can be used only by
the company that's been assigned them. Here's how you explain that
apparent paradox: Private addresses are to be used ONLY within the
privacy of their own private network, and NEVER used on the public
network (Internet), whereas public addresses can be used on the public
network (Internet). So the word public or private refers to where
they're being used, not to who's using them.
|
NAT |
|
Network Address Translation. A way to "multiplex" all the private IP
addresses on your LAN onto the address with which you hit the Internet
(the IP address coming out of your cable modem). You'll learn more about NAT in the Essential Principles section of this document. |
|
|
|
|
|
|
Essential Principles
Firewalling, NATting and port forwarding are complex things, so a high
level understanding of these concepts will make the difference between
success and failure building a OpenBSD/pf firewall.
Two NICs, Four Directions
A simple two zone firewall has an
external interface (NIC) going out to the Internet, and an internal
interface (NIC) going out to your local LAN. Did you notice I said
"going out
to" in both cases? That's how the PF firewall looks at everything --
from the perspective of the OpenBSD box, which in this case is a
firewall.
Traditionally the external interface to the Internet is represented by
a variable (macro to be more specific) called $ext_if, while the
internal interface to the local LAN is represented by macro $int_if.
These names are arbitrary -- you could call them $tom and $jerry if you
want, but the standard is $ext_if and $int_if.
Consider the following diagram:
Gaze at the preceding diagram until you understand, in your very soul, that the terms "in" and "out", as used in the pf.conf file, are relative to the BSD/pf firewall, not to the LAN. If you don't understand that intuitively, you'll have a lousy time making your pf.conf file.
So the two NICs are $ext_if and $int_if, and the four directions are:
- In on $int_if
- Out on $int_if
- In on $ext_if
- Out on $ext_if
Keep it Simple, VERY Simple
Firewalls that do Network Address Translation (NAT) and Port Forwarding
are incredibly complex, with numerous and inobvious variables. There's
lots of stuff that can go wrong, and usually does go wrong, and when it
does, it's hard to troubleshoot because diagnostic tests are expensive
in terms of time, setup, and inconvenience to everyone. In a SOHO type
situation, if you take down your current firewall/router to test your
new one, everybody goes offline, and if they're anything like my wife
and kids, they scream bloody murder. If you're in a running small business with employees, it's worse.
So this document walks you through creation of a very simple
firewall/router in the hopes that you can get it operational very
quickly. After that, if you want, you can add one feature at a time,
testing as necessary and putting it back if things screw up.
Here are some of the simplifications this document makes:
- Only two firewall zones: Internet ($ext_if) and LAN ($int_if). No DMZ, no special zone for Wifi.
- Simple pass/block rules:
- Pass everything in from $int_if
- Pass everything out through $int_if
- Pass everything out through $ext_if
- Block everything in from $ext_if
- Pass all IMCP except redirects
It's my belief, at least in my situation, that the preceding pass/block
are reasonably safe, at least as a start. My belief is that adding more
rules before you have a working system can turn this project into a
time sucking tar baby. Once you have a working firewall, you can add
new features one at a time.
What's In and What's Out?
The next point you must understand is that, although TCP and UDP connections are a two way communication, as far as pf.conf is concerned, the direction is governed by the first contact. This is because the PF firewall keeps track of state, so if you query http://www.troubleshooters.com and http://www.troubleshooters.com
sends data back to you, the PF firewalling software has enough smarts
to remember that you asked for Troubleshooters.Com's information and
it's just replying, so PF considers the entire communication as
outgoing from the firewall to http://www.troubleshooters.com. What does NOT happen is the firewall considereing the response to be incoming.
Please remember this. All computer communication goes back and forth.
The factor that determines whether a packet is considered incoming or
outgoing for the purpose of firewalling is not the source and
destination of the packet, but the source and destination of the packet
that initiated the conversation. Without that understanding you're dead
meat!
Let's go through this one more time. You query http://www.troubleshooters.com. PF remembers enough from your initial query that when the response
comes, PF says "oh, I already know this is a response to a known query
going out, so I'll consider it outgoing." PF does this even if your pf.conf
bans all traffic in from the Internet, because it doesn't consider
Troubleshooters.Com's response incoming on the external interface -- it
considers it part of an outgoing conversation on the external
interface. It's vitally important you understand this.
By the way, I know that UDP is stateless, but the PF firewalling
software has ways of "remembering" who sent what and "recognizing" a
UDP response to a sent out query.
Once again, the terms "in" and "out" refer to entire conversations, not to specific responses. It's vital you understand this.
Now let's see how this fits into the "Keep it Simple" philosophy
discussed earlier. Basically, this document assumes your LAN's users
are at least somewhat intelligent and responsible. They don't cruise
the Internet looking for porn, warez, and all the other creeping crud
that installs malware on their computers. They don't use Outlook (you
don't let them use Outlook, do you?) and they don't click on unknown
attachments. Last but not least, because you're reading this on Linux friendly Troubleshooters.Com, there's
an assumption that at least a good portion of your LAN is comprised of
Linux computers rather than virus prone Windows computers. In short,
your users don't go out looking for trouble.
Therefore, we assume that any communications on the LAN itself are OK.
We assume that any communications from your users to the Internet are
OK. The only thing that's not OK are spontaneous communications from
the Internet to your users or firewall -- that's not OK -- why would
anyone have a reason for instituting communication with your LAN or
firewall. This paragraph is why we set the firewall pass/block rules at:
- Pass everything in from $int_if
- Pass everything out through $int_if
- Pass everything out through $ext_if
- Block everything in from $ext_if
Almost always, servers listen for communication, and respond after a
client calls them. Therefore, a good rule of thumb is that
conversations start with a communication from client to server. And typically servers don't try
to reach in and mess with your network -- clients do that. Therefore,
for the most part, the only time you need to restrict outgoing traffic out of the external
interface is one of these two situations:
1) You're hosting servers on your firewall or your LAN and don't want
them sending private or dangerous information to just anybody
2) You don't trust your users not to access dangerous servers
In other words, if you have an FTP server on the LAN, you're darned well going to restrict who can access it.
But more to the point, as computers on your LAN become infected with
viruses, they can acquire dangerous servers. Thus, for instance, a
virus installed keylogger stores info and maintains a server listening
for the badguy to come in on some port or whatever with just the right
query. When that happens, the keylogger sends all your keystrokes.
There go all your passwords, including those to your bank accounts.
You're in trouble.
To combat that, you might implement a rule against traffic out of the
external interface, so the server can't send the stuff out. If your LAN
has the kind of users who download anything and everything, open any
email from anybody, use Outlook Express, and are just plain careless,
you might need to limit their ability to send to the Internet, or more
precisely, their traffic in on the internal interface. You can
recognize them by IP address or other ways.
Network Address Translation (NAT)
In an ideal (or maybe not so ideal) world, every device would have its
own, registered IP address, so any device could contact any other
device. Maybe that will happen when the world moves to the IPV6
addressing standard, but right now most everyone's on the IPV4
addressing standard, which is already nearly out of IP addresses.
Therefore, most homes have only one IP address (usually assigned only
temporarily), and most non-home businesses have either one fixed IP
address, or a small block of them. Bottom line, there are many more
computers than there are possible IP addresses.
But good news. Long ago they saw this problem coming down the pipeline
and created an innovative solution: Private Addressing Spaces. Private
addressing spaces are three blocks of IP addresses that are not
registered with the Internet authorities but instead can be used *INTERNALLY*
by any home or business, as long as such addresses are kept internal
and now allowed to escape onto the Internet. Those three private
address spaces are:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
If you notice, all this document's existing LAN addresses start
with
192.168.100. They're part of the third above listed block of private
addressing
space. This document's "new test LAN" has addresses that start with
192.168.200. Once again, part of the third above listed block of
private addressing space.
OK, so you're sitting here with about twelve computers, each needing to
access the Internet, but with IP addresses that can't go onto the
Internet. They all go through a single IP address assigned your house.
How can that be done?
The answer is Network Address Translation, or NAT, which is done in
the
firewall. Note that in the setup described by this document, the firewall is also the LAN's gateway. NAT is a technique by which
the NAT box changes the private address of the
sending computer to the address of the NAT box's Internet facing NIC,
and changes the source port to an arbitrary high number. These values
and some others are stored in the "Network Address Translation Table"
so that when responses come in, they can be remembered and changed in reverse. See the
following graphic:
In
the preceding graphic, all boxes without background are packets. Those
with background are computers. The computer at 192.168.100.2 sends an
HTTP query to the website at 5.5.5.5. It sends it out the gateway
address 192.168.100.96, where NAT changes its source IP address to the
NAT's Internet facing address, in this case 9.9.9.9, and its source
port to a random unused high port number, in this case 65432. This port
number is recorded in the NAT table so responses can be recognized.
The computer at 5.5.5.5 receives the packet, which it thinks came from
9.9.9.9 at port 65432, and does what it always does, replies to the
packet, switching the source and destination data. So it sends back a
packet whose source address is 5.5.5.5 and source port is 80, to
destination address 9.9.9.9, port 65432. That packet goes to the NAT,
whose software looks up port 65432 in its NAT table to find out that
corresponds to port 39000 on computer 192.168.100.2, and it forwards
the packet there. So the computer at 192.168.100.2 receives the packet
appearing to be from 5.5.5.5 at port 80, and processes it.
Thus, the server
at 5.5.5.5 thinks it's talking directly to 9.9.9.9 port 65432, and has
no idea its responses are being forwarded to 192.168.100.2.
One more thing. It's not symetrical. 192.168.100.2 can initiate a
conversation with to 5.5.5.5, but 5.5.5.5 cannot initiate a
conversation with to 192.168.100.2. The only way for an Internet entity
to initiate a conversation with 192.168.100.2 would be to initiate a
conversation with the firewall (9.9.9.9) at a certain port (let's say
port 22), and have the firewall have a port forwarding rule that forwards the request to 192.168.100.2. Be very careful with port forwarding -- it can backfire on you security wise.
Dual Level Testing: Do It Safely
The "hows" of dual level testing are explained in later sections. This subsection discusses the "whats" and "whys". |
You know what the truly fearless among us would do? After configuring
the OpenBSD/pf box, they'd disconnect their current firewall, take their newly
configured OpenBSD/pf box, plug the Internet facing NIC into their
cable modem, their LAN facing NIC into their Lan, and fire it up. If it
works, great, they've just saved themselves hours of testing and
reconfiguration. If it fails, they can just keep switching things
around til it does, or set the firewall wide open and then just keep
narrowing things until they discover what was blocking them. Carpe
Diem: Seize the Day!
I'm
not that fearless, and I hope you're not either. Because that fearless
fellow has a natural enemy with a Latin slogan of his own: Veni, vidi,
vici: I came, I saw, I conquered. While the courageous commando seizes the day by connecting his LAN to the Internet
through his not-ready-for-prime-time firewall, perhaps for minutes at a
time partially or fully disabling the firewall, an army of thousands of
script-kiddies, crackers, badbots, organized crime cyber profiteers,
and other badguys of every stripe are coming to his firewall, seeing what's there with nmap or other techniques, and conquering
if they find a chink in the firewall's armor. Depending on that chink,
they might be able to compromize any and all machines on the LAN, and
maybe the OpenBSD/pf firewall itself itself. Think about it: if our
hero leaves the firewall up for three minutes with no guard against
incoming ftp and telnet, the attacker can leave a root kit for later
use.
Being compromized is kind of like radiation. You can't see it. You
can't feel it. But it's there, getting you sicker and sicker as time
goes on. Or, maybe like radiation caused cancer, it sits there for
months until all of a sudden makes you violently ill and kills you.
For all these reasons, in this document I espouse dual level testing,
where in the first level your new box's Internet NIC is plugged into
your existing LAN, which is protected by your current firewall. In this
level, which can be called "simulation mode", you can test almost
everything about your new firewall, and troubleshoot it to your hearts
content, including running the thing wide open, and you'll still be as
safe as your current firewall. As an added bonus, when testing in
simulation mode, your LAN stays up so you don't have people yelling at
you to hurry up -- a sure recipe for trouble. Another bonus -- you can
do penetration testing from your LAN through the BSD/pf box to your
test computer without violating anyone's terms of service.
Once it's up and working in simulation mode, you go to the second
level, which is just like running it live except that instead of the
firewall feeding your LAN, it feeds one test machine that contains no
valuable or private data and can easily be reformatted. I call it "live
Internet, test client" mode. Illustrations and simple explanations
follow.
Simulation Mode |
|
Live Internet with Test Computer |
|
|
NOTE: The newly created LAN is physically separate from the existing LAN.
|
Simulation Mode |
|
Live Internet with Test Computer |
The Internet NIC of the pf box
plugs into the existing LAN, gets an address from the existing LAN's
DHCP server, then serves out an address to the test computer on a
different subnet via the pf box's DHCP server. Advantages are:
- No matter what's done to the pf box during testing or troubleshooting, it's as safe as the existing LAN's firewall.
- You needn't take down your existing LAN while doing simulation mode testing, nor kick your LAN's users off the Internet.
- It's easier to simulate Internet badguys from your own LAN
than from the Internet, and you don't have to explain your activites to
the owner of the facility from which you do your penetration testing.
- You don't violate anyone's terms of service (TOS).
- It can be done with just a few changes to pf.conf, hosts, hostname.re0 (or whatever the file extension for the LAN facing NIC), and dhcpd.conf. This will be explained in the next section of this document.
- Once the system's passed the simulation mode level of testing, it's a pretty good bet that if you reverse the changes to pf.conf, hosts, hostname.re0, and dhcpd.conf., it will pass the Live Internet Test Computer mode level of testing immediately.
|
|
After your OpenBSD/pf box passes
all the simulation mode tests, you reverse out the changes you made for
simulation mode, and then run it live against the Internet. This means
you disconnect the current firewall from the cable modem, and instead
connect the WAN facing NIC of the BSD/pf box to the cable modem. You
then connect the test box to the BSD/pf box's LAN facing NIC in order
to simulate the existing LAN without letting any bad stuff onto it.
So, just to be clear, the existing LAN goes on with its life, but without a connection to the Internet. The
new simulated LAN immitates the current LAN, complete with the same
netmask and DNS servers, but the simulated LAN is completely physically
separated from the existing LAN, so they can't interfere with each
other, they can't ping each other, they can't see each other. This is
why, at least for this test, you can't use a DNS server on the existing
LAN. Later, when testing's complete, you can.
The beauty of the test computer is if something is wrong, instead of
getting every machine on your LAN infected, you just infect your test
computer.
|
PART II: PROCEDURES
At the very highest level, here is the process by which you make and deploy your new OpenBSD/pf firewall:
- Build, install and configure your box
- Test and troubleshoot in Simulation Mode with your current LAN connected to the PF box's Internet facing NIC.
- Test and troubleshoot in Live Internet Test Computer Mode with
the PF box's Internet facing NIC connected to the cable modem and the
LAN facing NIC connected to a single test computer.
- Connect the LAN facing NIC to the existing LAN so that now the PF
box has replaced your existing firewall. Watch the logs very carefully
the first couple weeks.
- As time goes on, add and test rules one at a time to increase
security for specifics like careless users and Windows computers, or to
implement additional zones for Wifi or DMZ, or to make redirection
pinholes for incoming SSH, mail server or web server.
Read the preceding to understand the lay of the land. But when you
want an actual roadmap of how to set up an OpenBSD/pf box, use the
following:
The preceding are not only a roadmap, they're also your table of contents for Part II. Read on...
Build the OpenBSD/pf Box
Building the box is straightforward. You need a hard disk at least 1 GB
in capacity. In SOHO environment probably 512K of RAM and a 1GHz
processor are sufficient. In other words, it's probable that anything
new enough to be reliable is good enough for this firewall. You're also
going to need two different NICs. Sometimes the one on the motherboard
can be used, but sometimes OpenBSD won't work with it. So be prepared
with two daughterboard NICs, preferably of a different type so they're
easy to tell apart in config files and physically.
Last but not least, you'll need a case, power supply and the like. If
you're going spend money on this firewall, it makes sense to get a
small, low power computer to save on electricity, space, and noise. If
you're using a computer you have laying around, go for it.
Install the Software
Start by connecting one of the NICs to your current DHCP serving LAN.
Then make yourself an OpenBSD 4.8 install CD. Get the install48.iso
file for your particular platform (i386, amd64, etc) from a nearby
mirror listed at http://openbsd.org/ftp.html. Burn the CD from the ISO
and boot the CD, which walks you through the installation.
For the most part, take the defaults. Add a non-root user, say no
root ssh, and say no to X. meaning all the packages that begin with x,
as well as the games package. Tell the installation that the plugged in
NIC is a DHCP client. If asked, configure the (so far) unused NIC to an
unused address on your LAN's subnet. You can configure it more
accurately later. When asked for the domain, put the domain of your
subnet. When asked for the hostname, put bsdpf or something like
that.
If you find software you need but don't have, you can get it by typing the following command:
pkg_add <software-name>
For instance, you'll probably want the irssi IRC client so you can talk
to people from your BSD box when your regular firewall is down. The
following is a pkg_add session to install it:
# pkg_add irssi
Ambiguous: irssi could be irssi-0.8.15-socks irssi-0.8.15
# pkg_add irssi-0.8.15
irssi-0.8.15: ok
#
As you notice, I got the name wrong and it gave me hints. When your
firewall is about to go live, you probably want to get rid of irssi, so
do this:
pkg_delete irssi
You can find what packages have been installed via pkg_add with this command:
pkg_info
Configure the Box
Before you start configuring there are several things you need to figure out:
- What is your current LAN's subnet?
- What will be your new simulation testing LAN's subnet?
- What will be this firewall's final IP address?
- What will be your new simulation testing mode Firewall IP?
- Which will be your Internet facing NIC (dhcp client)?
- Which will be your LAN facing NIC (hard coded address)?
- What's the device name of your Internet facing NIC?
- What's the device name of your LAN facing NIC?
|
|
A few notes about the preceding.
The simulation testing LAN can be seen in the upper right on the
diagram on the left, labelled "Newly created LAN". Its subnet must not
be the same as the existing LAN, shown at the bottom of the diagram.
The diagram shows the numbers used in the examples of this document.
|
The NIC device names are important because they're used in several config files and as extensions in the hostname.<devicename>
files. Be sure you know which devicename faces the Internet and which
faces the LAN. Remember in the diagram above, the Internet facing NIC
is connected to the current LAN, because the current LAN is simulating
the Internet.
One of the great things about OpenBSD is all configuration is done with files, most of it within the /etc directory. The configuration of your firewall involves these files -- all are in /etc except dhcpd.leases, which isn't even a config file but still must be created:
- /var/db/dhcpd.leases
- hosts
- hostname.<devicename> (for Internet facing NIC)
- hostname.<devicename> (for LAN facing NIC)
- sysctl.conf
- rc.conf.local
- dhcpd.conf
- myname
- dhclient.conf
- pf.conf
Now let's discuss specific changes to these files. All these changes
put the firewall in the live mode. Later we'll change them for the
simulation mode:
/var/db/dhcpd.leases
All you have to do is make sure this file exists, so you use the following command:
touch /var/db/dhcpd.leases
hosts
Add Lines for test and live firewall IP address:
192.168.100.96 bsdpf.domain.cxm bsdpf ## LIVE
#192.168.200.96 bsdpf.domain.cxm bsdpf ## TEST
hostname.<devicename> (for Internet facing NIC)
In this document, the devicename for the Internet facing NIC is rl0, so the filename is hostname.rlo. It's a DHCP client, so the file contains just the following:
dhcp
The way a lot of people do that is just to echo the string in:
echo dhcp > /etc/hostname.rl0
hostname.<devicename> (for LAN facing NIC)
In this document, the devicename for the Internet facing NIC is re0, so the filename is hostname.reo.
It's hard coded to address 192.168.100.96 for live, production service,
but for simulation testing it's hard coded to 192.168.200.96.
Therefore, its contents look like this:
inet 192.168.100.96 255.255.255.0 192.168.100.255 # LIVE
#inet 192.168.200.96 255.255.255.0 192.168.200.255 # TEST
So each line contains these four items in order:
- The interface type, in this case inet
- The IP address of the interface
- The netmask of the interface (255.255.255.0)
- The broadcast address
- Optional comment telling its use so you know which one to uncomment
Be SURE to include the broadcast address. The NIC will silently fail to start if you don't.
sysctl.conf
Back up the file to sysctl.conf.org, and then in sysctl.conf uncomment the line that begins with:
net.inet.ip.forwarding=1
Doing this enables port forwarding.
rc.conf.local
Anything in this file completely overrides what's in rc.conf. In this way, you can leave the fairly long and complex rc.conf alone and just see your changes in rc.conf.local. It's an excellent idea, in my opinion. The rc.conf and rc.conf.local files determine what services boot up. Here's what yours should look like to make an OpenBSD/pf box:
dhcpd_flags="re0"
#dhcpd_flags=NO
The first line declares that you will have a DHCP server on interface re0,
which in this example is the LAN facing NIC. The second line would say,
if it weren't commented out, that there's no DHCP server. If at any
time you want to turn off DHCP serving you can switch the hash sign to
switch which line is commented, and then reboot the box.
Please remember that file /var/db/dhcpd.leases must exist, so make sure it does. If it doesn't, make it with this command:
touch /var/db/dhcpd.leases
dhcpd.conf
Before doing this, one way or another get the IP addresses of two
known good Internet DNS servers. This turns out to be much harder than
you'd imagine, because today most ISPs for some reason don't list their
DNS servers in their support sections. Maybe they figure you're always
using DHCP on everything, or maybe they just don't care. If you can't
quickly find your ISP's DNS server IP addresses, my suggestion would be
to use a "public DNS" as listed in these two documents:
In this example I've used 65.32.5.111 and 65.32.5.112. You'll need to insert these in your option domain-name-servers statement.
First we'll show the contents of the file, and then discuss them:
# $OpenBSD: dhcpd.conf,v 1.2 2008/10/03 11:41:21 sthen Exp $
#
# DHCP server options.
# See dhcpd.conf(5) and dhcpd(8) for more information.
#
option domain-name "domain.cxm";
option domain-name-servers 65.32.5.111, 65.32.5.112;
## LIVE DHCPD SUBNET
subnet 192.168.100.0 netmask 255.255.255.0 {
option routers 192.168.100.96;
range 192.168.100.230 192.168.100.239;
}
## TEST DHCPD SUBNET
subnet 192.168.200.0 netmask 255.255.255.0 {
option routers 192.168.200.96;
range 192.168.200.230 192.168.200.239;
}
You already know from file rc.conf.local
that any DHCP server will be on the LAN facing NIC. This file declares
DHCP services on two subnets: 192.168.100.0/24 and 192.168.200.0/24. In
each case, it serves out DHCP leases between .230 and .239. Notice that
this is a different range from the current firewall, which in this
example serves leases between 240 and 249.
Each subnet serves out a router on its subnet: 192.168.100.96 for live production, and 192.168.200.96 for simulation test mode.
Last but not least are the domain names above both subnet declarations, setting the domain name sent to clients to be domain.cxm and the DNS servers sent to both clients to be 65.32.5.111 and 65.32.5.112.
You'll notice these are not DNS servers on my LAN (there are two boxes
on my LAN with djbdns servers). In testing the LAN isn't available for
DNS service, so what you must do is pass two known good DNS servers.
The best way is to use those documented by your ISP (after testing to
make sure they work).
You don't need to comment or uncomment anything when switching from
live to simulation. This is because in live mode, the LAN facing NIC is
constrained by hostname.re0
(or whatever your config file's extension) to be in the 192.168.100 (or
whatever it is on your LAN) subnet, so the other DHCP subnet never gets
exercised. In simulation mode, the existing LAN indeed has a
192.168.100 subnet, but that never touches the LAN facing NIC, which is
the NIC that is the DHCP server. In simulation mode, hostname.re0 constrains this NIC to the 192.168.200 subnet.
myname
Put in the desired host and domain name. Here's what it looks like in this example:
bsdpf.domain.cxm
dhclient.conf
This file will have a bunch of comments. At the very end, insert two lines like these:
request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers;
require subnet-mask, domain-name-servers, routers;
You can request anything you want, but clients of your OpenBSD/pf box's
DHCP server absolutely must know their domain-name-servers.
pf.conf
This is the big kahuna, the firewall definition. Remember the "Keep It Simple" subsection back in section Essential Principles?
I guarantee you that if you're just an ordinary guy and not a Network
Ninja, trying to throw in every last feature before getting everything
running will frustrate you for days or weeks. Initially make it simple:
NATting, simple packet scrubbing and antispoofing, dropping packets
sent to or from private networks in the Internet (a clear illegality),
dropping packets intended for your LAN's internal private network (the
only way they should be able to see an internal host is via
redirection/forwarding), and the simple philosophy discussed in Keep It Simple:
- Pass all out to the LAN
- Pass all in from the LAN
- Pass all out to the Internet
- Block all in from the Internet
One other principle you should know is that in the pf.conf
file, when two rules contradict, the later one determines. So I
implemented the simple "all open except in from the Net" this way:
block log all
pass on $int_if all
pass out on $ext_if all
The first line allows in all traffic on all interfaces. The third contradicts it for the purpose of $ext_if, the Internet facing NIC, blocking all incoming traffic from that interface.
However, you can override the "last rule takes precidence" technology with the use of the quick keyword. If, going down the rules, you match a quick rule, then all further rules are disregarded.
The following is the contents of the pf.conf file when set up live direct to the Internet. It will be explained later:
# STEVE LITT'S ULTRASIMPLE pf.conf
# MACROS
ext_if="rl0"
int_if="re0"
lan_ip="192.168.100.0/24"
private_networks="{ 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 255.255.255.255/32, 127.0.0.0/8 }"
# SCRUB PACKETS
match in all scrub (no-df)
match out all scrub (random-id)
# SET UP NAT: 4.8 SYNTAX
match out on $ext_if from $lan_ip nat-to ($ext_if) #LIVE
#match out on $ext_if from !($ext_if) nat-to ($ext_if) #TEST
# IPV6 CURRENTLY IRRELEVANT, DROP IT **QUICK**
block drop in quick inet6
# ANTISPOOF **QUICK**
antispoof log quick for { $ext_if } inet
# DEFAULT IS BLOCK IN FROM INTERNET, PASS ALL ELSE
block log all
pass on $int_if all
pass out on $ext_if all
# SKIP LOOPBACK
set skip on lo0
# ALLOW ALL ICMP EXCEPT REDIRECTS
pass in inet proto icmp all
block in log on $ext_if inet proto icmp all icmp-type redir
# BLOCK THE OBVIOUSLY BOGUS **QUICK**
#block in quick log on $ext_if from any to 192.168.200.0/24 #TEST
block in quick log on $ext_if from no-route to any
block in quick log on $ext_if from any to 255.255.255.255
block in quick log on $ext_if from any to $private_networks
block in quick log on $ext_if from $private_networks to any
block return out quick log on $ext_if from any to $private_networks
# COMMENT OUT THE PRECEDING 3 LINES WHEN TESTING THE INTERNET FACING
# NIC ON THE LAN IN ORDER TO SIMULATE THE INTERNET,
# UNCOMMENT THEM FOR LIVE PRODUCTION
# ALLOW INTERNET QUERIES TO FIREWALL'S SAFE INTENTIONAL SERVERS
#pass in on $ext_if proto tcp from any to any port {22}
I'm going to pretend that all of the preceding is self explanetory
until the part about NATting. The problem with NATting is its syntax
changed recently. The syntax above is for OpenBSD 4.8. The syntax I
marked as "Test" will work in live production situations, but the one
marked "Live" is a little more restrictive, so that's better for live.
But for testing, the live one would fail to transfer.
The next thing needing explanation is the part about defaults for TCP
and UDP. I defaulted the firewall to block in from Internet, pass
everything else. For IMCP, I set it to pass everything except redirects.
Now look at the part labelled "block the obviously bogus". The first of
those lines is used only in simulation testing, to prevent someone from
setting up a route from 192.168.100.2 to, let's say, 192.168.200.230
though 192.168.100.249. Without that line, from the existing LAN, I can
have my way with the test computer -- the equivalent of putting a
Windows computer on the Internet with no firewall at all. What could possibly go wrong?
Look at the last three lines of the "obviously bogus" section. The
first of those three block rules prevents anything from the Internet
trying to access your private networks. In live mode this does
everything discussed in the preceding paragraph, but in simulation mode
it doesn't work because the firewall's Internet facing NIC has a
private address, so it has to be commented out. That's why in
simulation mode you need the rule preventing the outside from reaching
into your LAN and accessing 192.168.200.0/24 -- to substitute for the
more inclusive rule that blocks reaching in for ANY private address.
For the same reason, the second of those lines must be commented out.
Any packet on the Internet purporting itself to be from a private
address is no good. But of course in simulation mode everything coming
in is from your LAN and must be commented out.
Same with the third of those three lines. It's there to prevent
something on your LAN from reaching out to a private address on the
Internet. And like the other two, it must be commented out for
simulation test mode.
The pf.conf given in this
section is for live use, as is everything in this section. But before
doing any live testing, you need to do simulation testing, and to do
that you need to make some changes to several of these files. Read on...
Do Simulation Mode Testing
Simulation Mode
|
|
|
|
|
Simulation mode is as safe as
the existing firewall, which of course we all hope is safe indeed. You
have to plug the new BSD/pf machine's Internet facing NIC into a hub or
switch on the existing, firewall protected LAN. Changes are made so the
LAN facing NIC outputs on a different subnet, 192.168.200.0/24 in the
illustration.
Then you begin your tests, with your existing LAN acting as the Internet and the test machine acting as your future LAN.
|
To accommodate simulation mode, the following changes must be made to files in the /etc directory:
- Change hosts file so
the LAN facing NIC is now in the 192.168.200
subnet, rather than existing LAN's 192.168.100. In this example, this
NIC
would now be addressed at 192.168.200.96. You can do this just by
moving the comment character (the hash) from the test line to the live
line.
- Change the hostname.re0, or whatever the name of the LAN facing
NIC is, to reflect the same IP address (192.168.200.96 in this example). Change the broadcast address on
that line so it's in the new subnet. Once again, just move the comment symbol.
- In pf.conf, do the following:
- Uncomment the test NAT rule and comment out the live one. The NAT rules all start with match out on $ext_if.
- In the section blocking obviously bogus Internet packets,
comment out the bottom three of the six, the ones that contain $private_networks and refer to private
address blocks on the Internet. In fact, when you test using the
existing LAN as an Internet simulation, all external packets WILL be in
the 192.168.100.0/255 subnet -- a private network.
- In the section blocking obviously bogus Internet packets,
uncomment the first rule -- the one preventing reaching in to
192.168.200.0/24. This is to compensate for the three you commented out.
- At the bottom, uncomment the pass command for port 22.
- Reboot the BSD machine. If you need to keep rebooting in order to troubleshoot, you can
probably use the following sequence of commands to restart the necessary things:
- sh /etc/netstart
- dhcpd
- pfctl -f /etc/pf.conf
- By the way, if any of these produce errors, investigate. If the
pfctl command produces errors, it means that pf.conf didn't compile and
you now have no firewall. This is why the 2 level testing is so
important.
Now
that you have the BSD box configured for simulation testing, perform
your simulation tests. They are very thorough because hopefully, if you
pass all the simulation tests, you'll easily pass the live internet
test computer tests with flying colors. Most of the simulation tests
are performed without using the test box because they don't test NAT or
DHCD server. Those not using the test box follow:
- From the BSD box, use ifconfig
to confirm that your LAN facing NIC is where you
just set it, in the separate subnet from the existing LAN, e.g.
192.168.200.96, and your Internet facing NIC has an IP address from
your existing LAN's DHPC server. If the LAN facing NIC DOES NOT have an
IP address, check to make sure you put broadcast addresses in each of
the two lines of the hostname file for the LAN facing NIC, and if not
put them in and restart the network with sh /etc/netstart. If still no joy, try this command and look for error messages:
sh /etc/netstart re0 up
Obviously you'll substitute your LAN facing NIC's device name for re0.
- From the BSD box, ping (by IP address) a box (that can normally
respond to ping) on your existing LAN. The ping should go through your
Internet facing NIC, which in this case is attached physically and by
IP address subnet to your existing network. If the ping fails, make
sure your Internet facing NIC is configured in your LAN's subnet, make
sure your Internet facing NIC is not configured to the same IP address
as something else on the LAN, and make sure your LAN facing NIC is now
configured to an address outside
the LAN's subnet, because two NICs on the same subnet in the same box
can cause problems. If all the preceding are correct, check your pf.conf settings for something that might be blocking IMCP packets. Once you can ping from the BSD box to a box on the LAN, continue.
- From a box on your current LAN, test the firewall's ability to resist private addresses from the outside by doing the following:
- route add -net 192.168.200.0/24 gw 192.168.100.249
- route
- Look for a route with destination 192.168.200.0 and gateway 192.168.100.249
- ping 192.168.200.230
- If the ping succeeds, this is very bad and you need to screen it out from your "BOGUS" ruleset.
- From a box on your current LAN, ping www.troubleshooters.com. It
should ping correctly, or else there's something wrong with your
current LAN or current firewall and you must fix that before going
further. If it continues not to ping, disconnect the BSD box from the
LAN and see if it changes the symptom. Once you can ping
www.troubleshooters.com from a box on your LAN, write down the IP address the ping command gives you for www.troubleshooters.com.
- From the BSD box, ping the **IP Address** of
www.troubleshooters.com, as learned in the preceding step. If the
numeric ping fails, make sure you made all the changes to pf.conf described earlier.
Make sure the LAN facing NIC is not set to the same subnet as the LAN,
because that can cause problems including failure to ping. Troubleshoot
as necessary.
- From
the BSD box, ping www.troubleshooters.com by name. It should ping
normally. If it doesn't, and it pinged correctly by IP address,
you have a DNS problem. Use the dig command, look at /etc/resolv.conf for the DNS server IP's, and look at what the BSD box's DHCP client is doing. Troubleshoot as necessary.
- From the BSD box, lynx http://www.troubleshooters.com. It should pull up
Troubleshooters.Com in the Lynx text browser. If it doesn't, look again
at your pf.conf. If Lynx doesn't run, you can install it with the
following command:
- pkg_add lynx
- Follow the instructions from there.
- You can move around the web page with the arrow keys. To quit Lynx, press q twice.
- Remembering the DHCP provided address of the Internet facing NIC, which you got from the ifconfig command, from a Linux machine on the existing LAN,
ssh into the BSD machine username root, and be sure to
use your root password for the BSD box(not your personal account password and not your password on
other machines). Verify ssh
FAILS to into the BSD machine because you shut off root access to the
BSD/pf's ssh server. The message, after you put in the correct
password, should be something like "Permission denied, please try
again, even though you know it's the right password." If you CAN ssh
in,and run pfctl -f /etc/pf.conf.<TODO>
- Remembering the DHCP provided address of the Internet facing NIC, which you got from the ifconfig command, from a Linux machine on the existing LAN,
ssh into the BSD machine using your username (not root), and be sure to
use your password for the BSD box(not root's and not your password on
other machines). Verify you can ssh into the BSD machine. If not make
sure you uncommented the two port 22 pass rule in pf.conf, and if not, uncomment it and run pfctl -f /etc/pf.conf.
- Remembering the DHCP provided address of the Internet facing NIC, which you got from the ifconfig command, from a Linux machine on your current LAN, run the following penetration tests, as root, against your new firewall:
- nmap -sT -p 1-65535 192.168.100.249 | tee penetration.tcp
- nmap -sU -p 1-65535 192.168.100.249 | tee penetration.udp
- NOTE:
RUN THESE AS ROOTIf these commands aren't run as root, they'll silently give less
infomation, possibly leading you to conclude everything's OK when it
isn't.
- NOTE: The latter command (-sU) will take a long time to run. It took
20 minutes on my computer. It's probably acceptable to save time by not running the latter command.
- The -sT command should show port 22 (ssh) to be open.
- Now comment out the port 22 pass pf.conf line you previously uncommented, reset PF with the pf -f /etc/pf.conf command, and retry sshing into the BSD box and the two penetration tests. You should now note that you cannot ssh in, and the penetration tests will not find port 22 open.
IF YOU GOT THIS FAR, your BSD machine's firewall and DHCP client are
working correctly. Now it's time to test the BSD machine's NAT
capabilities and DHCP server, using a test machine.
- Plug the test computer into the LAN facing NIC of your BSD
machine, make sure the test machine is set to receive its IP address
from DHCP (make it a DHCP client), erase its current /etc/resolv.conf (on the test box, not on the BSD box), and reboot the test box.
- On the test box, run ifconfig
to verify that it got an IP address in the new LAN's subnet, which in
this example is 192.168.200.0/24. The IP address should be in the range
of the BSD box's DHCP server lease range. In this example the test box got an address of 192.168.200.230.
- On the test box, ssh into the BSD/pf box's LAN facing NIC, which
in this example is 192.168.200.96. If ssh doesn't log in, check your
pf.conf that $int_if is wide open, and check all IP addresses.
- On the test box, ping the IP address you earlier wrote down for www.troubleshooters.com. If
the ping doesn't work, look at the IP addresses for the test box and
the LAN facing NIC of the BSD/pf box. Re-confirm that you can still
ping www.troubleshooters.com's IP address from the BSD/pf box, and if
not, troubleshoot that problem.
- On the test box, once you can ping www.troubleshooters.com by IP
address, ping it by name. If it fails by name but succeeded by IP
address, you have a DNS problem. Your very first move should be to
erase the test box's /etc/resolv.conf file and restart the test box's network. Many times that fixes this problem. If not, look at what's in the test box's /etc/resolv.conf and use the dig program to see whether the DNS server IP(s) listed in /etc/resolv.conf are work. If they don't work on the test box, see whether they work on the BSD box. If not, change your /etc/dhcpd.conf file to pass different DNS servers. If none of these steps help, perhaps there's something in the firewall
blocking you, or both your BSD box's NICs are in the same subnet (all bets
are off if that happens), or there's something else wierd. Troubleshoot
as necessary.
- On the test box's web browser, browse to
http://www.troubleshooters.com and verify you can surf the Internet. If
not, perhaps something's blocking port 80 on your BSD/pf box's /etc/pf.conf or else perhaps a firewall on the test box is stopping you.
IF YOU GOT THIS FAR, your OpenBSD/pf machine's NAT and DHCP server are
functioning correctly. Next, for extra credit, and even though I said
port redirection was beyond the scope of this document, let's do a
quick port redirection exercise.
Extra Credit: Port Redirection Exercise
Don't do this until the simulation mode tests all passed. Now, with /etc/pf.conf just the way you left it, add this one line to the bottom of /etc/pf.conf:
pass in on $ext_if proto tcp from any to $ext_if port 22 rdr-to 192.168.200.230 port 22
In the preceding command, substitute your test box's IP address for the
192.168.200.230. What the preceding command says is that if any TCP
packet with destination port 22 comes in from the Internet facing NIC,
redirect it to port 22 on the test machine's IP address.
Now, on the BSD/pf box, reset PF with this command:
pfctl -f /etc/pf.conf
Make sure you have a non-root login on the test machine, and if not, make one.
From a Linux machine on the existing LAN,
ssh into the IP address
of your BSD/pf machine's Internet facing NIC. In this example it would be 192.168.100.249. This address was provided
by your existing LAN's DHCP server. If you remember, you ssh'ed into it
a few tests ago. But this time, when asked for the username, put your
username on the test machine. Same with the password. If the stars are
smiling on you, you'll be logged into your test machine, meaning you penetrated into the other side of the NAT (use uname -a to verify).
But another likely result is that you'll get an error something like this well known problem:
root@mydesk:~# ssh slitt@192.168.100.249
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
07:9b:b9:27:58:87:49:8c:54:80:3b:98:06:47:3e:de.
Please contact your system administrator.
Add correct host key in /root/.ssh/known_hosts to get rid of this message.
Offending key in /root/.ssh/known_hosts:7
RSA host key for 192.168.100.249 has changed and you have requested strict checking.
Host key verification failed.
root@mydesk:~#
Here's what this error means. Your .ssh/known_hosts file has the credentials of your BSD/pf box from the last time you sshed
into it. But now when you ssh into that same IP address, you're
actually sshing into the test machine so you get the test machine's
credentials, which don't match what's stored, so of course your client
thinks someone's trying a man in the middle attack even though you know
better. So here's what you do, on the machine from which you're trying to ssh, to get past this:
- ssh-keygen -H -F 192.168.100.249 to see the auth data for that IP address
- Copy to clipboard at least twenty characters from the output
- Edit $HOME/.ssh/known hosts
- Search for the string you copied to clipboard, and make sure it happens only once in known_hosts.
- If it occurs only once, delete that record (dd in Vim). If it occurs more than once, investigate.
- Save the file and exit the editor
Now when you try the ssh command it should work. Once you get in, do a uname -a command to verify you're really on the experimental computer. If so, you've done port forwarding. If not, troubleshoot.
Now put the file back the way it was. Delete the line you just put on the bottom of pf.conf., and restart PF with pfctl -f /etc/pf.conf. Note that if you now try to ssh back in you'll get the same known_hosts error and have to solve it the same way.
So Far So Good
You're almost done. You created a firewall, connected it to your
existing LAN to simulate the Internet, and proved it could do
firewalling, NAT, DHCP server to a new LAN, and redirection/port
forwarding. Now, by undoing the changes made in order to do the
simulation testing, you can connect this firewall directly to the
Internet (through your cable modem or whatever), test briefly with your
test box representing the LAN, and then connect the LAN where the test
box was, and let your OpenBSD/pf box begin its daily duty as your
firewall.
Warning:
Do NOT yet rewire things so your OpenBSD/pf is plugged into your cable
modem. If you were to do that before reworking all files to get back
into live mode, a script kiddie might come in and own you.
Do Live Internet, Test Computer Mode Testing
WARNING
Do not wire the OpenBSD/pf box into the cable modem until told to do
so. Wiring it in early can allow a badguy to come in and own your
computer!
|
|
|
The diagram at the left
describes the Live Internet, Test Computer mode of testing, except that
the test computer plugs right into the LAN facing NIC of the BSD/pf.
Before you do anything else, you first have to reset everything back to its original "live" settings. Read on... |
Reconfigure for Live Internet, Test Computer
- Change hosts file so
the LAN facing NIC is back in the 192.168.100
subnet. In this example, this
NIC
would now be addressed at 192.168.100.96. You can do this just by
moving the comment character (the hash) from the live line to the test
line.
- Change the hostname.re0, or whatever the name of the LAN facing
NIC is, to reflect the same IP address (192.168.100.96 in this example). Change the broadcast address on
that line so it's in the same subnet (192.168.100.0/24 in this example). Once again, just move the comment symbol.
- In pf.conf, do the following:
- Uncomment the live NAT rule and comment out the test one. The NAT rules all start with match out on $ext_if.
- In the section blocking obviously bogus Internet packets,
uncomment the bottom three of the six, the ones that contain $private_networks and refer to private
address blocks on the Internet.
- In the section blocking obviously bogus Internet packets, comment out the first rule -- the one preventing reaching in to
192.168.200.0/24. This is no longer necessary because the rule barring reaching in for a private address does this and more.
- At the bottom, make sure you've deleted the ssh redirection rule that contains "rdr-to".
- At the bottom, comment the pass command for port 22.
- MAKE DOUBLY, TRIPLY, QUADRUPLY sure you've done all these reconfigurations right.
- When satisfied that you've correctly completed the reconfiguration, shut down both your OpenBSD/pf box and your test machine.
Test the New Configuration
If you haven't done so, make sure your configuration is correct as described in the preceding subsection. Now rewire everything:
- Shut down and power down your existing firewall.
- When the existing firewall is powered down, power down your cable modem.
- Unplug your existing firewall from both the cable modem and the existing LAN. Move it out of the way.
- Connect the Internet facing NIC of your BSD/pf box to your cable modem. DO NOT connect its LAN facing NIC to the LAN.
- Connect your BSD/pf's LAN facing NIC to your test machine.
- Power up the cable modem. Wait at least a minute for its boot to
complete. Depending on the modem type, you might be able to tell by its
panel lights when it's fully booted.
- Power up the BSD/pf machine.
Now you're ready to begin testing. Log in as root.
- ifconfig. The results should show your LAN facing NIC to be
on
your existing LAN's subnet, and your Internet facing NIC should have an
Internet based (not private) based IP address. If not, make sure you
completely changed back all the files to LIVE mode. Be sure your
dhclient.conf file is correct.Try downing and upping the firewall and
modem again to see if that makes a difference. Troubleshoot as
necessary.
- ping the IP address of Troubleshooters.Com, which you found and
wrote down earlier in this document. If you can't ping it, troubleshoot.
- ping by name www.troubleshooters.com. If it fails but you could
ping the IP address, you have a DNS problem. Try looking at your /etc/resolv.conf, then deleting it, and then performing the sh /etc/netstart command in order to restart your network, and see if the contents of /etc/resolv.conf are any different, or whether the DHCP client even made it. Troubleshoot as necessary.
- Use the lynx text browser to pull up http://www.troubleshooters.com on the BSD/pf box. This proves you can get out on port 80.
- If possible, from another computer, try to ssh
into your BSD/pf firewall. It should fail because you have no pass
command for port 22. Then uncomment the pass command, restart PF with pfctl -f /etc/pf.conf, and now you SHOULD be able to ssh in. Once you've proven you can toggle the sshability of your box with that one line of pf.conf, leave it commented to prevent brute force attacks via ssh. You can still ssh in from the LAN facing NIC.
- Do not try penetration tests from the outside unless you get
permission -- conducting such penetration tests from the Internet are
very likely a serious breach of terms of service.
Now you've proven to a reasonable degree (the best you can do without
penetration tests) that the BSD/pf box's DHCP client and firewall work
properly. Now it's time to test NAT and DHCPD server.
- If it isn't yet, connect the test machine to the BSD/pf machine's LAN facing NIC.
- Power up the test machine.
- Log into the test machine as root, and perform an ifconfig
command. It should show an IP address in the same subnet as the
BSD/pf's LAN facing NIC, in the BSD/pf's DHCP server's lease range. If
not, on the test machine, bring the network down and up again and see
if that helps. If not, try rebooting the test machine. If that doesn't
help, troubleshoot.
- On the test machine, ping the IP address for www.troubleshooters.com. It should ping. If not, troubleshoot.
- On the test machine, ping www.troubleshooters.com. If it doesn't ping, you have a DNS problem. Try deleting the test machine's /etc/resolv.conf,
restart the test machine's network, and see if that fixes the problem.
If not, take a good look at the DNS server IP addresses the BSD/pf
machine's /etc/dhcpd.conf file is passing, and make sure they're legitimate DNS servers. Troubleshoot accordingly.
- On the test machine, open a browser and pull up web page http://www.troubleshooters.com. It should come up, thereby proving your ability to go out port 80.
Use As a Real Firewall
If all your tests worked with the BSD/pf hooked directly to the
Internet, the next step is to start using your new OpenBSD/pf firewall
as it was intended, sitting between the Internet and your LAN. So
unplug your LAN facing NIC from the test machine and plug it into a
switch port on your LAN, and start using your new firewall.
As time goes on and you need to further refine your firewall, keep in mind all the principles you've learned in this document.
PART III: REFERENCE
Part III is a quick reference for after you've built your firewall and want to change it. It consists of the following sections:
Files
This section contains listings of the relevant files. Note that in all these files, re0 is the NIC facing the LAN, rl0 is the
NIC facing the Internet, the LAN is in subnet 192.168.100.0/24, and the
test subnet is 192.168.200.0/24. You'll need to change these to fit
your own situation.
Filename
|
Description
|
Contents
|
rc.conf.local |
Everything in this file overrides rc.conf. This is where you enable or disable services, or give information about services.
The file on the right enables a DHCP server on re0, the LAN facing NIC.
You can switch the comment to disable the DHCP server if needed, and
you can uncomment the pf line to disable pf for diagnostic tests. Note
that if you disable pf and connect directly to the Internet, you've
just compromised your OpenBSD/pf box and really should reformat it,
along with anything that was connected to it.
|
dhcpd_flags="re0"
#dhcpd_flags=NO
#pf=NO |
sysctl.conf |
This is where you enable port forwarding. To enable port forwarding, just uncomment the line that looks like:
#net.inet.ip.forwarding=1
|
|
|
|
|
myname |
The BSD box's hostname
|
bsdpf.domain.cxm
|
hosts |
Quick internal name resolution
|
click
|
hostname.rl0 |
The NIC config for the Internet facing NIC, a DHCP client. Note that in your case the file extension will probably be different. NICs are named by manufacturer and order, so every computer has different names for their NICs. |
dhcp
|
hostname.re0
|
The NIC config for the LAN
facing NIC, hard wired to an IP address. To implement a hard wired
config, the line starts with the word "inet", then the IP address of
the NIC, then the netmask of the NIC, and finally the broadcast IP
address for the NIC. Note
that in your case the file extension will probably be different. NICs
are named by manufacturer and order, so every computer has different
names for their NICs.
|
Click
|
dhclient.conf |
This defines what information a
DHCP client acquires from its server. In this case the DHCP client is
attached to the Internet facing NIC, and the DHCP server is at your ISP.
|
Click
|
dhcpd.conf |
This
defines what information a DHCP server sends to its clients. In this
case the DHCP server is attached to the LAN facing NIC. For
each subnet served, it defines the range of IP addresses it can lease
out. It enables the DHCP server to give each of its clients DNS
servers. In this case, at least during testing, it's best to give out
the DNS servers that the Internet facing NIC got from its DHCP server. It can also give the clients a domain name, which in this case is set to "domain.cxm".
To facilitate testing in which the current LAN simulates the Internet,
a testing config is added, and need not be commented out unless you
really intend to have a LAN at that subnet. The 192.168.200.0/24 subnet
is for testing. It can only serve out addresses if the BSD box's LAN
facing NIC is at an address in that subnet, so basically when you
switch the LAN facing NIC, you switch the DHCP setup along with it,
without commenting anything in dhcpd.conf.
|
Click
|
resolv.conf |
For the purposes of the BSD box, this should be controlled by the WAN facing NIC's DHCP server.
|
search domain.cxm
nameserver 192.168.100.96
|
pf.conf |
This covers the firewall rules, the NAT, and any redirections (beyond the scope of this article).
Note there are several pairs of lines labelled LIVE and TEST, in most
cases corresponding to whether the Internet facing NIC connects
to the LAN as a simulation test, or directly to the Internet for
testing live operation or to function in a live environment.
|
Click
|
ssh (directory, make sure no bogus known hosts) |
Contains files related to SSH.
Be careful that nothing in here, perhaps put in during diagnostic
tests, can compromise your system.
|
|
/etc/hosts
|
# $OpenBSD: hosts,v 1.12 2009/03/10 00:42:13 deraadt Exp $
#
# Host Database
#
# RFC 1918 specifies that these networks are "internal".
# 10.0.0.0 10.255.255.255
# 172.16.0.0 172.31.255.255
# 192.168.0.0 192.168.255.255
#
127.0.0.1 localhost
::1 localhost
#192.168.100.96 bsdpf.domain.cxm bsdpf ## LIVE
192.168.200.96 bsdpf.domain.cxm bsdpf ## TEST
|
|
/etc/hostname.re0
|
inet 192.168.100.96 255.255.255.0 192.168.100.255 # LIVE
#inet 192.168.200.96 255.255.255.0 192.168.200.255 # TEST
|
/etc/dhclient.conf
|
# $OpenBSD: dhclient.conf,v 1.1 1998/09/08 20:26:41 marc Exp $
#
# DHCP Client Configuration
#
# See dhclient.conf(5) for possible contents of this file.
# When empty default values are used:
#
# Example:
#
# send dhcp-lease-time 3600;
# send host-name "myhost";
# supersede host-name "myhost";
# supersede domain-name "my.domain";
# request subnet-mask, broadcast-address, time-offset, routers,
# domain-name, domain-name-servers, host-name, lpr-servers, ntp-servers;
# require subnet-mask, domain-name-servers, routers;
# media "link0 link1", "link0 link1", "link0 link1", "-link0 link1";
request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers;
require subnet-mask, domain-name-servers, routers;
#
|
/etc/dhcpd.conf
|
# $OpenBSD: dhcpd.conf,v 1.2 2008/10/03 11:41:21 sthen Exp $
#
# DHCP server options.
# See dhcpd.conf(5) and dhcpd(8) for more information.
#
option domain-name "domain.cxm";
option domain-name-servers 65.32.5.111, 65.32.5.112;
## LIVE DHCPD SUBNET
subnet 192.168.100.0 netmask 255.255.255.0 {
option routers 192.168.100.96;
range 192.168.100.230 192.168.100.239;
}
## TEST DHCPD SUBNET
subnet 192.168.200.0 netmask 255.255.255.0 {
option routers 192.168.200.96;
range 192.168.200.230 192.168.200.239;
}
|
NOTE: For the option domain-name-servers
line, use two known good Internet DNS servers, probably those given you
by your ISP. If you have a trusted DNS server on your LAN, after your
firewall goes live you can change this line to include any trusted DNS
servers on your LAN. |
/etc/pf.conf for LIVE use and LIVE testing
|
# STEVE LITT'S ULTRASIMPLE pf.conf
# MACROS
ext_if="rl0"
int_if="re0"
lan_ip="192.168.100.0/24"
private_networks="{ 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 255.255.255.255/32, 127.0.0.0/8 }"
# SCRUB PACKETS
match in all scrub (no-df)
match out all scrub (random-id)
# SET UP NAT: 4.8 SYNTAX
match out on $ext_if from $lan_ip nat-to ($ext_if) #LIVE
#match out on $ext_if from !($ext_if) nat-to ($ext_if) #TEST
# IPV6 CURRENTLY IRRELEVANT, DROP IT **QUICK**
block drop in quick inet6
# ANTISPOOF **QUICK**
antispoof log quick for { $ext_if } inet
# DEFAULT IS BLOCK IN FROM INTERNET, PASS ALL ELSE block log all
pass on $int_if all
pass out on $ext_if all
# SKIP LOOPBACK
set skip on lo0
# ALLOW ALL ICMP EXCEPT REDIRECTS
pass in inet proto icmp all
block in log on $ext_if inet proto icmp all icmp-type redir
# BLOCK THE OBVIOUSLY BOGUS **QUICK**
#block in quick log on $ext_if from any to 192.168.200.0/24 #TEST
block in quick log on $ext_if from no-route to any
block in quick log on $ext_if from any to 255.255.255.255
block in quick log on $ext_if from any to $private_networks
block in quick log on $ext_if from $private_networks to any
block return out quick log on $ext_if from any to $private_networks
# COMMENT OUT THE PRECEDING 3 LINES WHEN TESTING THE INTERNET FACING
# NIC ON THE LAN IN ORDER TO SIMULATE THE INTERNET,
# UNCOMMENT THEM FOR LIVE PRODUCTION
# ALLOW INTERNET QUERIES TO FIREWALL'S SAFE INTENTIONAL SERVERS
#pass in on $ext_if proto tcp from any to any port {22}
|
|
/etc/pf.conf for SIMULATION Mode test
|
# STEVE LITT'S ULTRASIMPLE pf.conf
# MACROS
ext_if="rl0"
int_if="re0"
lan_ip="192.168.100.0/24"
private_networks="{ 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 255.255.255.255/32, 127.0.0.0/8 }"
# SCRUB PACKETS
match in all scrub (no-df)
match out all scrub (random-id)
# SET UP NAT: 4.8 SYNTAX
#match out on $ext_if from $lan_ip nat-to ($ext_if) #LIVE
match out on $ext_if from !($ext_if) nat-to ($ext_if) #TEST
# IPV6 CURRENTLY IRRELEVANT, DROP IT **QUICK**
block drop in quick inet6
# ANTISPOOF **QUICK**
antispoof log quick for { $ext_if } inet
# DEFAULT IS BLOCK IN FROM INTERNET, PASS ALL ELSE block log all
pass on $int_if all
pass out on $ext_if all
# SKIP LOOPBACK
set skip on lo0
# ALLOW ALL ICMP EXCEPT REDIRECTS
pass in inet proto icmp all
block in log on $ext_if inet proto icmp all icmp-type redir
# BLOCK THE OBVIOUSLY BOGUS **QUICK**
block in quick log on $ext_if from any to 192.168.200.0/24 #TEST
block in quick log on $ext_if from no-route to any
block in quick log on $ext_if from any to 255.255.255.255
#block in quick log on $ext_if from any to $private_networks
#block in quick log on $ext_if from $private_networks to any
#block return out quick log on $ext_if from any to $private_networks
# COMMENT OUT THE PRECEDING 3 LINES WHEN TESTING THE INTERNET FACING
# NIC ON THE LAN IN ORDER TO SIMULATE THE INTERNET,
# UNCOMMENT THEM FOR LIVE PRODUCTION
# ALLOW INTERNET QUERIES TO FIREWALL'S SAFE INTENTIONAL SERVERS
pass in on $ext_if proto tcp from any to any port {22}
|
|
Commands
Task
|
Command
|
Restart the network (after changing config). This also restarts any DHCP clients. I found one case where doing this didn't recognize a change to the IP address, so if all else fails you might have to reboot.
|
sh /etc/netstart
|
Restart the DHCP server.
|
dhcpd
|
Find every file with the current IP address (presumably to change them)
|
grep -rl 192.168.100.96 /etc/*
|
|
|
Reset the PF firewall. This also syntax checks /etc/pf.conf.
|
pfctl -f /etc/pf.conf |
Temporarily disable PF firewall
NOTE: Very dangerous unless running in simulation mode behind another firewall.
|
pfctl -d
|
Re-enable PF firewall
|
pfctl -e
|
Show firewall rules in the order they're executed
|
pfctl -s rules
|
Show everything including ruleset warnings.
|
pfctl -vv <other options and args>
|
Run "lint" on your pf.conf to
show warnings and other stuff. Compiles but does not load the config
file, so if it fails to compile it doesn't leave you wide open. If you
want to actuall load it, which I think is a bad idea if you're at the
lint stage,substitute the -f option for the -n.
This is also an excellent way to get a numbered list of rules, with numbers starting at zero.
|
pfctl -g -vv -nf /etc/pf.conf
|
View your PF log file. DO NOT use the -v option -- insecure! |
tcpdump -n -e -ttt -r /var/log/pflog
|
View PF events live as they happen (sort of like a tail-f). DO NOT use the -v option -- insecure!
|
tcpdump -n -e -ttt -i pflog0
|
|
|
Finding
a host's entry in a hashed .ssh/known_hosts. After running the command,
grep .ssh/known-hosts for the material shown by the command.
|
ssh-keygen -H -F 192.168.100.249
|
Public DNS servers
- Google
- Verizon
- 4.2.2.1
- 4.2.2.2
- 4.2.2.3
- 4.2.2.4
- 4.2.2.5
- 4.2.2.6
- DNSAdvantage
- 156.154.70.1
- 156.154.71.1
- OpenDNS
- 208.67.222.222
- 208.67.220.220
- Norton free DNS
- 198.153.192.1
- 198.153.194.1
- Scrubit
- 67.138.54.100
- 207.225.209.66