Securing BSD Daemons

02/07/2001

In last week's article, we used the sockstat utility to determine which daemons were listening for network connections on a FreeBSD system. Let's continue where we left off by taking a closer look at /etc/inetd.conf.

Remember that inetd is the internet super-server which listens for requests on behalf of other daemons; it reads /etc/inetd.conf to determine which ports you wish it to listen on. You should always comment out the lines which represent the daemons you don't wish people to make network connections to. A good general rule is that if you don't know what a daemon does, comment it out.

On my system, inetd is listening for IPV4 connection requests for the following daemons: ftp, telnet, comsat, ntalk, and tftp. I don't intend to maintain a tftp or ftp server, and I'm not totally convinced that I need to provide comsat or ntalk services. However, I do need to telnet into my FreeBSD system on occasion. So, I'll become the superuser, open up /etc/inetd.conf using the vi editor, and add comment characters to the four lines that represent the daemons on whose behalf I don't want inetd to listen. When I'm finished, that portion of my /etc/inetd.conf file will look like

What happened here? It looks like my FreeBSD system is still accepting ftp connections. We've just discovered that it is not enough to edit /etc/inetd.conf; we must also tell inetd to stop listening on behalf of the daemons we've commented out. We'll have to send a hang up or HUP signal to inetd to make it aware of our changes. In order to do that, we must find out inetd's PID:

In my example, I have no need to accept ftp (port 21) or telnet (port 23) connections from clients running IPV6, so I'll comment out these two lines in my /etc/inetd.conf file. The IPV6 section is located towards the bottom third of the file. Again, if you edit this file, don't forget to send the HUP signal and check that your changes took effect by running sockstat again.

Editing /etc/inetd.conf allows you to control which portsinetd will monitor for incoming connection requests. However, it doesn't have a mechanism to allow control over which clients you are willing to accept connection requests from. As it stands now, any person with a network connection, which unfortunately includes an Internet connection, to my FreeBSD system can telnet to my computer. Fortunately, they'll be prompted to login, which is one reason why it is important to implement a good password policy. But it makes sense to add another layer of security by telling inetd to refuse the incoming connection request if it does not come from a client that I trust.

This is where tcp wrappers comes into play. If you are running FreeBSD 3.2 or higher, it is already built into your system and is just waiting for you to configure which clients you are willing to accept connection requests from. The name of its configuration file is /etc/hosts.allow, but you'll find the syntax of the file under man 5 hosts_access and additional options under man 5 hosts_options.

There are two things to keep in mind when editing this file:

the first rule found that matches the client for a particular service is used to determine if the client is allowed or denied access to that service;

if there are no rules that match the client, access is allowed.

The syntax itself is fairly straightforward; each rule has 2 fields and can use an optional third field:

daemon: client :command

If your rule doesn't fit on one line, use the \ character at the end of the line to indicate that the rule continues to the next line.

There are a few useful wildcards and operators that you should be aware of.

ALL matches all; can be used in the "daemon" or "client" field

LOCAL -- used in the "client" field and matches hostnames that don't contain a "." in them; for example, it would match "genisis", but not "genisis.istar.ca"

EXCEPT -- used in the "client" field; allows you to allow some clients but not others

ALLOW -- used in the last field to allow the service

DENY used in the last field to deny the service

As you create your rules, you'll want to use the tcpdmatch utility to ensure that your rules are actually creating the access control you intend. Before I start creating access rules for the telnet daemon on my FreeBSD system, let's see what happens when I try to telnet into my FreeBSD box.

Notice that my system is accepting telnet connections and responds by giving a login prompt on terminal ttyp1. Once I've logged in, I receive my MOTD, my customized prompt, and it's just like I'm sitting at my FreeBSD box. It would appear that inetd did its job properly. Now, let's see what the default /etc/hosts.allow file looks like.

Let's stop right here to see if we can determine why that first rule prevents the rest of the file from working. It basically says: for all daemons, from all clients, allow access. Because this rule matches all clients, and it's the first match, it will always be used. Let's see what happens if we comment out that first rule. I'll become the superuser, open /etc/hosts.allow using the vi editor, and put a # in front of that first rule, and save my changes.