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

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:

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 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:

# cd /usr/pkgsrc/net/nmap
# make && make install

or, using binary packages with pkgin:

# pkgin install nmap

Using nmap

The nmap 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