Linux access control using TCP WRAPPERS
Maintaining a good access control list is a nice practice, that must be adopted by any Linux system administrator. This can be achieved with the help of multiple tools. An additional layer of security after your firewall and before your service daemon is a good approach, because even if your firewall is breached, the attacker still has to overcome the extra wrapper you have applied to protect your service.
In some cases you can also protect daemons that does not have an in built security mechanism for maintaining access list. TCP Wrapper is one such wonderful tool that's widely used in Linux/Unix operating systems for maintaining filter's based on the source of the request. Initially when Wietse Venema came up with TCP Wrappers, it was only applicable to services handled by inetd daemon, these days it can be made to work with almost all available internet protocol based services.
To get an idea about the work flow of TCP wrapper, the below shown diagram might prove helpful.
An important fact to note from the above diagram is that "TCP Wrapper comes in between the firewall and your network service"
Another thing to keep in mind is "If you have xinetd configured, then TCP Wrapper will pass control to xinetd after its filtering is done, which will again pass through xinetd specific filters."
TCP Wrapper is by default installed on most of the Linux distributions out there. In order to verify, you can query your RPM database as shown below.
[root@myvm1 ~]# rpm -qa | grep tcp_wrappers
tcp_wrappers-7.6-40.6.el5
[root@myvm1 ~]#
An important shared library file that this package installs is libwrap.so.
[root@myvm1 ~]# ls /usr/lib/libwrap.so
/usr/lib/libwrap.so
[root@myvm1 ~]#
Any service that requires its access filtering to be done by TCP Wrapper, then that service binary needs to be compiled with libwrap.so file. Most of the services available are by default using libwrap.so library(which means that particular service will work with TCP Wrapper.)
For more about shared libraries.
Read: Shared Libraries in Linux
[root@myvm1 ~]# ldd /usr/sbin/vsftpd | grep libwrap
libwrap.so.0 => /lib/libwrap.so.0 (0x00add000)
[root@myvm1 ~]#
In the above example i have used "ldd" command to query library files used by ftp(file transfer protocol) service binary(vsftpd), and searched for libwrap.so .
As shown in the above example, you can always query a binary of your interest with ldd command to verify whether it supports TCP Wrapper or not.
Before going ahead with the configuration of TCP wrappers let's first make some points which are advantages of TCP wrapper and some points which are disadvantages of TCP wrapper.
Things to Note about TCP Wrapper
- One of the main plus points of TCP wrapper is the fact that, it can be used to manage multiple TCP services all in one place.
- Logging of acceptance and denial of incoming requests through syslog.
- Easy and simple management of the configuration using only two files called hosts.allow and hosts.deny
- You can modify the access list for a particular TCP service, without restarting the service. TCP wrapper behaves like plug and play. In fact the effect of the modification is very immediate.
- You can only control address based access list using tcp wrappers. Which means you will not get the flexibility and other complex options that a full fledged firewall like iptables supports.
- The two end points of the communication (the service and the client) are unaware of the presence of TCP wrapper in between them
- the simplicity of TCP wrapper has also caused some confusion for many administrators. This is mainly because of two files to mention allow and deny rules.
- Also "one rule per line" in configuring hosts.allow and deny are prone to cause mistakes, which will result in omitting that particular rule.
Linux TCP Wrapper Configuration
Like any other Linux service, TCP wrapper is also configured using normal text files. Below mentioned two files are used for it.
- /etc/hosts.allow
- /etc/hosts.deny
Understanding the order in which these files are read, on receiving a client request, is very important.
A server with TCP wrapper configured, on receiving the request for a particular service from a client will first go through /etc/hosts.allow file. If it finds an entry for that particular service for that particular source address(address of the client), It will allow the connection.
Point to note in the above process is that if a host is allowed first in /etc/hosts.allow and is then denied in /etc/hosts.deny, the host will be allowed. Because once an allow entry for a source address is found in /etc/hosts.allow, the server will allow the connection without even bothering about /etc/hosts.deny.
So always keep in mind that the file /etc/hosts.allow is always processed first by the system
The order in which these files are configured is also very important. The first matching rule for a request is only applied, rest is ignored.
The format followed by the hosts file is as below:
Service/Daemon Name : Client/Host Address : [<other options> : <options>]
Service/Daemon Name
This is the list of services or daemon names. Each of them are separated by coma. The keyword "ALL" can also be used to specify all services that uses TCP wrappers.
Client/Host Address
This is nothing but a list of hostnames or ip addresses which needs to passed through the rule.
<other options>
You can specify actions to do with the help of options. We will look what actions can be done, whenever a rule is matched.
TCP wrapper Sample configurations
Lets see some example configurations of TCP Wrapper.
[root@myvm1 ~]# cat /etc/hosts.allow
ALL: .slashroot.in
[root@myvm1 ~]#
As i mentioned earlier "ALL" acts as a wildcard for all services that are compatible with tcp wrappers. In the above shown example, it will allow all requests to the machine from "slashroot.in" domain.
Also note the fact that in the above case "hosts.deny" file is empty. Even if you add the same entry in hosts.deny, it will not be of any use, because hosts.allow is processed first.
Deny requests for a particular service
[root@myvm1 ~]# cat /etc/hosts.allow
sshd: .slashroot.in
[root@myvm1 ~]#
In the above shown example sshd service is only allowed from "slashroot.in" domain.
[root@myvm1 ~]# cat /etc/hosts.allow
vsftpd: .slashroot.in
[root@myvm1 ~]#
In the above shown example, vsftpd service is only allowed from slashroot.in domain.
Again keep the fact in mind that a conflicting entry in hosts.deny will be ignored, because hosts.allow is processed first and if a request pattern is allowed, it will never process hosts.deny file at all.
Also you can deny these same requests as shown in the above examples, by making the same entry in hosts.deny, but in that case your hosts.allow must be empty or else must not contain similar rule for allowing.
Let's see another pattern for allowing and denying hosts.
[root@myvm1 ~]# cat /etc/hosts.allow
ALL: 172.16.
[root@myvm1 ~]#
In the above example all hosts with the ip address 172.16.*.* is allowed to make connections to all TCP wrapper based services on the hosts.
In the above example if you add ALL: 172.16.104.54, in the file hosts.deny will not be of any use, because you have already allowed all requests from 172.16.*.* in hosts.allow file.
You can also make the same entry with IP and subnet mask based style, as shown below.
[root@myvm1 ~]# cat /etc/hosts.allow
ALL: 172.16.0.0/255.255.0.0
[root@myvm1 ~]#
If you want to deny or allow a large number of hosts, then you can also do that by mentioning the list of ip/hostnames in another file and pointing to that file in /etc/hosts.allow.
[root@myvm1 ~]# cat /etc/hosts.allow
sshd: /etc/sshd.hosts
[root@myvm1 ~]#
In the above rule, an important point to note is that the rule starts with a "/", mentioning the path for the file.
Previously we saw that you can allow/deny an entire domain, but what if you want to make exceptions to some hosts on that domain.
[root@myvm1 ~]# cat /etc/hosts.allow
ALL: .slashroot.in EXCEPT example.slashroot.in
[root@myvm1 ~]#
In the above example all hosts from slashroot.in domain will be allowed except example.slashroot.in.
In the exact similar manner, you can also deny one particular service, after allowing the rest to a group of hosts or domain, as shown below.
[root@myvm1 ~]# cat /etc/hosts.allow
ALL EXCEPT sshd: 172.16.0.0/255.255.0.0
[root@myvm1 ~]#
In the above shown method all hosts from 172.16.0.0 network are allowed for all the services except ssh.
The <options> field in the tcp wrapper entry can also be used to make all entry in one files itself(Yeah that's correct, you can use a single file for accept and deny rules. This is the best method to avoid confusion.), the syntax for such entry should be made, by taking an extra care.
[root@myvm1 ~]# cat /etc/hosts.deny
vsftpd : example1.slashroot.in : allow
sshd : example1.slashroot.in : deny
sshd : example2.slahroot.in : allow
[root@myvm1 ~]#
In the above example, i have made the entry of both allowing and denying connections to service in hosts.deny file(i have kept my hosts.allow file empty). "allow" and "deny" are part of the options filed in the entry.
Another important fact that must be kept in mind is the length of the access rule that you are making in tcp wrapper files.
One rule per line is the way it must be made. Otherwise rules might get skipped without applying them while processing. There is a workaround for this problem, by including "/", for all those rules that are lengthy. An example is shown below.
[root@myvm1 ~]# cat /etc/hosts.allow
vsftpd : 172.16.103.150 \ : spawn /bin/echo ftp access prohibited>>/var/log/ftp.log \ : deny
[root@myvm1 ~]#
In the above example, we have used backslashes to denote that the rule is one line. Also we have spawned echo process to make a text redirect to ftp log file. This kind of actions can be taken with the help of options field as shown above.
Like we have used spawn to echo some text content in ftp log, this can be made very detailed log with the help of some options.
[root@myvm1 ~]# cat /etc/hosts.allow
vsftpd : 172.16.103.150 \ : spawn /bin/echo %c %h %p %u ftp access prohibited>>/var/log/ftp.log \ : deny
[root@myvm1 ~]#
In the above example, i have used
%c for complete client information like username and hostname
%h is used to determine client's ip address
%p is used to log process id of the process
%u is used for username of the client who is requesting the service.
You can make much more interesting things to trigger on matching a rule, using the same spawn method and redirection.
A complete mannuel entry for TCP wrapper can be found by running the below command as shown below.
[root@myvm1 ~]# man hosts_options
[root@myvm1 ~]#
Hope this article was helpful in understanding the concept of TCP wrappers in Linux.
Comments
Security
Hi,
Nice article. Just wanted know that, Can hacker bypass the host.allow or deny?
If yes how and if no how?
Thanks,
Savy.
Wrappers
Nice Article. Keep posting new one's ........
best topic
it helped me a lot,
Thank you
Very Good Article..
Very Good Article...Thoroughly explained..
Add new comment