...making Linux just a little more fun!

Joey's Notes: TCP Wrappers on Red Hat Enterprise Linux

By Joey Prestia

Joey's Notes image


In information technology, security is never a result of "just one thing"; in other words, there is not a panacea for digital security. The best security practices result from multiple applications and practices to protect your system, such as iptables firewalling, Mandatory Access Controls such as SELinux, and Discretionary Access Controls such as permissions and rights. Last, consider coupling TCP Wrappers to complement your firewall rules.

[ As security guru Bruce Schneier often points out, "security is not a product; it's a process". The largest part of security is not even related to the tools you use; it's the awareness of the continual necessity of staying informed, updated, and at the top of the game. The tools are one of the means to that end. -- Ben ]


TCP Wrappers work in the manner of a host-based Access Control List. They are used to filter out network access to Internet Protocol (IP) servers that are running Linux, Unix, or BSD. They will allow host or network addresses to be used as indicators to filter and implement a layer of access control. They additionally extend the capabilities of xinetd-controlled daemons. By using this technique, connection attempts can be logged, restricted, and messages returned. This can add an extra layer of security in your environment. TCP Wrappers also allow run-time reconfiguration without restarting or reloading the services they protect.


Connections that are permitted are simply allowed; those that are denied will fail. Some services will report a particular error message, as do SSH and vsftpd. Here is an example of an exchange using TCP Wrappers to protect services.

An example of SSH being disallowed from the client's perspective:

[root@alien ~] ssh root@
ssh_exchange_identification: Connection closed by remote host

An example of FTP being disallowed:

[root@alien ~] ftp
Connected to
421 Service not available.

How TCP Wrappers Work

When connections are attempted to a service using TCP wrappers, the following occurs (the following steps are important because order matters, and rules are processed line-by-line):

  1. The process will check the file /etc/hosts.allow. Access will be granted if a match is found in the /etc/hosts.allow file.
  2. The process will check the file /etc/hosts.deny. Access will be denied if a match is found in the /etc/hosts.deny file.
  3. In the event no matching rules apply, access will be granted.

To uncover what processes/daemons use TCP Wrappers, do the following:

strings -f <program_name> | grep hosts_access

An example of output from this command:

[root@alien ~] strings -f /usr/sbin/* | grep hosts_access
/usr/sbin/in.tftpd: hosts_access
/usr/sbin/sshd: hosts_access
/usr/sbin/stunnel: hosts_access
/usr/sbin/stunnel: See hosts_access(5) manual for details
/usr/sbin/tcpd: hosts_access_verbose
/usr/sbin/vsftpd: hosts_access
/usr/sbin/xinetd: hosts_access

[root@alien ~] strings -f /sbin/* | grep hosts_access
/sbin/portmap: hosts_access_verbose

Implementing TCP Wrappers

When using TCP Wrappers, bear certain things in mind. First, order matters. Second, the search will stop with the first match. Any changes to /etc/hosts.allow or /etc/hosts.deny take effect immediately without having to restart any services. As with iptables, order is crucial in these rules. Let's take a look at the commands for setting rules. The basic formats of commands in /etc/hosts.allow and /etc/host.deny are:

daemon_list : client_list  : shell_command 

daemon_list - This is a list of one or more daemon process names or wildcards
client_list - This is a list of one or more host names, host addresses, patterns or 
              wildcards that will be matched against the client host name or address.

Examples of /etc/hosts.allow and /etc/hosts.deny rules:


# hosts.allow   This file describes the names of the hosts 
#               allowed to use the local INET services, as decided
#               by the '/usr/sbin/tcpd' server.
# My new rule below
sshd : 


# hosts.deny    This file describes the names of the hosts 
#               *not* allowed to use the local INET services, as decided
#               by the '/usr/sbin/tcpd' server.
# The portmap line is redundant, but is left to remind you that
# the new secure portmap uses hosts.deny and hosts.allow.  In particular,
# you should know that NFS uses portmap!
# My new rule below

Observe the results of my new rules:

From station14.example.com (

Last login: Tue Apr  7 06:45:09 2009 from station14
[root@station15 ~]#	

From alien.example.com (

[root@alien ~]# ssh
ssh_exchange_identification: Connection closed by remote host
[root@alien ~]#


This wildcard will match all services or hosts.
This matches any host that does not contain a dot character.
This matches any unknown user, and matches any host whose name or addresses are unknown. Remember that host names may be unavailable if name server problems are encountered.
This matches any known user, and matches any host whose name and address are known. Remember that host names may be unavailable if name server problems are encountered.
This will match any host whose name does not match its address.
This is intended to be used in the form: list_1 EXCEPT list_2. This operator matches anything that matches list_1 unless it matches list_2. EXCEPT can be used in daemon_lists and in client_lists.

(WARNING: Always leave a blank line containing an 'enter' character in both /etc/hosts.allow and /etc/hosts.deny! Simply go to the end of your last line in insert mode within the vi editor, and hit the carriage return (<enter>) key. Failure to perform this step may cause unwanted consequences with TCP Wrappers.)

Here are some rule examples included below. Which file you put the rule in determines how the rule works, unless you add an 'allow' or a 'deny' at the end of the rule.

sshd : .example.com
vsftpd : 192.168. 
sshd : station1.example.com : allow
sshd : station15.example.com : deny
vsftpd : ALL EXCEPT *.hacker.org

Using Twist

The 'twist' directive is used to replace the service with a selected command. It is commonly used to set up honeypots. Another use for it is to send messages to connecting clients. The 'twist' command must be used at the end of a rule line. Here is an example of using 'twist' in /etc/hosts.deny to send a message to a host that has abused FTP services, via the echo command:

Example using twist in /etc/hosts.deny

vsftpd : station6.example.com \
: twist /bin/echo "Service suspended for abuse!"

Using Spawn

The 'spawn' directive causes a child process to be launched. This can be very handy when used to generate special access log files. You can also run custom scripts in the background with this directive that will be unseen by the user. In this example, we will create a timestamp in a custom log so we can monitor FTP connections:

Example in /etc/hosts.allow

vsftpd : .example.com  \
: spawn /bin/echo $(/bin/date) access granted to %h>>/var/log/ftp_access.log 

These are what character expansions you can take advantage of, when used in either /etc/hosts.allow or /etc/hosts.deny.


       The following expansions are available within shell commands:

       %a    The client host address

       %A    The server's host address

       %c    Client information: user@host, user@address,  a  host  name,  or just an address

       %d    The daemon process name

       %h    The client  host name or address, if the  host  name  is unavailable

       %H    The server host name or address, if the  host  name  is unavailable

       %n    The client host name (or "unknown" or "paranoid")

       %N    The server host name (or "unknown" or "paranoid")

       %p    The daemon process id

       %s    Server  information: daemon@host, daemon@address, or just a daemon name

       %u    The client user name (or "unknown")

       %%    Expands to a single "%" character.

       (Characters in % expansions that may confuse the shell are replaced by underscores)


TCP Wrappers make a great complement to your current security measures. Remember: always thoroughly test any security implementation before moving to a production platform!


Talkback: Discuss this article with The Answer Gang


Joey was born in Phoenix and started programming at the age fourteen on a Timex Sinclair 1000. He was driven by hopes he might be able to do something with this early model computer. He soon became proficient in the BASIC and Assembly programming languages. Joey became a programmer in 1990 and added COBOL, Fortran, and Pascal to his repertoire of programming languages. Since then has become obsessed with just about every aspect of computer science. He became enlightened and discovered RedHat Linux in 2002 when someone gave him RedHat version six. This started off a new passion centered around Linux. Currently Joey is completing his degree in Linux Networking and working on campus for the college's RedHat Academy in Arizona. He is also on the staff of the Linux Gazette as the Mirror Coordinator.

Copyright © 2009, Joey Prestia. Released under the Open Publication License unless otherwise noted in the body of the article. Linux Gazette is not produced, sponsored, or endorsed by its prior host, SSC, Inc.

Published in Issue 162 of Linux Gazette, May 2009