The inetd(8)
“super-server” handles incoming network requests for network services that aren’t used very often. After all, many systems don’t have a steady stream of incoming FTP requests, so why have an FTP daemon running constantly? Instead, inetd
listens for incoming network requests, and when an FTP request arrives, it starts the FTP server and feeds it the request. Other common services that frequently (but not always) run through inetd
include ident, finger, and TFTP. Many of these services can also run standalone, if the application usage warrants it.
inetd
also handles functions so small and rarely used that they’re easier to implement within inetd
itself, rather than by calling a separate program. These functions include discard
(which dumps any data received into the bottomless pit of /dev/null), chargen
(which pours out a stream of characters), and echo
(which repeats whatever you send to it). Most of these services are not needed on the modern Internet and are disabled by default, but you have access to them if necessary.
You configure inetd
in /etc/inetd.conf. Here’s the default inetd
configuration for OpenBSD’s FTP server:
#1ftp 2stream 3tcp 4nowait 5root 6/usr/libexec/ftpd 7ftpd -US #ftp stream tcp6 nowait root /usr/libexec/ftpd ftpd -US
The first thing you’ll notice is that these entries are commented out. OpenBSD’s default inetd
offers only the identity server identd(8)
and two time services by default.
The first field is the service name (ftp
in this case) 1. The name in this field must match a name in /etc/services. The inetd
program uses the services file to perform a service lookup to identify which ports it must listen on. To change the TCP/IP port that your FTP server runs on, change the port for FTP in /etc/services. (You could also change the first field to use the name of the service that usually runs on the desired port, but I find starting my FTP server entry with the wrong name just gives me a headache.)
The second field is the socket type (stream
in this case) 2. This field dictates what sort of connection this is. All TCP connections are of type stream
, and UDP connections are of type dgram
. The inetd
program does support other types of connections, but they’re rarely used. If you’re considering using them, either you’re reading the documentation for a piece of software that needs that type of connection or you’re wrong (probably the latter).
The third field is the layer 4 network protocol, usually tcp
3, udp
, tcp6
, or udp6
. If you want to offer a service over both IPv4 and IPv6, you need a separate entry for each. That’s why there are two otherwise identical configurations for the FTP server. The inetd
program also supports RPC services, which have type rpc/udp
or rpc/tcp
.
The fourth field (nowait
in this case) 4 indicates whether inetd
should wait for the server program to close the connection or just start the program and go away. As a general rule, TCP-based daemons use nowait
, and UDP-based daemons use wait
. (There are rare exceptions.)
The fifth field (root
in this case) 5 names the user that the server daemon runs as. Many inetd
-using programs must run as root, as they can affect multiple users or accept more specific logins, but some smaller programs have dedicated unprivileged users.
The sixth field is the full path to the server program inetd
runs when a connection request arrives 6. Services implemented within inetd
have a path of internal
. The FTP server is at /usr/libexec/ftpd.
Finally, the last field gives the command to start the server program, including any command-line arguments you want. This configuration runs the FTP server with the arguments -US
7.
Script kiddies occasionally try to knock a server off the Internet by sending it more connection requests than it can handle. The inetd
program accepts up to 256 connections per minute per service. If a service receives too many connection requests, inetd
logs the issue and stops answering requests for that service for 10 minutes.
The IPv4 and IPv6 versions are limited separately, so you could accept 512 FTP connections per second if the requests are evenly divided between protocol families. You can override this globally with a command-line flag when starting inetd
, or you can configure this on a per-service basis.
The -R
flag controls how many connections per minute and per service that inetd
accepts. For example, to accept 1000 requests per minute, you would set the following in /etc/rc.conf.local:
inetd_flags='-R 1000'
You can set per-service limits by editing the wait/nowait
field in the service’s inetd.conf entry. Add a dot to the wait
or nowait
entry, followed by the number of times per minute you want to allow the service to be called. For example, if you have an FTP server that should be used by only a few of your friends, you could limit the server to 10 requests per minute, as follows:
ftp stream tcp nowait.10 root /usr/libexec/ftpd ftpd -US ftp stream tcp6 nowait.10 root /usr/libexec/ftpd ftpd -US
Now, if more than 10 connection requests arrive in one minute, inetd
stops servicing FTP requests for ten minutes. An attacker could still use this to knock your FTP service offline, but not to knock the entire server offline. At least this way you get to choose your failure mode and when you reach it.