Added most of final content.
1 parent e0dbbc5 commit c2123dad7afd99f5650f39eafe92e1d10991939f
@tundra tundra authored on 25 Sep 2006
Showing 1 changed file
View
259
tperimeter.txt
.. 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
--------------