BSD DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement


FreeBSD Basics

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

#ftp stream tcp nowait root /usr/libexec/ftpd ftpd -l
telnet stream tcp nowait root /usr/libexec/telnetd telnetd
#shell stream tcp nowait root /usr/libexec/rshd rshd
#login stream tcp nowait root /usr/libexec/rlogind rlogind
#finger stream tcp nowait/3/10 nobody /usr/libexec/fingerd fingerd -s
#exec stream tcp nowait root /usr/libexec/rexecd rexecd
#uucpd stream tcp nowait root /usr/libexec/uucpd uucpd
#nntp stream tcp nowait usenet /usr/libexec/nntpd nntpd
# run comsat as root to be able to print partial mailbox contents w/ biff,
# or use the safer tty:tty to just print that new mail has been received.
#comsat dgram udp wait tty:tty /usr/libexec/comsat comsat
#ntalk dgram udp wait tty:tty /usr/libexec/ntalkd ntalkd
#tftp dgram udp wait nobody /usr/libexec/tftpd tftpd /tftpboot
#bootps dgram udp wait root /usr/libexec/bootpd bootpd

Now let's see what happens if I try to ftp into my FreeBSD computer.

ftp 24.141.117.39
Connected to 24.141.117.39.
220 foo.bar.com FTP server (Version 6.00LS) ready.
Name (24.141.117.39:genisis): anonymous
530 User anonymous unknown.
ftp: Login failed.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>

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:

ps -acux | grep inetd
root 172 0.0 0.6 1040 784 ?? Is Thu03PM 0:00.52 inetd

Since this process is owned by root, we'll have to become the superuser in order to send it the HUP signal:

su
Password:

kill -1 172
exit

To see if this worked, let's rerun the sockstat utility:

sockstat -4
USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS  FOREIGN ADDRESS      
root     XF86_SVG  3752    0 tcp4   *:6000         *:*                  
root     sshd       185    4 tcp4   *:22           *:*                  
root     sendmail   181    4 tcp4   *:25           *:*                  
root     sendmail   181    5 tcp4   *:587          *:*                  
root     lpd        177    6 tcp4   *:515          *:*                  
root     inetd      172    5 tcp4   *:23           *:*                  
daemon   portmap    152    3 udp4   *:111          *:*                  
daemon   portmap    152    4 tcp4   *:111          *:*                  
root     syslogd    149    4 udp4   *:514          *:*                  
root     dhclient   125    3 udp4   *:*            *:*                  
root     dhclient   125    6 udp4   *:68           *:*

Notice that there is now only one entry for inetd and that it is only monitoring port 23, the telnet port. Let's see what happens now if I try to ftp into my FreeBSD system:

ftp 24.141.117.39
ftp: connect: Connection refused

To be thorough, we should also see if inetd is willing to accept connections from IPV6 clients:

sockstat -6
USER   COMMAND  PID  FD PROTO  LOCAL ADDRESS  FOREIGN ADDRESS
root   sshd     185   3 tcp46  *:22           *:*                  
root   inetd    172   9 tcp6   *:21           *:*                  
root   inetd    172  10 tcp6   *:23           *:*

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 ports inetd 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.

telnet 24.141.117.39
Trying 24.141.117.39...
Connected to genisis.
Escape character is '^]'.

FreeBSD/i386 (genisis) (ttyp1)

login: genisis
Password:
Last login: Thu Jan 18 17:44:29 on ttyv4
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
    The Regents of the University of California.  All rights reserved.

FreeBSD 4.2-RELEASE (SOUND) #0: Tue Dec 12 20:01:29 EST 2000

  _   _   _   _   _     _   _   _   _   _   _   _   _   _   _   _  
 / \ / \ / \ / \ / \   / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ 
( M | e | r | r | y ) ( C | h | r | i | s | t | m | a | s | ! | ! )
 \_/ \_/ \_/ \_/ \_/   \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ 
You have mail.

genisis@~ logout
Connection closed by foreign host.

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.

more /etc/hosts.allow
#
# hosts.allow access control file for "tcp wrapped" applications.
# $FreeBSD: src/etc/hosts.allow,v 1.8.2.3 2000/07/20 15:17:44 ume Exp $
#
# NOTE: The hosts.deny file is deprecated.
#       Place both 'allow' and 'deny' rules in the hosts.allow file.
#	See hosts_options(5) for the format of this file.
#	hosts_access(5) no longer fully applies.

#	 _____                                      _          _ 
#	| ____| __  __   __ _   _ __ ___    _ __   | |   ___  | |
#	|  _|   \ \/ /  / _` | | '_ ` _ \  | '_ \  | |  / _ \ | |
#	| |___   >  <  | (_| | | | | | | | | |_) | | | |  __/ |_|
#	|_____| /_/\_\  \__,_| |_| |_| |_| | .__/  |_|  \___| (_)
#					   |_|                   
# !!! This is an example! You will need to modify it for your specific
# !!! requirements!


# Start by allowing everything (this prevents the rest of the file
# from working, so remove it when you need protection).
# The rules here work on a "First match wins" basis.
ALL : ALL : allow

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.

Pages: 1, 2

Next Pagearrow





Sponsored by: