5. Implementation
Next Previous Contents
5. Implementation
5.1 Certificate Authority.
You will need this if you intend to use any of the following: stunnel/PPP, OpenVPN in TLS mode, IPSEC when the client is on coming from a dynamic address.
If you already have a CA you need to evaluate who has your certificates. It is important to note that some software may ignore the x509 fields responsible for certificate use so a certificate explicitly issued only for code signing may end up being usable for authentication versus your VPN system. If in doubt, create a new authority.
Create the necessary directory structure
Choose your own directory location. Depending on the number of
certificates to deal with and local policy - either /usr/local/etc/ssl
or use the existing config under /etc/ssl (all examples use /etc/ssl
to be more readable). Create the necessary subdirectories and files:
mkdir /etc/ssl/certs mkdir /etc/ssl/crl mkdir /etc/ssl/newcerts mkdir /etc/ssl/private echo "01" > /etc/ssl/serial touch /etc/ssl/index.txt
Prepare an openssl.conf file
The primary reason for doing this is to avoid having to enter your company name, location, etc every time you run openssl. Here is a sample config based on the SSL Cookbook. If you are starting from an existing one only edit the files marked in bold and leave the rest to their defaults.
RANDFILE = /etc/ssl/.rand #################################################################### [ ca ] default_ca = CA_default #################################################################### # The default ca section #################################################################### [ CA_default ] dir = /etc/ssl # Where everything is kept certs = $dir/certs # Where the issued certs are kept crl_dir = $dir/crl # Where the issued crl are kept database = $dir/index.txt # database index file. new_certs_dir = $dir/newcerts # default place for new certs. certificate = $dir/cacert.pem # The CA certificate serial = $dir/serial # The current serial number crl = $dir/clr/crl.pem # The current CRL private_key = $dir/private/cakey.pem # The private key #x509_extensions = x509v3_extensions # The extentions to add to the cert default_days = 365 # how long to certify for default_crl_days= 30 # how long before next CRL default_md = md5 # which md to use. preserve = no # keep passed DN ordering # A few different way of specifying how similar the request should look # For type CA, the listed attributes must be the same, and the optional # and supplied fields are just that :-) policy = policy_match # For the CA policy [ policy_match ] countryName = match stateOrProvinceName = optional localityName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] default_bits = 1024 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = UK countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = localityName = Locality Name (eg, city) localityName_default = Cambridge organizationName = Organization Name (eg, company) organizationName_default = SigSegV organizationalUnitName = Organizational Unit Name (eg, section) organizationalUnitName_default = commonName = Common Name (eg, YOUR name) commonName_default = sigsegv.cx commonName_max = 64 emailAddress = Email Address emailAddress_max = 40 emailAddress_default = root-ca@sigsegv.cx [ req_attributes ] challengePassword = A challenge password challengePassword_min = 4 challengePassword_max = 20
Note that the v3 x509 extensions have been commented out. I have had some trouble with them and racoon once upon a time and haven't bothered to test ever since. They are not used by any of the parties concerned anyway.
CA certificate
You will need the CA certificate for stunnel/PPP, IPSEC using x509 authentication and OpenVPN/TLS. If you want to use the Windows native IPSEC and SSL implementations you will also have to convert the cert to the p12 format in order for Windows to read it.
openssl req -new -x509 -keyout /etc/ssl/private/cakey.pem -out /etc/ssl/cacert.pem openssl pkcs12 -export -in /etc/ssl/cacert.pem -inkey private/cakey.pem -nokeys -out CA.p12
As a result you will have two PEM format files for your Certificate Root and a PKCS#12 file which you can import into a windows system. Keep in mind that if you do not use the -nokeys switch, the resulting PKCS#12 file will contain your CA private key as well. At least with OpenSSL 0.9.6c under debian-woody this option did not work correctly and the keys are present in the PKCS#12 file (according to windows, I have not retested lately). If your private key has been kept for any reason it can be easily stripped by exporting it under windows and reimporting it back in.
Client and Server certificates
These are essentially the same.
openssl req -new -keyout key.pem -out cert.pem -days 360 cat cert.pem key.pem > cert-req.pem openssl ca -policy policy_match -out cert-signed.pem -infiles cert-req.pem
Note that if you intend to change expiry dates or do any other similar changes while retaining the same certificate you will need to keep the certificate request.
If you intend to use the certificate on a server or for unattended operation you will have to decrypt the private key. This is essential for racoon and necessary for most OpenVPN modes of operation.
openssl rsa -in cert-key.pem -out cert-key-decrypted.pem
If you intend to use the certificate on a windows client using the windows native IPSEC functionality you will have to convert the certificate to its P12 form.
openssl pkcs12 -export -in cert-signed.pem -inkey key.pem -out cert.p12
5.2 BSD Kernel and setting policies
Kernel options
I will suggest using a BSD which is as recent as possible, best of all 5.x. I have been happy with 4.x IPSEC stack, but I have to admit that especially the IKE and the interaction between racoon and the kernel when expiring SAs is not 100% reliable. With 5.x you also get the possibility to do proper ipfw filtering on IPSEC packets using the ipsec tag in ipfw2.
You will need to enable the following in the config file:
options IPSEC #IP security options IPSEC_ESP
You will most likely need IPFIREWALL or IPFILTER. Keep in mind
that IPFILTER NAT in some configurations may not be compatible with
using IPSEC.
If you intend to use OpenVPN you will also most likely need
options BRIDGE device tap
If you intend to use for infrastructure any VPN technology which
attempts reliable delivery like stunnel/PPP, OpenVPN in TCP mode
or PPTP with MPPE encryption you are likely to need to limit the
contents of the tunnel to a rate which is lower then the smallest
known bottleneck on the way. This should be sufficient to avoid most
mss and window scaling problems like the ones described
here. The best
way to this is using the ALTQ framework. Unfortunately its theory
and operation is a topic worth a 200+ page book. For the simpler
cases you may also get away by using
options DUMMYNET
and configuring ipfw rules to limit the bandwidth of the contents of the tunnel to a value known not to cause congestion.
Setting Policies with Setkey
If you intent to use IPSEC you will most likely have to specify what needs to be handled by the kernel IPSEC functionality and how would you like it handled. This is done using the setkey utility. For example the following two statements will require any PPTP Control traffic
spdadd 1.2.3.4[1723] 0.0.0.0/0 tcp -P out ipsec esp/transport//require; spdadd 0.0.0.0/0 1.2.3.4[1723] tcp -P in ipsec esp/transport//require;
It is important to note that unless one of the sides is using "generate policy" (or its equivalent) the policies do not need to be the same. They may be quite different, but if the traffic matches policies at both end the connection will work correctly.
If you want to interoperate versus non-BSD derived systems you will also most likely need to adjust the following sysctl
net.key.preferred_oldsa=0
Prior to 5.2 it is misspelled as net.key.prefered_oldsa. If there are more then one SA for a specific policy this sysctl controls which one is used - the older or the newer one. The default behaviour is to use the older one which is different from nearly any non-BSD implementation. If you leave this one at default links will be negotiated and fail at random later if one of the systems decide to rekey. You are also likely to have problems after reboots and restarts.
5.3 Ports Providing VPN Functionality
Some of the VPN technologies on BSD are provided by a packages from the ports collection. It is important to note that they have their own development lifecycles and you have to follow them separately and check their own bugtracking systems and mailing lists for any problems.
RACOON
It is under /usr/ports/security/racoon. In most cases a simple
make ; make install should be enough. The only problem recently has
been the omission of -L ../libipsec/ from the racoon Makefile. If
it compiles, but fails to link you will need to make that alteration
by hand.
Racoon is known for its offensive programming and some racoon FreeBSD snapshots have been known to have problems. Make sure that the version is up to date and check for any bug reports filed versus it on www.kame.net
One of the major pluses of racoon compared to other IKE software is the very good debug output. If you run into a problem versus another implementation you always have the best chance to understand it debugging on the racoon side. From my experience this has been valid for troubleshooting versus Cisco, Firewall1, FreeSWAN, Windows and several other implementations.
Racoon configuration consists of three main parts: global declarations, authentication sections and Security Association (SA) descriptions.
The global section describes where racoon finds its shared keys, certificates, its debug as well as some timing parameters and interfaces. The shared keys are a file which is reasonably well described in the racoon manual page so I will not describe them here. The certificates are stored in a flat structure in a directory and looked up using their hashes. As a result your certificates must be either renamed to their hashes
mv demon.pem `openssl x509 -noout -hash -in demon.pem`.0
or have symlinks to their standard x509 hash format generated as follows:
ln -s demon.pem `openssl x509 -noout -hash -in demon.pem`.0
Here is an example of a racoon config which supposedly makes
racoon only listen on IP address 3.4.5.6, output reasonable level
of debug output, use the /usr/local/etc/racoon/certs for certificates
and /usr/local/etc/racoon/racoon.keys for shared keys.
path pre_shared_key "/usr/local/etc/racoon/racoon.keys" ;
path certificate "/usr/local/etc/racoon/certs" ;
log debug;
listen {
isakmp 3.4.5.6;
strict_address;
}
And here immediately comes a caveat: while listening on 3.4.5.6 racoon at least as of 2003 snapshots will use 3.4.5.6 only when responding to connections. If it is originating the connection it will use the address of the interface facing in the relevant direction as you can see from one of the bugs I have filed a while ago. It should not be hard to fix and may have been fixed. Unfortunately KAME is not very keen on doing a full system test for outstanding bugs before release so it is not clear which PRs have been fixed as a part of work on unrelated issues and which are still outstanding. There are definitely some bugs on their bug page that have long been cleared and are not marked because the fixes were towards a different issue.
The next section deals with IKE. In other words is it responsible for authentication and parameter negotiation.
I have generally had no problems with racoon and IP address based shared keys and certificates. I could not make shared keys work with USER_FQDN style identifiers from an anonymous address when I first tried. I have not retested this for more then several years now so if you think that shared keys are a better idea compared to x509 certs you might as well try. I will be happy to hear the result (if I do not get around to test it until then). What follows are two typical sections, one for a dedicated VPN link and one for anonymous RAS access.
remote 7.8.9.10 {
# firewall 1 (or NG) peer, FW1 defaults to aggressive mode which is
# for PSK is dangerous and some of the problems have been discussed
# on BUGTRAQ. It is deliberately turned off on both sides
exchange_mode main, base;
my_identifier address 3.4.5.6; # we look up PSK based on address
passive off; # we will actively try to set up an SA at startup
proposal_check obey;
# just in case the FW1 people decide to change
# the SA lifetimes we will use theirs because if there is a difference
# SAs are established first time and after that we get some sillies
# with informational messages I think this bug has been fixed, but why
# tickle it. See kame bug fbsd4/470
lifetime time 1440 min;
initial_contact on;
proposal {
encryption_algorithm 3des;
hash_algorithm sha1;
authentication_method pre_shared_key;
dh_group 2;
}
# this will also work versus 128 bit encryption IOS and PIX
#you need dh_group 1, des and md5 for the 56 bit variety
}
remote anonymous
{
exchange_mode main, base;
passive off; # quite meaningless here
certificate_type x509 "server-signed.pem" "server-key.pem";
my_identifier asn1dn;
verify_cert on;
proposal_check obey; # once again we try not to wake up. See kame bug fbsd4/470
# unless really necessary
proposal {
encryption_algorithm 3des;
hash_algorithm md5 ;
authentication_method rsasig ;
dh_group 2 ;
}
}
Once you are done with the authentication part of IKE you need to specify the parameters related to SPI negotiation. From VPN perspective something missing in racoon is what can be called lose SA info spec or a SA filter. In other words an SA statement that is applied as a check when racoon is configured to "generate policy" based on a client request. It is a MUST for implementing IPSEC tunnel mode VPN clients for RAS. They usually function this way: the client requests in IKE the policy substituting its current address for the remote tunnel endpoint and the server complies if the request matches its set of allowed policies. The lack of this feature effectively limits racoon to tunnel mode between systems on static addresses.
Here are two SA info statements that specify the parameters for a typical IPSEC tunnel mode connection between two networks 1.2.3.0/24 and 1.2.4.0/24.
sainfo address 1.2.3.0/24 any address 1.2.4.0/24 any {
encryption_algorithm blowfish;
authentication_algorithm non_auth, hmac_sha1;
compression_algorithm deflate;
lifetime time 28800 sec;
}
sainfo address 1.2.4.0/24 any address 1.2.3.0/24 any {
encryption_algorithm blowfish;
authentication_algorithm non_auth, hmac_sha1;
compression_algorithm deflate;
lifetime time 28800 sec;
}
If you intend to use IPSEC to protect other VPN RAS technologies using transport mode or if you are brave enough to use the "generate policy" option you will also need an anonymous section
sainfo anonymous {
encryption_algorithm 3des, blowfish, aes;
authentication_algorithm non_auth, hmac_sha1;
# if any clients are coming from across NAT leave this as non_auth only
compression_algorithm deflate;
}
An important caveat when dealing with racoon is that racoon follows its own policy definitions and ignores informational IKE messages about the other side policies. As a result if you are working FreeBSD to FreeBSD or FreeBSD to Windows you may end up negotiating a successful set of SAs and have traffic silently discarded because the policy on the encryption end does not match the policy on the decryption end. If you are working versus a system that pays attention to these messages you are likely to have IKE failures that do not have a meaningful debug message on the racoon side (AFAIK can happen vs checkpoint NG).
POPTOP
PopTOP is the PPTP daemon developed by Lineo for Linux several years ago. It is designed to be the CO component of a PPTP RAS solution. It can be used for the purposes of establishing infrastructure, but its use is limited to the fact that it handles only the termination of connections.
It is fairly well maintained, but it has always been and is likely to remain mostly Linux oriented software. For example under BSD it relies on a static magic config section in the ppp.conf and there is no way to run with multiple configurations on the same machine. Otherwise it is pretty much mature software. It offers passable performance along with good stability. It is a good idea to keep it on machines which run the other PPTP implementation (mpd) just in case you run into an mpd gremlin.
You may ignore all address related PopTOP configuration fields under BSD. They are there for the sole purpose of being passed as command line arguments to the linux style pppd. BSD userland ppp will ignore them. The fields in use are only: listen and pidfile. Unfortunately there is no way to specify the name of the configuration section. Besides being good system administration and good programming style, this is something which you will need if you want to run mppe and non-mppe traffic from the same system. I have suggested to the BSD port maintainer in the past to use the "option" field in the PopTOP configuration (or create a new option alltogether). There used to be a 10 line patch to do so in the previous version of this HowTo. Unfortunately the suggestion has been ignored, so if you need this functionality you will have to do some UTSL.
Once you have configured PopTOP you need to configure a section
named with the magic name "pptp" in your /etc/ppp/ppp.conf
loop: set timeout 0 set log phase chat connect lcp ipcp command set device localhost:pptp set dial set login # Server (local) IP address, Range for Clients, and Netmask set ifaddr 1.2.3.4 2.3.4.5-2.3.4.254 255.255.255.255 set server /tmp/loop "" 0177 pptp: load loop enable proxy enable MSChapV2 # note1: If you enable CHAP as well Mergic PPTP (PalmOS, Nokia, etc) will fail # note2: If you enable PAP all MSFT clients will fail disable pap # this depends on your routing. generally the easiest way out: # enable proxy accept dns # DNS Servers to assign client set dns 1.2.3.5 1.2.3.5 # NetBIOS/WINS Servers to assign client set nbns 172.28.0.46 172.28.0.5 # this enables MPPE encryption enable mppe # this sets the encryption mode to stateless and allows any key length set mppe * stateless set device !/etc/ppp/secure
While you can set the addresses of the point-to-point link in the config itself, I would suggest to use the /etc/ppp/ppp.conf file instead. You can share it between ppp, PopTOP and mpd installations. If you do this you must not use the ppp specific extension which allows you to specify a section name after the IP address to be executed once the link is authenticated.
PPTP Client (port from Linux)
You are likely to need this one only if you are trying to get
a BSD client running versus a PopTOP server. It does not operate
correctly versus MPD unless you use PAP and no encryption. It is
quite unstable on BSD and its coredumps are one too many. The situation
is made worse if you add routes in the /etc/ppp/ppp.conf file. I
have not bothered to debug the problem to its roots, but in some
configs the route will be set only once and attempts to set the route
again after a link restart will generate an error. As a result you
end up having to use scripts to make sure it is running and ip-up
scripts to set routes.
Overall it is definitely not worth the effort and I would recommend against using it and looking at other alternatives like mpd for BSD clients.
L2TPD
This is a port from Linux and as of version 0.69 it does not use BSD proper userland PPP or netgraph L2TP/PPP architectures. This is the reason why I would recommend against using it. Porting it to use userland PPP should be fairly easy by nicking the relevant code from PopTOP. Unfortunately so far there does not seem to be a great interest to do so.
MPD
This daemon supports PPP and PPTP and has been designed using the new netgraph architecture. As a result it has very high performance and can support unencrypted PPTP rates in excess of 10000 packets per second on a 533 Mhz Via Eden.
It supports both originating and terminating connections and can be used as a RAS server, RAS client and for infrastructure links.
It is generally better then PopTOP as far as serving Windows clients for RAS is concerned. It is considerably worse if you want to operate a diverse access point or use MPPE encrypted PPTP for infrastructure due to a number of outstanding interoperability nags and problems. These are due to the fact that it uses a slightly different GRE encoding from the one used by PopTOP and pptp-linux. Windows does not seem to care, but it is enough to make MPPE not usable (as of version 3.14 and all prior to that) versus the open source pptp servers and clients operating with MPPE encryption. There are also a number of differences in the handling of CHAP and the events on the control connection. These lead to linux-pptp coredumping when using CHAP versus mpd. Obviously these are not a problem if you do not use MPPE encryption and use PAP authentication.
Also, it does not support common PPP compression schemes like deflate. I have had some minor problems with some keep-alive gremlins as well. It also may trigger a kernel race in the netgraph initialization susbsystem if you try to run multiple instances. As a result it is impossible to have an installation with mpd which terminates both MPPE enabled and MPPE disabled connections.
As of 3.14 you have to specify the logging parameters at compile time and the default ones will generate messages that will not end up in /var/log/ppp.log. I would suggest changing the defaults before compilation if you want to keep your logging in one place.
It is also a bit annoying to configure because it requires a separate configuration section for every interface in use. Interfaces are not allocated dynamically and must be preassigned. It is capable to template interfaces so this is more of an annoyance then real problem.
A typical MPD config for RAS will look like this mpd.conf:
default: # this is a list of interfaces which will be initialized on startup
load pptp1
load pptp2
load pptp3
#...repeated many times...
load pptp127
pptp1:
new -i ng1 pptp1 pptp1
load common
pptp2:
new -i ng2 pptp2 pptp2
load common
#...repeated many times...
pptp127:
new -i ng127 pptp127 pptp127
load common
common:
set iface disable on-demand
set iface enable proxy-arp
set iface idle 0
set bundle disable multilink # I have run into sporadic problems with XP on this one.
# Check if ICMP is OK while running witing +/- 50 octets
# from the MTU
set link enable acfcomp protocomp
set link no pap chap
set link enable chap
set link keep-alive 10 60
set ipcp yes vjcomp
# these are same as in the PopTOP example left is local address,
# right is remote address
set ipcp ranges 1.2.3.4/32 2.3.4.5/24
set ipcp dns 1.2.3.5 1.2.3.6
set ipcp nbns 1.2.3.5 1.2.3.6
#
# The five lines below will enable Microsoft Point-to-Point encryption
# (MPPE) using the ng_mppc(8) netgraph node type. uncomment if you
# want to use it
#set bundle enable compression
#set ccp yes mppc
#set ccp yes mpp-e40
#set ccp yes mpp-e128
#set ccp yes mpp-stateless
Note that this does not complete the configuration, you also have to complete the links file mpd.links which describes which links use which addresses.
pptp1: set link type pptp set pptp self 3.4.5.6 set pptp enable incoming set pptp disable originate pptp2: set link type pptp # Important Caveat as of up to 3.14 !!! # if the address here is different from above MPD will not scan to # this address when establishing a connection!!! First free link is # used regardless of the address so if you want to have 3.4.5.6 for # MPPE enabled traffic and 3.4.5.7 for normal traffic you are out of luck # it is on the wishlist and one day the feature may be there. set pptp self 3.4.5.6 set pptp enable incoming set pptp disable originate ...repeated many times... pptp127: set link type pptp set pptp self 3.4.5.6 set pptp enable incoming set pptp disable originate A typical RAS client configuration for mpd consists of the following entries in mpd.conf: office: new -i ng2 office office set iface disable on-demand set link type pptp set iface idle 0 set bundle authname client-username set bundle password "VerySecretClientPassword" set bundle disable multilink set link yes acfcomp protocomp set link keep-alive 10 60 set ipcp yes vjcomp set ipcp ranges 0.0.0.0/0 0.0.0.0/0 set bundle enable compression # set mppe enable # set ccp yes mppc # set ccp yes mpp-e40 # set ccp yes mpp-e128 # set ccp yes mpp-stateless # the office network set iface route 6.7.8.9/24 open iface
Note the open iface statement which is necessary to initiate
the connection at boot. You also need a corresponding section in
mpd.links:
pptp127:
set link type pptp set pptp self 3.4.5.6 # this address will be honoured for origination set pptp peer 4.5.6.7 # peer remote address set pptp disable incoming # set pptp enable originate
OpenVPN
OpenVPN is still in active development. While the infrastructure functionality is already there, many "obvious" features related to RAS are still on the TODO list.
The most important missing feature as far as RAS is concerned is the inability to multiplex multiple connections onto the same port when using UDP transport. There is a number of workarounds existing for this problem. Most of them rely on placing a load balancer in front of the VPN access system which NATs the "externally visible" port to a port on the VPN concentrator. The VPN concentrator still runs multiple instances of the openVPN configured for Using this approach suffers from the obvious problem that every new connection has a non-zero probability to be balanced on top of an existing one and supersede it. I would suggest using unique ports/addresses for each client instead.
# Client config for Layer2 using UDP transport port 5100 # change to 5101,510, etc for every client/server pair dev tap tls-client comp-lzo ca cacert.pem # certificate authority cert cert client.pem #signed client certificate key client-key.pem # unencrypted key persist-tun ping 60 user openvpn # only on a unix client # Server Config for Layer2 using UDP transport port 5100 # change to 5101,510, etc for every client/server pair dev tap1 # change to 2,3,4,5,6,7 for every unique port tls-server comp-lzo ca /etc/ssl/CA/cacert.pem # certifcate authority cert dh /etc/openvpn/dh1024.pem # diffie helman group cert /etc/openvpn/openvpn.pem key /etc/openvpn/openvpn-key.pem persist-tun ping 60 user openvpn
If you require having the same config on all clients as well as using the same port/address on all clients you are better off with using TCP transport. TCP transport when running from inetd starting from OpenVPN version 1.6 (as of rc3) is capable of operating in no-wait mode and supporting multiple connectons with the same config.
# OpenVPN multiple-client-server (based on the OpenVPN FAQ) # use this in inetd.conf (assuming you are trying to cheat and use the https ports) # https stream tcp nowait root /usr/sbin/openvpn openvpn --config /etc/openvpn/config.443 inetd nowait proto tcp-server dev tap ifconfig 1.2.3.4 255.255.255.0 ifconfig-noexec tls-server dh /etc/openvpn/dh1024.pem ca /etc/ssl/CA/cacert.pem # certifcate authority cert dh /etc/openvpn/dh1024.pem # diffie helman group cert /etc/openvpn/openvpn.pem key /etc/openvpn/openvpn-key.pem
If you intend to use OpenVPN for infrastructure you are likely to be better off in Layer3 mode. If you intend to use OpenVPN for RAS you are possibly better off in Layer 2 mode. This will allow you to use DHCP to configure most of the network settings and integrate it into the network. There are some examples and more information on this in the Network and Client Notes section.
Next Previous Contents




Post new comment