ONLamp.com    
 Published on ONLamp.com (http://www.onlamp.com/)
 See this if you're having trouble printing code examples


FreeBSD Basics

Understanding BSD Daemons

01/31/2001

In the last few articles, we've looked at creating users and password policies. Password policies are just one layer in the many-layered approach needed to create a secure computing environment that protects both users and resources.

Also from FreeBSD Basics:

Fun with Xorg

Sharing Internet Connections

Building a Desktop Firewall

Using DesktopBSD

Using PC-BSD

If you recall from the article on the System Startup Daemon init, there are three types of terminals on your FreeBSD system, as there are three different ways of accessing a computer running FreeBSD.

The first method is to physically walk up to a FreeBSD box and type in a username and password at a login prompt. The second is to dial into a FreeBSD system using a dial-up modem and a phone number. The third is to access the FreeBSD system over a network connection using an IP address.

In the next few articles, I'd like to concentrate on network connections. Since FreeBSD uses TCP/IP as its networking protocol, let's start by reviewing the basics of TCP/IP. You may want to take a few moments to skim over the article Networking with TCP/IP to remind yourself how TCP/IP ports and IPV4 addresses work.

TCP/IP applications always have 2 components: the server component, also called the daemon, "listens" for connection requests; the client component "initiates" connection requests. In order for two computers to share data using a TCP/IP application, one computer must use the client component and the other computer must provide the server component. Let's take a look at the snipped output of the following command:

apropos ftp

ftp(1), pftp(1), gate-ftp(1) - ARPANET file transfer program
ftpd(8) - Internet File Transfer Protocol server

Notice the two results for ftp: ftp(1) is the client portion while ftpd(8) is the server portion of the ftp application protocol. Often you'll see the letter d after an application name; the d represents the daemon so you know that it is the server component. If you read the manpage for ftp, you'll learn how to use the FTP client to transfer files to and from a remote site. However, if you read the manpage for ftpd, you'll learn how to configure server issues such as welcome screens, authentication methods, and logging.

In order for users to connect to your FreeBSD system over a network, they need to have the client component of the application they wish to use, and the matching server component must be listening for requests on your computer. For example, a user can use a telnet client to connect to your telnet daemon. However, if your telnet daemon is not listening for requests, a connection can not be created and the user will instead receive an error message.

It's important to know which of your daemons are listening for requests to ensure that network users aren't connecting to services you're not aware of, and users are able to connect to the services you wish them to connect to. One way of determining which of your daemons are waiting for connection requests from clients is to use the sockstat command:

whatis sockstat
sockstat(1) - list open sockets

The sockstat utility will show which daemons will accept IPV4 requests, IPV6 requests, and local Unix requests. If you just type sockstat, it will show all three types of requests; to specify one type of request, use the -4, -6, or -u switches with the command. Let's see which daemons on my computer are waiting for connection requests from clients running IPV4:

sockstat -4
USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS
tty comsat 8372 0 udp4 *:512 *:*
tty comsat 8372 1 udp4 *:512 *:*
tty comsat 8372 2 udp4 *:512 *:*
genisis navigato 3758 20 tcp4 24.141.117.39:4472 209.225.2.218:80
genisis navigato 3758 30 tcp4 24.141.117.39:4469 208.201.239.36:80
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 4 tcp4 *:21 *:*
root inetd 172 5 tcp4 *:23 *:*
root inetd 172 6 udp4 *:512 *:*
root inetd 172 7 udp4 *:518 *:*
root inetd 172 8 udp4 *:69 *:*
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 *:*

Let's pick apart this output. Notice that each listening daemon is a process as it has a PID. Also, each daemon has the choice of using either the TCP or the UDP transport protocol; you may notice that portmap actually uses both. The local address section shows either which port that daemon listens on, or the socket for a connection that has already been established.

Remember that there are thousands of TCP/IP application protocols, and each one has been assigned a port number. This number is used by the client to indicate which daemon it wishes to make a connection to. For example, the port number for SMTP is 25 and the port number for HTTP is 80. Since clients request connections by using a port number, the associated daemon listens for requests on that port number.

If you are unsure which application is associated with a certain port number, do a grep through the /etc/services file. For example, let's concentrate on this line in our output:

USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS
tty comsat 8372 0 udp4 *:512 *:*
^^ ^^^

To see which daemon is listening on the local address port number of 512, we could issue this command:

cat /etc/services | grep -w 512
aed-512		149/tcp	   #AED 512 Emulation Service		
aed-512		149/udp	   #AED 512 Emulation Service		
exec		512/tcp	   #remote process execution;
biff		512/udp	   comsat	#used by mail system to notify users
            ^^^^^^^

Even though we received four results, only one matches port number 512 using UDP. Let's see what biff is:

whatis biff
biff(1) - be notified if mail arrives and who it is from
comsat(8)                - biff server

It's not surprising that we received two results back from our whatis command, since we're dealing with a TCP/IP application. The client portion of this application is called biff, and the server portion is called comsat, or the biff server. Notice that the word comsat occurs under the COMMAND section of our sockstat output as it is the daemon that has the PID of 8372 that is listening on port 512 of my FreeBSD system.

Now let's concentrate on this line of output:

USER    COMMAND   PID FD PROTO LOCAL ADDRESS      FOREIGN ADDRESS      
genisis navigato 3758 20 tcp4  24.141.117.39:4472 209.225.2.218:80

This line represents an active TCP connection on my computer. You'll notice that both the local address and foreign address sections are filled in with an IP address followed by a colon followed by a port number. An IP address followed by a port number is called a socket, hence the name of the utility we are using. You may recognize the port number of 80 as belonging to HTTP; let's see what port 4472 is:

cat /etc/services | grep -w 4472

If you try the above command, you won't receive any results, just your command prompt back. To understand why, we need to look at how TCP connections are established.

TCP/IP applications actually have a choice of two transports, or the protocols used to "transport" the data between the server and the client. If an application uses the TCP transport, a logical connection is first created between the client and the server; once this connection has been established, "streams" of data can flow between the server and the client. If an application uses the UDP transport, no connection is created; instead the client sends out a "datagram" of information in the hopes that it is received by the server.

To create the necessary connection, TCP uses a mechanism known as the "three-way handshake," as three packets are required to fully establish the connection. The first packet is sent out by the client and indicates which port number or application it wishes to make a connection with. The second packet is sent out by the server and includes the socket. Since the server needs to keep the original port number open so it can continue to listen for requests from other clients, it will choose a random, high port number not being used by any other daemon. It will "bind" the IP address of the client to that port number to create the socket. The IP address of the client is important, as a daemon may actually be responding to several clients at a time; for example, an FTP server may have many clients logged in simultaneously and needs to ensure that it is sending the correct data to the correct client. Finally, the third packet is sent by the client; it contains information confirming that it knows what socket it is bound to and states that it is ready for data transfer to occur.

Returning to our example:

USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS
genisis navigato 3758 20 tcp4 24.141.117.39:4472 209.225.2.218:80

The user genisis used Netscape Navigator (an HTTP client) to access the httpd or web server running on port 80 of a computer with the IP address of 209.225.2.218. The httpd responded by choosing to bind port number 4472 to my IP address of 24.141.117.39. The reason why port 4472 did not show up in our grep of /etc/services is because it represents a socket or open connection, not a listening service.

If the sockstat output had shown this instead:

LOCAL ADDRESS		FOREIGN ADDRESS
24.141.117.39:80	209.225.2.218:4472

it would indicate that a user on a computer with the IP address of 209.225.2.218 had made a connection to my web server using port 80. To summarize, if a port number in the LOCAL ADDRESS column is found in the /etc/services file, it either represents a daemon on your computer listening for requests or it will be bound to the IP address of a client that has already established a connection with one of your daemons. If a port number used in a socket under the LOCAL ADDRESS column does not appear in /etc/services, it means that your computer used a client application to connect to another computer running TCP/IP.

The last thing I'd like you to notice in the sockstat output are the lines that mention inetd:

USER  COMMAND PID  FD PROTO LOCAL ADDRESS  FOREIGN ADDRESS      
root  inetd   172   4 tcp4  *:21           *:*                  
root  inetd   172   5 tcp4  *:23           *:*                  
root  inetd   172   6 udp4  *:512          *:*                  
root  inetd   172   7 udp4  *:518          *:*                  
root  inetd   172   8 udp4  *:69           *:*

You'll notice that this one command has one PID, but it is actually listening on five different ports. Let's grep /etc/services to see what applications those ports represent:

cat /etc/services | grep -w 21
ftp   21/tcp   #File Transfer [Control]
ftp   21/udp   #File Transfer [Control]

cat /etc/services | grep -w 23
telnet   23/tcp
telnet   23/udp

cat /etc/services | grep -w 512
aed-512   149/tcp  #AED 512 Emulation Service		
aed-512   149/udp  #AED 512 Emulation Service		
exec      512/tcp  #remote process execution;
biff      512/udp  comsat  #used by mail system to notify users

cat /etc/services | grep -w 518
ntalk   518/tcp
ntalk   518/udp

cat /etc/services | grep -w 69
tftp  69/tcp   #Trivial File Transfer
tftp  69/udp   #Trivial File Transfer

It looks like this one daemon is listening on behalf of the ftp, telnet, biff, ntalk, and tftp protocols. Now let's see what inetd is:

whatis inetd
inetd.conf(5), inetd(5) - internet super-server

Looks like it is the internet super-server and that it has its own configuration file. The inet daemon was created to save resources on Unix systems. Rather than creating processes for daemons that may not be used that often, this one daemon will listen on behalf of other daemons. If a client requests a connection on a port that is monitored by inetd, inetd will start a process for the daemon normally associated with that port so it can respond to the client's request. The configuration file tells inetd which ports to listen on; for example, if you don't want your FreeBSD computer to accept FTP connection requests, you need to tell inetd not to listen on port 21 on behalf of the FTP daemon.

Let's take a look at inetd's configuration file:

ls -l /etc/inetd.conf
-rw-r--r--  1 root  wheel  4859 Jan  9 09:34 /etc/inetd.conf

It looks like anyone can read this file, but only the superuser can edit it. Let's take a look at the top few lines of this file; I've snipped the output of my "more" command:

more /etc/inetd.conf

# $FreeBSD: src/etc/inetd.conf,v 1.44.2.3 2000/10/04 07:58:51 kris Exp $
#
# Internet server configuration database
#
# @(#)inetd.conf 5.4 (Berkeley) 6/30/90
#
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

You'll notice that this file contains a line for every daemon that inetd can listen on behalf of. If a line begins with the comment character #, inetd will not listen on the port associated with that daemon. For the lines that have not been commented out, inetd needs the following information in this order:

  1. the name of the daemon, so it can look it up in /etc/services and know which port number to listen on
  2. whether this daemon understands streams of data or datagrams
  3. whether this daemon uses TCP or UDP as its transport
  4. whether inetd should wait for the daemon to finish transferring data to the client or not bother waiting before listening for more client requests on the port number
  5. the name of the user account to start the daemon under
  6. the full path to the daemon to start
  7. any arguments that need to be passed to the daemon when starting it

Notice that in my /etc/inetd.conf file, there are five lines that have not been commented out. Not surprisingly, these lines are for the five services that showed up under inetd's PID in the output of my sockstat command.

Next week, let's take a closer look at inetd's configuration file and see how it is integrated into the TCP wrappers program.

Dru Lavigne is a network and systems administrator, IT instructor, author and international speaker. She has over a decade of experience administering and teaching Netware, Microsoft, Cisco, Checkpoint, SCO, Solaris, Linux, and BSD systems. A prolific author, she pens the popular FreeBSD Basics column for O'Reilly and is author of BSD Hacks and The Best of FreeBSD Basics.


Read more FreeBSD Basics columns.

Copyright © 2009 O'Reilly Media, Inc.