# NetBSD Security Processes and Services
This document covers secure processes and services for NetBSD Operating
Systems and Networks. Most of the information in this document can
easily be translated to other BSD systems, however.
# Overview
## Setup Example
Simply writing this document without some sort of consistent example
would be quite difficult, so for the sake of easy discussion, the
following is what we want to accomplish:
Internal Network clients, hosts, internal servers
172.16.0.0
|
|
NetBSD Firewall fxp0 172.16.14.1
Server with SSH Open ------------------
ep0 216.68.250.60
|
|
Internet Connection gateway switch/
Provider Network router
216.68.250.65
|
|
Big Bad Internet insert cloud here
This is a pretty common setup for many organizations, to be connected
via a service providers network out onto the internet.
The purpose of this firewall is to allow the clients on the 172.16.0.0
network to interact with the internet.
## The Desired Setup of the Firewall
In a nutshell we want the firewall to be able to pass certain traffic in
and out, however, we only want one available service *at* the firewall
itself, that service is Secure Shell. Following is a matrix of how this
particular installation is to look:
Service |
Connect to Firewall |
Pass In |
Pass Out |
DNS |
NO |
YES |
YES |
SMTP |
NO |
YES |
YES |
HTTP |
NO |
YES |
YES |
FTP |
NO |
YES |
YES |
SSH |
YES |
YES |
YES |
It is important to note here that we need to be able to pass DNS, SMTP,
FTP and HTTP traffic, however, we only really *want* the SSH service to
be able to establish a connection to the firewall. The reason noting
this now is important is because the rules in IPFILTER for making a
connection and passing traffic are nearly identical.
## More than one way to . . .
The setup used throughout this document is an example, there is
definitely more than one way to do this, for example:
private network firewall DMZ with public firewall uplink
web, ftp, etc.
servers
The DMZ would have publicly accessible web servers, ftpd servers etc. In
our example, we do not require the DMZ since we are not hosting any web
servers or running a DNS server that will participate with the rest of
the internet.
# Configuring Secure Shell
NetBSD ships with a Secure Shell implementation based on OpenBSD's. The
default configuration of Secure Shell is done quite well, and there is
little an administrator needs to actually do in most cases. Turning on
the Secure Shell daemon is required, however. For posterity, we are
going to take a short look at configuring it.
## The Client Side Configuration File
The ssh client's configuration file is located in `/etc/ssh/ssh_config` and in
`~/.ssh/config` for single users.
The options contained in it are named intuitively and are rather verbose.
Documentation can be found in the ssh_config(5) manpage.
## The Server Configuration File
The server side of SSH is configured via `/etc/ssh/sshd_config`. The defaults
are set to high security levels by default. To enable the ssh server, put the
line `sshd=yes` into `/etc/rc.conf` and run
/etc/rc.d/sshd restart
to start the server daemon and create any host keys if they are not already
present.
One item to take note of is that the server config does not allow X11 forwarding
by default, which of course on a firewall is a **good thing**. To enable it the
administrator must change the following lines:
StrictModes no
X11Forwarding yes
Again, there is little to nothing the administrator needs to do with the Secure
Shell setup unless they wish to alter the default config.
# Configuring IPFILTER
NetBSD ships with IPfilter as its default firewall and packet filtering
software.
## Understanding The ipf.conf File
The file that controls firewall rules for ipfilter is `/etc/ipf.conf` for IPv4
and `/etc/ipf6.conf` for IPv6. In this section we will go over the settings we
need and how I chose to implement them.
Basically, ipfilter operates on two basic principles:
1. match the current line
2. the last line supersedes previous ones
Following is a very rudimentary `ipf.conf` file:
pass in on any all
block in on any all
According to the first line, on any interface, all traffic may be
passed. On the second line, however, all traffic on any interface is
blocked.
## The Syntax
For the most part, ipfilter syntax is generally easy to follow, it is almost
natural. To pass in certain traffic, one says pass in, to pass out, pass out.
The interface can be specified or it can be all by saying something like:
pass out on all . . .
If one wanted to specify the interface:
pass out on ep0 . . .
So far so good, now lets look at the configuration we need for our firewall,
first we already know we want SSH traffic to be able to pass and connect:
# sshd in from any
pass in quick on ep0 proto tcp from any to 216.68.250.60/32 port = 22 keep state
You have probably already noticed some very new syntax here, let us take a look
at that now before we go any further.
### The quick Keyword
The `quick` keyword overrides any previous settings. It is most convenient when
large and complex firewalls are built with up to 100 rules in them. In our case
it is not so, however, we are including to be absolutely sure that the rule will
be processed.
### The proto Keyword
The `proto` keyword dictates, you guessed it, the protocol. In the case of
this firewall the protocol is always TCP.
### The port Keyword
The `port` keyword can be either the port number or the name as defined in
`/etc/services`, for posterity I have mixed and matched in this file.
### The keep state Keyword
The `keep state` keywords ensure packet checking from end to end within
the firewall and here is why, if you look closely at all of the rules,
they all use the `quick` keyword, so they circumvent previous rules and
hence checking on both sides of the firewall *may* not take place.
## Example Entries
Now lets look at the rest of the file in sections since we have a
slightly better idea of what we are looking at.
### Blocking Reserved & Local Machine Addresses
There are certain address classes we already know should not pass at all
through our firewall. The addresses are those specified as internal only
addresses and the localhost address (not the interface addresses):
* 127.0.0.0/8 (the localhost)
* 192.168.0.0/16 (reserved for internal networks, see
[RFC 1918](tools.ietf.org/html/rfc1918))
* 172.16.0.0/12 (reserved for internal networks, see RFC 1918)
* 10.0.0.0/8 (reserved for internal networks, see RFC 1918)
* 169.254.0.0/16 (IANA use)
* 192.0.2.0/24 (netblock for documentation authors)
* 204.152.64.0/23 (Sun Microsystems cluster interconnects)
* 224.0.0.0/3 (class D and E multicasts)
It is important to note here that on one interface, fxp0, we want to be
able to pass in and out on the 172.16.0.0 network (since our internal
network is 172.16..0.0). To do this we can use the following rules:
block in quick on any from 192.168.0.0/16 to any
block in quick on any from 10.0.0.0/8 to any
block in quick on any from 127.0.0.0/8 to any
block in quick on any from 0.0.0.0/8 to any
block in quick on any from 169.254.0.0/16 to any
block in quick on any from 192.0.2.0/24 to any
block in quick on any from 204.152.64.0/23 to any
block in quick on any from 224.0.0.0/3 to any
In this table you will notice the 172.16.0.0/12 is omitted (even though
it should be blocked at least on ep0), you will see why in the next part
of the file.
### Paranoia Block
Next we will cut off all traffic to ep0, hence we do not need to explicitly
close off 172.16.0.0 from it.
# block all
block in quick on ep0 all
### Make the Firewall Act like an Internet Client
Next we want to make the firewall have the capability of acting like an internet
client, this is pretty simple:
# pass out as if we were a single internet client
pass out quick on ep0 proto tcp from 216.68.250.60/32 to any keep state
pass out quick on ep0 proto udp from 216.68.250.60/32 to any keep state
pass out quick on ep0 proto icmp from 216.68.250.60/32 to any keep state
### Passing the Rest
Now we ant to add all of the protocols we want to pass. It should be important
to note that if you have any of these services enabled **on the firewall** then
their port will be accessible **on the firewall**.
It is usually a safer bet *not to have anything but ssh, ipfilter and ipnat
running on it*, the exception this might be (as in my home setup) you simply do
not have the hardware to spare and must have DNS and/or other server processes
running on it as well.
# dns stuff
pass in log proto tcp from any to any port = 53 keep state
pass in log proto udp from any to any port = 53 keep state
# pass thru www and ftp
pass in log proto tcp from any to any port = www keep state
pass in proto tcp from any to any port = ftp keep state
pass in proto tcp from any to any port = ftp-data keep state
pass in proto tcp from any port = ftp-data to any port > 1023 keep state
pass in log proto icmp all keep state
## IP Filter for Dial Ups
Dial up connections offer somewhat of a challenge for ipfilter in that most dial
up interfaces are assigned a different IP address each time the user makes the
connection.
In dial up or any dynamic address situation, the rules must be written in a
slightly less secure manner. In other words, rules cannot use the internet side
IP address, however, even just using the interface is normally enough to
guarantee pretty good security. As an example, here is one of the rules that
uses an IP address:
# pass out as if we were a single internet client
pass out quick on ep0 proto tcp from 216.68.250.60/32 to any keep state
pass out quick on ep0 proto udp from 216.68.250.60/32 to any keep state
pass out quick on ep0 proto icmp from 216.68.250.60/32 to any keep state
For our dial up connection we will have to change the ruleset to this:
# pass out as if we were a single internet client
pass out quick on ep0 proto tcp from any to any keep state
pass out quick on ep0 proto udp from any to any keep state
pass out quick on ep0 proto icmp from any to any keep state
Now what good does this do us now? Well, first, any ports that are still blocked
are *still* inaccessible. Second, if a service is not turned on and no inbound
proxying is enabled, all of this traffic is just passing through. There is no
way for anyone to connect to the firewall except via ssh.
# Configuring IPNAT
Network Address Translation (NAT) is part of IPfilter, which comes by default
with the NetBSD release. The job of NAT is to take a source IP address and
translate it to another out a different network interface. This is also known
as masquerading.
Luckily for you (as the exhausted reader) and I (the exhausted author)
configuring NAT is pretty simple, especially with the example we are using.
## What our /etc/ipnat.conf needs to look like
It is very simple:
map ep0 172.16.0.0/16 -> 216.68.250.60/32 proxy port ftp ftp/tcp
map ep0 172.16.0.0/16 -> 216.68.250.60/32 portmap tcp/udp 10000:20000
map ep0 172.16.0.0/16 -> 216.68.250.60/32
First we are proxying ftp thru the ep0 interface. The next line says go ahead
and map all tcp/udp traffic right on through the interface and assign each out
bound "connection" a port from 10000 to 20000 and finally the last line says,
just plain map from 172.16.0.0/16 to 216.68.250.60/32. For our purposes this is
all we need so the rest of this document is of limited interest to those of you
in a crunch trying to get a firewall up.
## Other Nifty Stuff
A few items of interest for the curious, we can also map *into* the local
network as well:
map fxp0 216.68.250.60/32 -> 172.16.14.1/32 (add whatever service here)
This might be handy to connect to a specific server inside (such as a web
server) or if you recall the DMZ example before, we may wish to translate *into*
the DMZ from the world. Additionally it can be used as a poor man's router to
link internal networks together - but there are much better was of doing that.
Instead of this, however, most administrators would locate the web server within
a DMZ and use ipfilter to ensure only http and ssh connections can be made to
the system.
If you look closely you will see all outbound connections map to a single IP
address, what if you wanted to be able to map to more? You can do so by simply
changing the single address to a network:
map ep0 172.16.0.0/16 -> 216.68.250.0/24
Finally, the portmap range can be adjusted to whatever you feel is necessary.
## IPNAT With Dial Up Networking
Many home users use dial up connections to access the internet. Many dial up
connections are assigned a dynamic IP address every time the user connects. At
first glance it may appear that some method for putting this new address into
`/etc/ipnat.conf` is required. Luckily, that is not so. Take note of how
addresses can be shown on the internet side of the `ipnat.conf` file. Actually
entire subnets can be used like so:
map ep0 172.16.0.0/16 -> 216.68.0.0/16
What this is saying is that addresses from 172.16.0.0 can be assigned any
address on 216.68.0.0's network. Keeping that in mind, on a dial up connection
you know you will be given one and one address, so the following entries
effectively do the same:
map ppp0 172.16.0.0 -> 0/32 proxy port ftp ftp/tcp
map ppp0 172.16.0.0 -> 0/32 portmap tcp/udp 40000:60000
map ppp0 172.16.0.0 -> 0/32
Here we are saying map anything on 172.16.0.0 to one single address, the address
the interface will have.
# Activating Services
At this point, in theory, we are ready to start everything up. All of the
services we will need running are:
* ipfilter
* ipnat
* ipmon
* sshd
Additionally, we need to make sure that ip forwarding is enabled in the kernel.
## Turning on IP Forwarding
To turn on IP forwarding use the sysctl facility:
sysctl -w net.inet.ip.forwarding=1
To have it turned on at bootup append the following text to `/etc/sysctl.conf`:
net.inet.ip.forwarding=1
## /etc/defaults/rc.conf and /etc/rc.conf
NetBSD's default rc settings are all kept in `/etc/defaults/rc.conf`. To make
upgrades safer, override settings in `/etc/rc.conf` instead of
`/etc/defaults/rc.conf`.
### What we need in /etc/rc.conf
Basically, we can yank the contents of `/etc/defaults/rc.conf` and drop them
right into `/etc/rc.conf`:
# cat /etc/defaults/rc.conf >>/etc/rc.conf
# vi /etc/rc.conf
Note the double `>` here to avoid overwriting the contents of `/etc/rc.conf` as
shipped! Here is what `/etc/rc.conf` would look like after editing:
#
# see rc.conf(5) for more information.
#
# Use program=YES to enable program, NO to disable it. program_flags are
# passed to the program on the command line.
#
# Load the defaults in from /etc/defaults/rc.conf (if it's readable).
# These can be overridden below.
#
if [ -r /etc/defaults/rc.conf ]; then
. /etc/defaults/rc.conf
fi
# If this is not set to YES, the system will drop into single-user mode.
#
rc_configured=YES
# Add local overrides below
#
ipfilter=YES
ipnat=YES
ipmon=YES ipmon_flags="-sn"
sshd=YES
On i386 (PC) systems you will also see the wscons framework enabled:
wscons=YES
## Activating the Services
Next we have to activate the services, we can do this one of two ways:
1. reboot the system
2. start using the rc scripts by hand
I prefer doing the latter first just to make sure everything is setup right,
then I do a reboot to make sure all of the services will start up properly
during the bootup sequence.
### Starting Services "by hand"
To start any service it is quite simple:
# /etc/rc.d/[service_name] start
Additionally, a service may be stopped:
# /etc/rc.d/[service_name] stop
or restarted:
# /etc/rc.d/[service_name] restart
So for this firewall, here is the order we need to start the services:
# /etc/rc.d/sshd start
# /etc/rc.d/ipfilter start
# /etc/rc.d/ipnat start
# /etc/rc.d/ipmon start
In reality, when sshd and ipmon start is arbitrary, however, ipfilter
must be enabled before ipnat.
# Additional Products
The NetBSD release comes ready to roll with a host of advanced networking
capabilities. However, an administrator may wish to use additional or
alternative software. This section looks at other software that can run on
NetBSD the administrator may find of interest.
## Portsentry
The portsentry utility is a great tool. In a nutshell, portsentry
watches your system for scans and connection attempts and then will take
action to block a possible attacker. The main weakness portsentry has is
that it takes one connection attempt for portsentry to determine that
the host attempting to connect is hostile, so, if the first attempt is
successful, you are still out of luck.
### Getting Portsentry
Portsentry can be retrieved and installed using the
[pkgsrc](http://www.NetBSD.org/docs/software/packages.html) system:
# cd /usr/pkgsrc/security/portsentry
# make && make install
or using binary packages with pkgin:
# pkgin install portsentry
### Configuring Portsentry
On NetBSD, portsentry is configured in `/usr/pkg/etc/portsentry.conf`.
### Port Configurations
In the configuration file there are three sets of ports shown, of these, one for
tcp and one for udp must be selected by uncommenting the line, the default is to
use the "middle" sets, they should look something like this:
# Un-comment these if you are really anal:
TCP_PORTS="1,7,9,11,15,70,79,80,109,110,111,119,138,139,143,512,513,514,515,540,
635,1080,1524,2000,2001,4000,4001,5742,6000,6001,6667,12345,12346,20034,30303,32
771,32772,32773,32774,31337,40421,40425,49724,54320"
#UDP_PORTS="1,7,9,66,67,68,69,111,137,138,161,162,474,513,517,518,635,640,641,66
6,700,2049,32770,32771,32772,32773,32774,31337,54321"
#
# Use these if you just want to be aware:
#TCP_PORTS="1,11,15,79,111,119,143,540,635,1080,1524,2000,5742,6667,12345,12346,
20034,31337,32771,32772,32773,32774,40421,49724,54320"
UDP_PORTS="1,7,9,69,161,162,513,635,640,641,700,32770,32771,32772,32773,32774,31
337,54321"
#
# Use these for just bare-bones
#TCP_PORTS="1,11,15,110,111,143,540,635,1080,524,2000,12345,12346,20034,32771,32
772,32773,32774,49724,54320"
#UDP_PORTS="1,7,9,69,161,162,513,640,700,32770,32771,32772,32773,32774,31337,543
21"
#### Advanced Stealth Detection
The number of ports portsentry should monitor in advanced mode, all of the ports
below the listed number(s) are monitored this way:
ADVANCED_PORTS_TCP="1023"
ADVANCED_PORTS_UDP="1023"
Additionally in this section portsentry can be told certain items to exclude
(such as loud NetBIOS services):
# Default TCP ident and NetBIOS service
ADVANCED_EXCLUDE_TCP="113,139"
# Default UDP route (RIP), NetBIOS, bootp broadcasts.
ADVANCED_EXCLUDE_UDP="520,138,137,67"
#### Configuration Files
Where files live, on NetBSD this is under `/usr/pkg/*`:
# Hosts to ignore
IGNORE_FILE="/usr/pkg/etc/portsentry.ignore"
# Hosts that have been denied (running history)
HISTORY_FILE="/usr/pkg/etc/portsentry.history"
# Hosts that have been denied this session only (temporary until next restart)
BLOCKED_FILE="/usr/pkg/etc/portsentry.blocked"
#### Response Options
This section is pretty straightforward just as it says in the file:
# 0 = Do not block UDP/TCP scans.
# 1 = Block UDP/TCP scans.
# 2 = Run external command only (KILL_RUN_CMD)
BLOCK_UDP="1"
BLOCK_TCP="1"
#### Dropping Routes
This is the kill route option, the one used for NetBSD is already uncommented:
# Generic BSD (BSDI, OpenBSD, NetBSD, FreeBSD)
KILL_ROUTE="/sbin/route add $TARGET$ 333.444.555.666"
It should be noted that some can actually modify firewall tables, for example,
the FreeBSD packetfilter option:
# For those of you running FreeBSD (and compatible) you can
# use their built in firewalling as well.
#
#KILL_ROUTE="/sbin/ipfw add 1 deny all from $TARGET$:255.255.255.255 to any"
If another type of firewall is being used on your system, it may be possible to
add in something like this to your portsentry configuration.
#### TCP Wrappers
This section is the text that gets put into `/etc/hosts.deny`.
#
KILL_HOSTS_DENY="ALL: $TARGET$"
#### External Commands
Here, any external command (or script etc.) may be called.
#KILL_RUN_CMD="/some/path/here/script $TARGET$ $PORT$"
As an example, altering the firewall could be here as well.
#### Scan Trigger Value
This is the number of port connects that portsentry allows before an alarm goes
up, the default is 0, 1 is usually pretty safe as well (to keep down the false
alarms).
#### Port Banner
This is a message that can be sent back to the person who tripped portsentry,
unless they are using a very verbose tool it usually ends up in a logfile on
their system (on NetBSD it ends up in `/var/log/messages`.
#PORT_BANNER="** UNAUTHORIZED ACCESS PROHIBITED *** YOUR CONNECTION ATTEMPT HAS
BEEN LOGGED. GO AWAY."
## NMAP
The nmap utility is a portscanner. It can scan one host, a network or
combinations therein. It is currently in the pkgsrc tree.
### Getting and Installing NMAP
Use [pkgsrc](http://www.NetBSD.org/docs/software/packages.html):
# cd /usr/pkgsrc/net/nmap
# make && make install
or, using binary packages with pkgin:
# pkgin install nmap
### Using nmap
The [nmap](http://insecure.org/) utility has **a lot** of options, we will look
at three examples:
1. scanning one host
2. scanning several hosts
3. scanning a NetBSD firewall
#### Scanning One Host
For this example we will use a pretty insecure system on an internal network:
# nmap -P0 172.16.14.12
Starting nmap V. 2.53 by fyodor@insecure.org ( www.insecure.org/nmap/ )
Interesting ports on marie.ipsosasi.net (172.16.14.12):
(The 1504 ports scanned but not shown below are in state: closed)
Port State Service
7/tcp open echo
9/tcp open discard
13/tcp open daytime
19/tcp open chargen
21/tcp open ftp
23/tcp open telnet
37/tcp open time
111/tcp open sunrpc
. . .
#### Scanning A Network
Now let's look at a whole bunch of machines!
% nmap -P0 172.16.14.0/24 > nmap.out
Whenever it is either done (which could be awhile) or interrupted/stopped take a
peek at the file where all of the information was dumped, following is a sample
from the network I scanned:
Starting nmap V. 2.53 by fyodor@insecure.org ( www.insecure.org/nmap/ )
All 1523 scanned ports on (172.16.14.0) are: closed
Interesting ports on somename.blah.net (172.16.14.1):
(The 1521 ports scanned but not shown below are in state: filtered)
Port State Service
23/tcp open telnet
68/tcp closed bootpc
All 1523 scanned ports on somename.blah.net (172.16.14.2) are: closed
Interesting ports on somename.blah.net (172.16.14.3):
(The 1520 ports scanned but not shown below are in state: closed)
Port State Service
23/tcp open telnet
79/tcp open finger
80/tcp open http
Interesting ports on somename.blah.net (172.16.14.4):
(The 1513 ports scanned but not shown below are in state: closed)
Port State Service
7/tcp open echo
9/tcp open discard
19/tcp open chargen
. . .
#### Scanning a NetBSD Firewall
Last but definitely not least, lets nail a firewall:
Starting nmap V. 2.53 by fyodor@insecure.org ( www.insecure.org/nmap/ )
Interesting ports on (216.68.250.60):
(The 1522 ports scanned but not shown below are in state: filtered)
Port State Service
22/tcp open ssh
Nmap run completed -- 1 IP address (1 host up) scanned in 772 seconds
Now that is more like it.
# Examples
* [[ipf.conf|http://netbsd.org/docs/network/nsps/examples/ipf.conf]]
* [[ipnat.conf|http://netbsd.org/docs/network/nsps/examples/ipnat.conf]]
* [[rc.conf|http://netbsd.org/docs/network/nsps/examples/rc.conf]]
* [[sysctl.conf|http://netbsd.org/docs/network/nsps/examples/sysctl.conf]]
* [[portsentry.conf|http://netbsd.org/docs/network/nsps/examples/portsentry.conf]]