| | .. footer:: $Id: tperimeter.txt,v 1.104 2006/05/02 04:22:23 tundra Exp $ |
---|
| | .. footer:: $Id: tperimeter.txt,v 1.105 2006/09/25 07:22:30 tundra Exp $ |
---|
| | |
---|
| | |
---|
| | ===================================================== |
---|
| | ``tperimeter`` - A Dynamic TCP Wrapper Control System |
---|
| |
---|
| | An internet-facing server is configured with a variety of services that |
---|
| | observe TCP Wrapper (``/etc/hosts.allow``) access control rules. It is |
---|
| | common to use this mechanism to very strictly limit which external IP |
---|
| | addresses may even attempt connection to these services. For instance, we |
---|
| | may choose to limit ``ssh` logins from IPs of hosts known to us. The |
---|
| | may choose to limit ``ssh`` logins from IPs of hosts known to us. The |
---|
| | problem with this is that legitimate users whose IP addresses may change |
---|
| | will not be able to connect. This is common when a user travels and uses |
---|
| | internet connections in airports, hotels, or other places where ``dhcp`` |
---|
| | is used for dynamic IP assignment. In this case, the user has no *a |
---|
| | priori* knowledge of what his IP address will be and thus cannot have it |
---|
| | added to ``/etc/hosts.allow`` to enable remote system access. |
---|
| | |
---|
| | ``tperimeter`` is designed to specifically address this problem. A |
---|
| | traveling user or a user whose IP address changes regularly simply logs into |
---|
| | a secure web page and informs the system of their current IP address and |
---|
| | which services they'd like to have enabled for them. ``tperimeter`` then |
---|
| | fulfills the request - typically within 5 minutes or so - and grants access |
---|
| | to the system for that service from that IP address for a small window in |
---|
| | time - again, 5 minutes it typical. This gives the user time to access the |
---|
| | desired service before TCP Wrappers once again close the system to its |
---|
| | default state. These semantics thus provide flexible remote access with |
---|
| | an automatic reset to system default access control. |
---|
| | A number of solutions to this problem have been proposed such as VPNs |
---|
| | and so-called "port knocking", but they are complex and require some |
---|
| | level of custom client code. ``tperimeter`` uses open-source tools to |
---|
| | solve the problem simply and elegantly. A traveling user or a user |
---|
| | whose IP address changes regularly simply logs into a secure web page |
---|
| | and informs the system of their current IP address and which services |
---|
| | they'd like to have enabled for them. ``tperimeter`` then fulfills |
---|
| | the request - typically within 5 minutes or so - and grants access to |
---|
| | the system for that service from that IP address for a small window in |
---|
| | time - again, 5 minutes it typical. This gives the user time to |
---|
| | access the desired service before TCP Wrappers once again close the |
---|
| | system to its default state. These semantics thus provide flexible |
---|
| | remote access with an automatic reset to system default access |
---|
| | control. |
---|
| | |
---|
| | |
---|
| | HOW ``tperimeter`` WORKS |
---|
| | ------------------------ |
---|
| | |
---|
| | ``tperimeter`` has two major components: |
---|
| | |
---|
| | 1) A *reqestor subsystem* that presents the user a web page to |
---|
| | request a "hole" be opened in the tcp wrappers for a specific |
---|
| | service from a particular IP address. This request is then |
---|
| | enqueued on disk for subsequent processing. |
---|
| | |
---|
| | 2) A *tcp wrapper rewrite* mechanism that periodically (under cron |
---|
| | control) rebuilds the ``/etc/hosts.allow`` file to reflect |
---|
| | any pending user requests queued by the requestor subsystem. |
---|
| | |
---|
| | The workflow is fairly simple: |
---|
| | |
---|
| | 1) The user logs into the ``tperimeter`` web interface and specifies |
---|
| | from what IP address and which service they want to access your system. |
---|
| | |
---|
| | 2) A cron job periodically runs to process any such pending requests by |
---|
| | dynamically rewriting the ``hosts.allow`` file. |
---|
| | |
---|
| | 3) The cron job then *deletes* the request from the ``tperimeter`` |
---|
| | queue. This means that the next time ``hosts.allow`` is rebuilt |
---|
| | by the cron job, the "hole" ``tperimeter`` opened in the |
---|
| | tcp wrappers will be *removed*. This ensures that someone |
---|
| | doesn't open a hole in the system that then stays there permanently. |
---|
| | This works fine in practice, because the tcp wrapper security |
---|
| | model operates only at the time of the initial connection request. |
---|
| | The ``tperimeter`` sematics were designed to open a hole only |
---|
| | long enough to allow the user to make the initial connection - |
---|
| | that will stay in place even after the wrappers are closed back |
---|
| | up to their default state. So, for example, you can open |
---|
| | access with ``tperimeter`` to gain access for, say, ``ssh``. |
---|
| | Once you've made the connecton, it remains connected even after |
---|
| | ``hosts.allow`` is rebuilt to its default closed state. |
---|
| | |
---|
| | The requestor subsystem consists of two parts. ``tperimeter-ui.html`` |
---|
| | is the web interface for the user to specify the service and IP |
---|
| | address they want opened. ``tperimeter.py`` is a CGI script that |
---|
| | parses the user's input and actually places it on the disk queue for |
---|
| | subsequent processing. |
---|
| | |
---|
| | ``rebuild-hosts.allow.sh`` is the tcp wrapper rewrite mechanism. |
---|
| | It is intended to be run periodically as a root cron job. Remember |
---|
| | that the "hole" ``tperimeter`` opens in your wrappers stays in |
---|
| | place until the *next time* the cron job runs. We thus recommend |
---|
| | running this script every 5 to 10 minutes to keep the window of |
---|
| | exposure small. |
---|
| | |
---|
| | The queue where ``tperimeter`` requests are initially deposited and |
---|
| | subsequently processed is transparent to the user and requires no |
---|
| | administration by the system administrator. The queue is created by |
---|
| | the web interface when a request is made. It is then subsequently |
---|
| | processed by the tcp wrapper rewrite mechanism and then *deleted* as |
---|
| | described above. |
---|
| | |
---|
| | However, there is a second queue that is of considerable importance to |
---|
| | the systems administrator. ``tperimeter`` has to know how to build |
---|
| | your "standard" tcp wrapper file - i.e., The ``hosts.allow`` entries |
---|
| | you *always* want in place regardless whether or not there is pending |
---|
| | requests for temporary access via the web interface. That's because |
---|
| | ``rebuild-hosts.allow.sh`` runs periodically under cron control and |
---|
| | rebuilds the *entire* ``hosts.allow`` file. To make this simple, |
---|
| | the list of things you always want in your ``hosts.allow`` file |
---|
| | is represented by a directory tree with zero-length files in it. |
---|
| | ``tperimeter`` uses the *names* of these directories and files to |
---|
| | build the default tcp wrapper file. This is a fairly standard |
---|
| | Unix idiom - using the file namespace to represent some larger |
---|
| | behaviorial semantic. Here's how it works: |
---|
| | |
---|
| | |
---|
| | |
---|
| | |
---|
| | HOW TO INSTALL ``tperimeter`` |
---|
| | ----------------------------- |
---|
| | |
---|
| | This section provides an overview of how ``tperimeter`` is installed. |
---|
| | It assumes you are a capable systems administrator and does not go |
---|
| | into the minutae of permissions, file ownership and so forth. |
---|
| | |
---|
| | In general, the requestor files should be owned by the web daemon |
---|
| | (usually ``www``) The wrapper rewrite script should be owned by |
---|
| | ``root``. These files should have permissions of ``700`` or possibly |
---|
| | ``740``. The file tree that describes the default wrapper |
---|
| | configuration should only be writable by ``root``. If you're |
---|
| | particularly paranoid and don't want local users to know what your |
---|
| | default wrappers look like, you can also make this file tree only |
---|
| | readable by ``root`` as well. And, of course, ``tperimeter.py`` |
---|
| | and ``rebuild-hosts.allow.sh`` should be set as executable by |
---|
| | their respective owners. |
---|
| | |
---|
| | First, you have to install the web interface. The example here |
---|
| | assumes you're using ``Apache``: |
---|
| | |
---|
| | 1) Install ``tperimeter-ui.html`` in your desired location |
---|
| | on the web site. We'll use ``/www/RemoteAccess`` for |
---|
| | our example. |
---|
| | |
---|
| | 2) You can either rename it to ``index.html`` (ugly) or |
---|
| | symlink to it (better):: |
---|
| | |
---|
| | ln -s tperimeter-ui.html index.html |
---|
| | |
---|
| | 3) You probably don't want the whole world to have access to |
---|
| | this service, so it's pretty much mandatory you use |
---|
| | password access to the system. With ``Apache`` this means |
---|
| | you'll need to install an appropriate ``.htaccess`` file |
---|
| | in this directory or otherwise secure it in your ``Apache`` |
---|
| | configuration file. |
---|
| | |
---|
| | 4) It is *highly* recommended that you require ``https`` when accessing |
---|
| | this URL. There's no point in securing your system if the password |
---|
| | is flowing in plain text over the internet. So, when you're done, |
---|
| | the user will gain access to ``tperimeter`` at:: |
---|
| | |
---|
| | https://your.fine.website.com/RemoteAccess |
---|
| | |
---|
| | Now, you need to install the CGI script: |
---|
| | |
---|
| | 1) In your web site's ``cgi-bin`` directory, create a directory |
---|
| | called ``tperimeter``. |
---|
| | |
---|
| | 2) Copy ``tperimeter.py`` to this directory. This script |
---|
| | requires a fairly recent copy of ``python`` on your system. |
---|
| | As written, it assumes that it is in ``/usr/local/bin/python``, |
---|
| | so you may need to modify the script if your system has |
---|
| | the ``python`` binary somewhere else. |
---|
| | |
---|
| | 3) Now (very important) symlink the ``.htaccess`` file you |
---|
| | created in the previous step to this directory. This |
---|
| | prevents Eeeeeeevil Hackers from running the requestor |
---|
| | script directly from a URL and bypassing your website |
---|
| | security:: |
---|
| | |
---|
| | ln -s /www/RemoteAccess/.htaccess .htaccess |
---|
| | |
---|
| | Next, you need to install the tcp wrapper rewrite subsystem: |
---|
| | |
---|
| | 1) Create the directory:: |
---|
| | |
---|
| | mkdir -p /usr/local/etc/tperimeter |
---|
| | |
---|
| | 2) Copy the ``rebuild-hosts.allow.sh`` file to this directory. |
---|
| | |
---|
| | |
---|
| | |
---|
| | Finally, you need to create a ``cron`` job that runs the tcp |
---|
| | wrapper rebuilding process regularly:: |
---|
| | |
---|
| | # Update /etc/hosts.allow to accommodate any tperimeter requests |
---|
| | 0,10,20,30,40,50 * * * * /usr/local/etc/tperimeter/rebuild-hosts.allow.sh >/etc/hosts.allow |
---|
| | |
---|
| | |
---|
| | |
---|
| | |
---|
| | |
---|
| | CUSTOMIZING ``tperimeter`` |
---|
| | -------------------------- |
---|
| | |
---|
| | The ``tperimeter-ui.html`` file provided with this distribution is |
---|
| | very simple and contains the login banner and greeting message the |
---|
| | user sees when they authenticate and gain access to the ``tperimeter`` |
---|
| | system. You can modify this file to suit your taste and otherwise |
---|
| | match the look-and-feel of your web site. |
---|
| | |
---|
| | You can modify the ``tperimeter.py`` file to indicate which services |
---|
| | may be accessed with ``tperimeter``. You can also modify this file |
---|
| | to list any IP addresses that are *never* allowed access. As a |
---|
| | practical matter, you typically only need provide access to ``sshd`` |
---|
| | for almost anything one would like to do remotely. |
---|
| | |
---|
| | |
---|
| | GOTCHAS |
---|
| | ------- |
---|
| | |
---|
| | There are a few things that can bite you when using ``tperimeter``: |
---|
| | |
---|
| | 1) The requestor/rewrite systems work off a common disk queue without |
---|
| | any access locking. This means it is theoretically possible to get a |
---|
| | race condition wherein the user queues a request just as the |
---|
| | rewrite system finishes running and deletes the queue. In this |
---|
| | case, the user's request will never be fullfilled, and they'll |
---|
| | have to request access again. |
---|
| | |
---|
| | 2) Similarly, there is no locking done when the ``hosts.allow`` file |
---|
| | is rewritten. The script that produces the new version of this |
---|
| | file simply overwrites it. There is the possibility that, at the |
---|
| | moment that file is being created, someone will attempt to access |
---|
| | your system when there are no tcp wrapper rules in effect. In |
---|
| | designing this system, it was felt that this exposure was quite |
---|
| | low. If this turns out not to be the case (remember, this is |
---|
| | EXPERIMENTAL software), then the ``hosts.allow`` rewrite |
---|
| | mechanism will have to be rewritten to make sure that there is |
---|
| | always some level of protection in place as the file is being |
---|
| | modified. If you have comments or experience with such problems |
---|
| | - or better still, can provide a better mechanism - please |
---|
| | contact us at the email address found below. |
---|
| | |
---|
| | 3) Some (many) dynamic DNS systems found in hotels, airports, and |
---|
| | the like do not properly match forward and reverse DNS entries. |
---|
| | If you use strict DNS rules in your ``hosts.allow`` file with |
---|
| | and entry like ``ALL : PARANOID : RFC931 20 : DENY``, this |
---|
| | would prevent access from such addresses even though they've |
---|
| | been granted by ``tperimeter``. For this reason, the wrapper |
---|
| | rewrite script places any ``tperimeter`` access at the beginning |
---|
| | of the ``hosts.allow`` file before your default configuration |
---|
| | statements. This should be benign, but it does have the effect |
---|
| | of circumventing your strict tcp wrapper rules and you should |
---|
| | be aware of this. If you don't like this sematic, you can |
---|
| | rewrite the ``rebuild-hosts.allow.sh`` file to suit your |
---|
| | preferences. |
---|
| | |
---|
| | 4) The ``tperimeter.py`` file is written to require full IP |
---|
| | quads when requesting access. For example, although tcp |
---|
| | wrappers allow entries like ``64.23.`` to specify a range |
---|
| | of addresses, you *cannot* enter such an IP specification via |
---|
| | ``tperimeter``. |
---|
| | |
---|
| | 5) When initially logging into the ``tperimeter`` interface, |
---|
| | the user probably does not know their "real" dynamic IP |
---|
| | address - i.e., The address they need opened by ``tperimeter`` |
---|
| | for the desired access. The dynamic IP addressing systems |
---|
| | found in hotels, airports, and self-service kiosks vary |
---|
| | considerably in their use of ``NAT`` and other address translation |
---|
| | schemes. There is a trivial solution to this problem, however. |
---|
| | Each time you log into the ``tperimeter`` system, simply |
---|
| | submit the request without the address field filled in. |
---|
| | ``tperimeter`` will report an error that includes the address |
---|
| | the request came from. This is almost always the correct |
---|
| | address to use. If you are in a given location for several |
---|
| | days, be aware that many dynamic IP systems assign a new address |
---|
| | each time you log in. So, the address you provided on your |
---|
| | first day at a hotel may not be the same one the next day. |
---|
| | For this reason, the "trick" described above should be done |
---|
| | every time you log into ``tperimeter``. |
---|
| | |
---|
| | |
---|
| | |
---|
| | SECURITY RISKS |
---|
| | -------------- |
---|
| |
---|
| | |