Securing BSD Daemons02/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
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 126.96.36.199 Connected to 188.8.131.52. 220 foo.bar.com FTP server (Version 6.00LS) ready. Name (184.108.40.206: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
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 -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 220.127.116.11 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
/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.
ALLmatches 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
DENYused 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 18.104.22.168 Trying 22.214.171.124... 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 126.96.36.199 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