# 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]]