[OpenVPN home] [Date Prev] [Date Index] [Date Next]
[OpenVPN mailing lists] [Thread Prev] [Thread Index] [Thread Next]
Google
 
Web openvpn.net

Re: [Openvpn-users] finishing OpenVPN book - looking for input on advanced configuration examples


  • Subject: Re: [Openvpn-users] finishing OpenVPN book - looking for input on advanced configuration examples
  • From: "John A. Sullivan III" <jsullivan@xxxxxxxxxxxxxxxxxxx>
  • Date: Mon, 02 Jan 2006 12:05:07 -0500

On Fri, 2005-12-30 at 14:21 +0100, Markus Feilner wrote:
> Hello List,
> I am writing on a book on OpenVPN (almost ready...) and I would appreciate 
> everybody who could send me (or post to this list) advanced configuration 
> examples. 
> I have several examples like certificate-based authentication with 
> client-specific options (client config dir) and revoke list, advanced 
> firewall issues (masquerading the tunnel etc.), and tap-devices with DHCP 
> configuration etc. 
> Nevertheless I would love to get input or ideas of typical or non-standard 
> openvpn configurations that somebody has implemented, like e.g. examples on 
> authentication scripts or use of sophisticated skripts with openvpn.
> Thanks for the input!
> Of course any private mail will be answered, too!
> :-)
> 
We are brand new to OpenVPN and so are still exploring the
possibilities.  However, over the weekend we successfully integrated
OpenVPN into an ISCS environment (http://iscs.sourceforge.net) for
highly secure, large scale, remote access environments. It has magically
solved almost all the remaining obstacles we faced and is an ideal entry
point into an ISCS network.  First, I'll describe the practical
implications of this synthesis and then a little about how we did it.

ISCS enables us to manageably and affordably extend perimeter style
network security into the interior of the network whether between WAN
connected offices or in a core switch.  It does so with remarkable
granularity, e.g., a limited number of superusers could have access to
all systems, all users of an entire ISP could have access to five
services of the public trouble ticketing system or financial, executive
and sales departments could have access to the sales data while only
finance and executive have access to the financial data.

It also moves the access control decision from the gateway protecting
the resource to the gateway protecting the accessor (user).  The result
is that we can use extended and out-of-band forms of user authentication
(e.g., X.509 certificates, RADIUS, Active Directory, LDAP, SecureID
tokens) throughout the entire WAN without resorting to spoofable,
virtual IP addresses or requiring access to each individual gateway.

Let me illustrate practically.  Let's say we have an ISCS policy where
anyone with a X.509 DER_ASN.1_DN where O=MyCompany and OU=Executive has
access to Strategic Market Data, R&D and Financial Data.  Financial Data
is in five different services in New York, R&D uses 18 services spread
between Frankfurt and Bangalore while Strategic Marketing uses eight
services between Paris, New York and Tokyo.  Non OpenVPN/ISCS systems
would handle this either of two ways.

1) Use the extended authentication credentials on each of the gateways
protecting New York, Paris, Tokyo, Bangalore and Frankfurt - a
management nightmare to manage all those separate connections for every
user.

2) Connect to a centralized RAS gateway with the extended credentials
and then be assigned a virtual IP address.  Since the access control
decisions are made on the gateways which protect the resources, they
must make their decisions based upon the IP address and not the extended
credentials.  That relegates us to spoofable, IP address security.

With OpenVPN/ISCS, a user can connect to any gateway and present their
extended credentials.  They only need to connect to one gateway.  Since
all ISCS systems are "loosely aware" of the others and the access
control decision is made on the gateway protecting the accessor and not
the resource, the user sends their packets to the OpenVPN gateway. The
OpenVPN gateway makes an access control decision based upon their
extended authentication credentials and then forwards or drops the
packet appropriately.  All access control decisions throughout the
entire WAN are made based upon the extended user credentials but the
user can connect to just one gateway.

How do we do it?

The first step is organizing the access control rules.  Although ISCS is
not finished, we have used it in limited production.  A recent typical
client has roughly one dozen sites in the US and Europe with roughly
thirty servers.  To implement granular, interior security using typical
monolithic firewall rules (e.g., iptables -A FORWARD -s 10.1.1.0/24 -d
10.1.2.5 -p tcp --dport 80 -j ACCEPT) would have required roughly 80,000
rules in this environment.

With ISCS, we use the same firewall tools like iptables but use them
differently.  We create modular rather than monolithic rules which
evaluate source separately from destination and then only evaluate the
pertinent rules.  Consequently, the rule set reduces to about 8000 rules
of which only a small subset need to be traversed by any one packet.
That's still too complicated so we then "magically" eliminate order
dependence to reduce human error.  Finally, we highly abstract the rule
sets into high level policies -- about 15 in this case to describe the
entire security environment.  As a result, the entire security
configuration can be set up in a couple of hours of dragging and
dropping and most of that is just defining the accessors (users) and
resources.  The actual policies took less than half an hour to
implement.

The modularity and abstraction are achieved through a judicious use of
user defined chains.  Thus, the OpenVPN/ISCS combination works with any
firewall that supports user defined chains such as iptables.  The key,
and the part that OpenVPN does so well, is to channel the remote access
users into the appropriate chain based upon their extended credentials
when they connect.  Here is an example of the client-connect script for
X.509 DN based access.  The client-disconnect script is almost
identical:

#!/bin/sh
IF_TYPE=tun+
PEER_ADDR=$ifconfig_pool_remote_ip
PEER_ID=$tls_id_0
PEER_CA=$tls_id_1
PEPDIR=/etc/PEP
. $PEPDIR/DNRead A
exit 0

The magic is in the DNRead script.  This script is a little more
complicated.  To fully understand what it is doing, one must understand
the chaining structure of ISCS.  This is described in the "PEP Packet
Flow" document in the devel-docs section of the ISCS CVS on SourceForge.
Once an also find a fully commented version of the script in the PEP
directory of the ISCS CVS.

#!/bin/sh
#
# ISCS DEVELOPMENT TEAM:  DO NOT DIRECTLY EDIT THIS FILE.  EDIT
DNRead.comments, STRIP THE COMMENTS AND SAVE THE STRIPPED VERSION AS
DNRead
#
# Copyright (C) 2003 - 2005  John A. Sullivan III
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
USA.
#
# e-mail: jsullivan@xxxxxxxxxxxxxxxxxxx
if [[ "$1" != [AD] ]] # make sure we've passed the needed parameters
from X509updown
then
        echo "Needed action parameter not passed to iptables - aborting
connection!!!!!"
        exit 13
fi
DelimitedID="$PEER_ID,"  # We need to add a , on the end or the match
test for the last field will not work
case $1 in
        "A" )
                iptables -I VPN_ALLOW 1 -s "$PEER_ADDR" -j RETURN
                ;;
        "D" )
                iptables -D VPN_ALLOW -s "$PEER_ADDR" -j RETURN
                ;;
        * )
                echo "Needed action parameter not passed to iptables -
aborting connection!!!!!"
                exit 13
                ;;
esac

AccessGroups=""
IFSORIG=$IFS
if [ -s $PEPDIR/DNListDENY ]
then
        IFS=";"
        while read DN CA GROUP
        do
                if [ $PEER_CA != $CA ]; then continue; fi # No need to
process if this ID is from a different CA
                match="true"
                OIFS="$IFS"
                IFS=",/" # WE MAY NEED TO ADD / AS A DELIMETER SINCE IT
IS A LEGAL X.509 FIELD DELIMETER

                for field in $DN

                do
                        if [ "${field##*=}" == "*" ]; then continue; fi
# Don't test if the field is set to *

                        if [ "${DelimitedID/"$field"\//}" ==
"${DelimitedID}" ]
                        then
                                match="false"
                                break
                        fi
                done
                IFS="$OIFS"
                if [ "$match" != "false" ];then AccessGroups="$GROUP;
$AccessGroups";fi  # Build the AccessGroups string if we didn't have a
mismatch
        done < $PEPDIR/DNListDENY
        #
        IFS=$IFSORIG
        until [ "$AccessGroups" == "${AccessGroups#;}" ]
        do
                AccessGroups="${AccessGroups#;}"
        done
        IFS=";"
        declare -a group
        group=($AccessGroups)  # Create an array to hold the individual
elements of the string
        while [ "${group[0]}" != "" ]
        do
                count=2
                countmax=${#group[@]}
                while [ $count -lt $countmax ]
                do
                        if [ ${group[1]} == ${group[$((count+1))]} ]  #
If it is a duplicate
                        then
                                unset group[$count]
                                unset group[$((count+1))]
                        fi
                        let "count+=2"
                done
                if [ "${group[0]}" != "" ]
                then
                        iptables -$1 ACCESS_GROUPS_DENY -s "$PEER_ADDR"
-j "${group[1]}_DENY"  # We will call this from updown with either a A
or D
                        unset group[0]
                        unset group[1]
                fi
                group=(${group[@]})
        done
fi
AccessGroups=""
if [ -s $PEPDIR/DNList ]
then
        IFS=";"
        while read DN CA GROUP
        do
                if [ $PEER_CA != $CA ]; then continue; fi # No need to
process if this ID is from a different CA
                match="true"
                OIFS="$IFS"
                IFS=",/" # WE MAY NEED TO ADD / AS A DELIMETER SINCE IT
IS A LEGAL X.509 FIELD DELIMETER

                for field in $DN
                do
                        if [ "${field##*=}" == "*" ]; then continue; fi
# Don't test if the field is set to *

                        if [ "${DelimitedID/"$field"\//}" ==
"${DelimitedID}" ]
                        then
                                match="false"
                                break
                        fi
                done
                IFS="$OIFS"
                if [ "$match" != "false" ];then AccessGroups="$GROUP;
$AccessGroups";fi  # Build the AccessGroups string if we didn't have a
mismatch
       done < $PEPDIR/DNList
        IFS=$IFSORIG
        until [ "$AccessGroups" == "${AccessGroups#;}" ]
        do
                AccessGroups="${AccessGroups#;}"  # Eliminate leading ;
caused by
        done
        IFS=";"
        group=($AccessGroups)
        while [ "${group[0]}" != "" ]
        do
                count=2
                countmax=${#group[@]}
                while [ $count -lt $countmax ]
                do
                        if [ ${group[1]} == ${group[$((count+1))]} ] ||
[ ${group[0]} != ${group[0]#${group[$count]}\/} ]  # If it is a
duplicate or hierar
                        then
                                unset group[$count]
                                unset group[$((count+1))]
                        else
                                if [ ${group[$count]} !=
${group[$count]#${group[0]}\/} ] #If count is a child of 0, that is 0 is
a hierarchical duplicate
                                then
                                        unset group[0]
                                        unset group[1]
                                        break
                                fi
                        fi
                        let "count+=2"
                done
                if [ "${group[0]}" != "" ]  # Am I here because I am
hierarchically redundant and broke the loop or because I am
hierarchically unique
                then
                        iptables -$1 ACCESS_GROUPS -s "$PEER_ADDR" -i
$IF_TYPE -j "${group[1]}"
                        unset group[0]
                        unset group[1]
                fi
                group=(${group[@]})
        done
fi
IFS=$IFSORIG 

Here is a sample of a simple DNList file to associate the DNs with the
Access Groups:

O=Atlas,OU=Eng;/C=US/O=Atlas/OU=PKI/CN=AtlasTestCA;Eng;Eng

We are very interested in pursuing this further.  For example, the
combination of iptables, openwan, OpenVPN and ISCS gives us something
more powerful that the most expensive commercial systems available
anywhere at any price and with the best of IPSec and SSL VPNs.  This is
potentially more powerful and more manageable than any $80,000 device
from F5 or Aventail and more flexible and easier to manage than a six
figure Solsoft or CheckPoint Provider1 system.

However, it is a huge undertaking.  If anyone is interested in taking
this further either as pure open source or as a commercial product using
open source technologies, please let me know.  I look forward to seeing
the book - John
-- 
John A. Sullivan III
Open Source Development Corporation
+1 207-985-7880
jsullivan@xxxxxxxxxxxxxxxxxxx

Financially sustainable open source development
http://www.opensourcedevel.com


____________________________________________
Openvpn-users mailing list
Openvpn-users@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/openvpn-users


Warning: require_once(../../../archive_common.php) [function.require-once]: failed to open stream: No such file or directory in /home/openvpn/domains/openvpn.net/public_html/archive/openvpn-users/2006-01/msg00023.html on line 509

Fatal error: require_once() [function.require]: Failed opening required '../../../archive_common.php' (include_path='/usr/local/lib/php') in /home/openvpn/domains/openvpn.net/public_html/archive/openvpn-users/2006-01/msg00023.html on line 509