Interesting article on how to link to Mac computers using Bluetooth.
Networking
IPSec transport mode with X.509 certificates
Scenario
This article describes how to create a secure network-level transport between two hosts. All traffic sent between both hosts will be encrypted automatically as in enters the TCP/IP stack at the network (IP) level by using IPSec Encapsulating Security Payload (ESP) protocol.
For more details about IPSec, read IPSec pilot between glass and teapot.
Security Policy Database (SPD) configuration
The Security Policy Database (SPD) defines which IP traffic flows are to be affected by IPSec. Any traffic protected by IPSec can be protected by two different security mechanisms:
- Confidentiality.
Is achieved by using IPSec Encapsulating Security Payload (ESP) protocol.
The IPSec ESP protocol cyphers the contents of the payload to be transported over IP. ESP, optionally, offers authentication and integrity, but it is considered weak since it does only affect the payload but not the header of the encapsulating IP datagram.
- Authentication and Integrity.
Is achieved by using IPSec Authentication Header (AH) protocol.
The IPSec AH protocol protects that payload and any unmutable field of the encapsulating IP header.
By configuring the SPD, it is possible to use:
- IPSec Transport Mode to protect all the traffic sent between two hosts.
- IPSec Tunnel Mode to protect all the traffic sent between to networks.
For the machine ipsec-a:
Create the file /etc/racoon/setkey.sh with the following lines:
#!/sbin/setkey -f spdflush ; spdadd 192.168.0.40 192.168.0.41 any -P out ipsec esp/transport//require ; spdadd 192.168.0.41 192.168.0.40 any -P in ipsec esp/transport//require ;
This file should be marked executable and will be executed before launching racoon in order to populate the SPD with the proper entries.
For the machine ipsec-b:
Create the file /etc/racoon/setkey.sh with the following lines:
#!/sbin/setkey -f spdflush ; spdadd 192.168.0.41 192.168.0.40 any -P out ipsec esp/transport//require ; spdadd 192.168.0.40 192.168.0.41 any -P in ipsec esp/transport//require ;
This file should be marked executable and will be executed before launching racoon in order to populate the SPD with the proper entries.
Racoon configuration
racoon is a user-space daemon in charge of negotiating and establishing the Security Associations (SA) between two peer.
When the kernel sees an IP datagram, affected by a SPD rule, for which there is no SA yet established, the kernel will invoke racoon in order to negotiate and set it up with the corresponding peer defined in the SPD.
The peers can authenticate using some of the following:
- Pre-Shared Keys (PSK)
Both peers mutually agree on a shared secret, which is manually configured by the administrator and stored in the file /etc/racoon/psk.txt.
- RSA Signature
Each peer has an associated private key and public key X.509 certificate. Authentication takes place by exchanging certificates between peers and validating them, while RSA is used for authentication.
- GSSAPI
Kerberos is used for authentication of both peers.
In out scenario, RSA Signature using X.509 public key certificates will be used for authentication between the peers so, in first place, we need to generate private keys and their corresponding certificates for each peer. The steps used to generate the certificates are described in Setting up Certificate Authority (CA) using OpenSSL.
The configuration for both peers is identical, so we will use the same racoon configuration file. However, the private key and public key certificate for each peer is different, so we should take this into consideration.
The peer private key must be installed into /etc/racoon/certs/key.pem, the peer signed public key certificate into /etc/racooon/certs/cert.pem and the CA public key certificate into /etc/racoon/certs/cacert.pem.
This is the /etc/racoon/racoon.conf configuration file:
path include "/etc/racoon"; path pre_shared_key "/etc/racoon/psk.txt"; path certificate "/etc/racoon/certs"; remote anonymous { # Some IPSec implementations have been found to # be vulnerable when used in aggressive exchange # mode exchange_mode main ; # Allow for the extension described in RFC 2407 # called Domain of Interpretation which allows # negotiation of the traditional 32-bit sequence # numbers or extended 64-bit sequence numbers doi ipsec_doi ; # Local identifier is taken from the Subject field # of the X.509 certificate (Distinguised Name) my_identifier asn1dn ; # Remote identifier is taken from the Subject field # of the X.509 certificate presented by the remote # peer (Distinguised Name) peers_identifier asn1dn ; # Checks that the oeer identity that appears in the # ID payload matches the identity specified in the # peers_identifier option verify_identifier on ; # Specifies the path to the certificate and private # key files, encoded in PEM, relative to the # "path certificate" option specified above certificate_type x509 "cert.pem" "key.pem" ; # Specifies the path to the CA certificate file, # encoded in PEM, relative to the "path certificate" # option specified above ca_type x509 "cacert.pem" ; # Configures the size of the nonce in bytes, which # must be no less than 8 and no more than 256 nonce_size 16 ; # Lifetime the Phase 1 SA proposal lifetime time 24 hour ; proposal { # Encryption algorithm for phase 1 encryption_algorithm 3des ; # Hash algorithm for phase 1 hash_algorithm sha1 ; # RSA Signature authentication authentication_method rsasig ; # Diffie-Hellman group for phase 1 dh_group 2 ; } } sainfo anonymous { # Diffie-Hellman group for phase 2 pfs_group 2; # Lifetime for the SA lifetime time 12 hour ; # Encryption algorithms to be used in the SA encryption_algorithm 3des, blowfish, des, rijndael ; # Authentication algorithms to be used in the SA authentication_algorithm hmac_sha1, hmac_md5 ; # Use deflate compression (IPComp) compression_algorithm deflate ; }
Starting peers
For every peer, we need to launch racoon. For testing purpouses, we will launch racoon in foreground, so all messages are dumped to the screen:
/usr/sbin/racoon -F
racoon will dump the following messages to the console:
INFO: @(#)ipsec-tools 0.5 (http://ipsec-tools.sourceforge.net) INFO: @(#)This product linked OpenSSL 0.9.7f 22 Mar 2005 (http://www.openssl.org/) INFO: 127.0.0.1[500] used as isakmp port (fd=7) INFO: 127.0.0.1[500] used for NAT-T INFO: 192.168.0.41[500] used as isakmp port (fd=8) INFO: 192.168.0.41[500] used for NAT-T INFO: ::1[500] used as isakmp port (fd=9) INFO: fe80::20c:29ff:fea1:d55c%eth0[500] used as isakmp port (fd=10)
Next, we need to initialize the SPD:
/etc/racoon/setkey.sh
Testing connectivity
To trigger the SA establishment we can ping the other host. The kernel will apply the SPD policy and will ask racoon to negotiate and set up the proper SA between both peers. racoon should dump something like this to the console:
INFO: IPsec-SA request for 192.168.0.40 queued due to no phase1 found. INFO: initiate new phase 1 negotiation: 192.168.0.41[500]192.168.0.40[500] INFO: begin Identity Protection mode. INFO: received Vendor ID: DPD WARNING: unable to get certificate CRL(3) at depth:0 SubjectName: /C=ES/ST=Madrid/O=Software AG/OU=IT/CN=ipsec-a WARNING: unable to get certificate CRL(3) at depth:1 SubjectName: /C=ES/ST=Madrid/L=Madrid/O=Software AG/OU=IT/CN=ca-server INFO: ISAKMP-SA established 192.168.0.41[500]-192.168.0.40[500] spi:2698c81446191f6c:9b9127e3b6956065 INFO: initiate new phase 2 negotiation: 192.168.0.41[0]192.168.0.40[0] INFO: IPsec-SA established: ESP/Transport 192.168.0.40->192.168.0.41 spi=78608282(0x4af779a) INFO: IPsec-SA established: ESP/Transport 192.168.0.41->192.168.0.40 spi=118550227(0x710eed3)
SSL/TLS VPN with stunnel
From the stunnel manual page:
The stunnel program is designed to work as SSL encryption wrapper between remote clients and local (inetd-startable) or remote servers. The concept is that by having non-SSL aware daemons running on your system you can easily set them up to communicate with clients over secure SSL channels.
stunnel can be used to add SSL functionality to commonly used inetd daemons like POP-2, POP-3, and IMAP servers, to standalone daemons like NNTP, SMTP and HTTP, and in tunneling PPP over network sockets without changes to the source code.
I will use stunnel to encapsulate PPP frames into the SSL tunnel, in order to create an SSL VPN between two peers. Both peers will have two network interfaces each:
- a eth0, or eth0-like interface, which is the native, physical, non-tunneled network interface, used by each peer to directly reach the other via a WAN, insecure connection, like the Internet or a Wireless network.
Traffic sent directly between peers through eth0 is assumed to be sent in the clear, without confidentiality, authentication or integrity.
- a ppp0 network interface which acts as a Layer 2 interface, using PPP framing to tunnel traffic between both peers over an insecure network connection. PPP frames will get wrapped inside an SSL/TLS session between both peers and delivered via the real eth0 interface.
Thus, traffic sent to the ppp0 interface will get wrapped inside a PPP frame, then transported over an SSL/TLS tunnel through the eth0 insecure interface to the other peer.
SSL/TLS adds confidentiality, authentication and integrity by means of an SSL/TLS session.
Configuring the server
The configuration file for the stunnel server will be stored in the /root/stunnel-server.conf file:
# The CA certificate file CAfile = /root/cacert.pem # The server public key certificate cert = /root/server.pem # The server private key key = /root/server.key # Name of server PID file pid = /root/server.pid # Verify peer certificate verify = 2 # The directory where all the certificates can be found # Only used when verify = 3 # CApath = /root # Some debugging stuff debug = 7 # output = /root/server.log # Use it for client mode client = no foreground = yes # Protocol Specific options # We need to specify DES-CBC3-SHA since there are some AES # ciphers that, when used with RSA, can't be decoded by ssldump ciphers = DES-CBC3-SHA:IDEA-CBC-MD5 # Service-level configuration [vpn] # incoming port number accept = 9871 # argv[0] for the PPP server exec = /usr/bin/pppd # argv[0], argv[1], ... argv[n] for the PPP server execargs = /usr/sbin/pppd debug noauth noaccomp noccp nodeflate nopcomp novj novjccomp 192.168.1.1:192.168.1.2 # Use a pty, since the PPP server will write PPP frames to a pty pty = yes
Some of the options used in this configuration file are described in the next paragraphs:
- CAfile, cert and key point to the location of the PEM-encoded CA certificate file, PEM-encoded server public certificate and PEM-encoded server private key, respectively.
- verify defines the level of peer certificate verification:
- verify peer certificate, if present
- always verify peer certificate
- verify peer with locally installed certificate
If no verify option is supplied, no peer certificate verification is performed.
- client = no tells stunnel this side will act as the server.
- foreground =yes requests stunnel not to fork off and log to stderr instead of using syslog.
- ciphers = DES-CBC3-SHA:IDEA-CBC-MD5 configures the ciphers preferred list for the server when negotiating a cipher and MAC protocol with the client.
I have chosen DES-CBC3-SHA in first place and IDEA-CBC-MD5 in second place cause if no cipher list is supplied, OpenSSL tends to select RSA-AES-256-SHA which ssldump is, at the time of this writing, is unable to decode.
- accept defines the port stunnel will listen to.
- exec specifies the program to execute in order to set up the PPP server used to encapsulate traffic inside the SSL/TLS tunnel.
In this case, we use /usr/sbin/pppd.
- execargs defines the arguments, starting at argv[0], that will be supplied to the command specified by the exec option (in this case, /usr/sbin/pppd):
- debug, enables debugging information
- noauth, disables any form of PPP authentication
- noccp novj novjccomp noaccomp, disables any form of compression.
noaccomp disables address/control compression in both directions.
noccp disables CCP (Compression Control Protocol) negotiation.
nodeflate disables Deflate compression support.
nopcomp disables protocol field compression negotiation, in both the receive and the transmit direction.
novj disables Van Jacobson style TCP/IP header compression in both the transmit and receive direction.
novjccomp disables the connection-ID compression option in the Van Jacobson style TCP/IP header compression.This will be useful when using ssldump to decode traffic between the client and the server.
- 192.168.1.1:192.168.1.2, tells the PPP server the remote peer ppp0 interface will get assigned IP 192.168.1.2, while the server, local ppp0 interface will get assigned IP 192.168.1.1.
- pty = yes tells stunnel to allocate a pseudo-terminal used for the exec program.
stunnel will get traffic from the remote peer through the SSL/TLS tunnel, will decrypt it using the private key and the resulting PPP frame will be written to this pseudo-tty so the PPP server can process it and send it back to the TCP/IP stack for further processing.
Any time the local machine sends traffic to the ppp0 interface, the PPP server capture it and encapsulate it into a PPP frame that will get written to the pseudo-tty. stunnel will see that PPP frame, will send it to the remote peer trough the SSL/TLS tunnel.
Launching the server
To make things easier, create a shell-script called launch-server.sh with the following lines:
#!/bin/sh /usr/sbin/stunnel /root/stunnel.conf
Configuring the client
The configuration file for the stunnel client will be stored in the /root/stunnel-client.conf file:
# The CA certificate file CAfile = /root/cacert.pem # The client public key certificate cert = /root/client.pem # The client private key key = /root/client.key # Name of client PID file pid = /root/client.pid # Verify peer certificate verify = 2 # The directory where all the certificates can be found # Only used when verify = 3 # CApath = /root # Some debugging stuff debug = 7 #output = /root/client.log # Use it for client mode client = yes foreground = yes # Service-level configuration # host and port where stunnel server peer is listening connect = stunnel-server:9871
Some of the options used in this configuration file are described in the next paragraphs:
- CAfile, cert and key point to the location of the PEM-encoded CA certificate file, PEM-encoded client public certificate and PEM-encoded client private key, respectively.
- verify defines the level of peer certificate verification:
- verify peer certificate, if present
- always verify peer certificate
- verify peer with locally installed certificate
If no verify option is supplied, no peer certificate verification is performed.
- client = yes tells stunnel this side will act as the client.
- foreground =yes requests stunnel not to fork off and log to stderr instead of using syslog.
- connect is used when client = yes and tells stunnel which host and port to connect to.
Launching the client
To make things easier, create a shell-script called launch-client.sh with the following lines:
#!/bin/sh /usr/sbin/pppd noauth debug dump passive noaccomp noccp nodeflate nopcomp novj novjccomp nodetach pty "/usr/sbin/stunnel /root/stunnel.conf"
This will launch the PPP client, pppd, using an SSL/TLS tunnel supplied by stunnel as the encapsulating Layer 2 tunneling protocol.
- noccp novj novjccomp noaccomp, disables any form of compression.
noaccomp disables address/control compression in both directions.
noccp disables CCP (Compression Control Protocol) negotiation.
nodeflate disables Deflate compression support.
nopcomp disables protocol field compression negotiation, in both the receive and the transmit direction.
novj disables Van Jacobson style TCP/IP header compression in both the transmit and receive direction.
novjccomp disables the connection-ID compression option in the Van Jacobson style TCP/IP header compression.This will be useful when using ssldump to decode traffic between the client and the server.
- debug, enables debugging information
- noauth, disables any form of PPP authentication
- passive, enables the passive option in the LCP.
With this option, pppd will attempt to initiate a connection. If no reply is received from the peer, pppd will then just wait passively for a valid LCP packet from the peer, instead of exiting, as it would do without this option.
- nodetach, tells pppd to not detach from the controlling terminal. Useful to keep pppd in the foreground, so it can get stopped with a SIGINT signal.
- pty, specifies the command script used to communicate rather than a specific terminal device. pppd will allocate itself a pseudo-tty master/slave pair and use the slave as its terminal device. The script will be run in a child process with the pseudo-tty master as its standard input and output.
The command script is just the invocation to stunnel, in order to encapsulate all the PPP frames generated by pppd inside the SSL/TLS tunnel.
Testing connectivity
After launching the client, a new ppp0 interface should be automatically configured with the following parameters:
ppp0 Link encap:Point-to-Point Protocol inet addr:192.168.1.2 P-t-P:192.168.1.1 Mask:255.255.255.255 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1 RX packets:3 errors:0 dropped:0 overruns:0 frame:0 TX packets:3 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:3 RX bytes:30 (30.0 b) TX bytes:30 (30.0 b)
A simply ping 192.168.1.1 command executed from the client should suffice to trigger traffic through the SSL/TLS tunnel and test connectivity.
SSLTunnel
SSLTunnel is a beautiful piece of software used to create an SSL/TLS VPN between two hosts, usually a client host and a VPN concentrator or server. Inside this tunnel, the traffic between the client and the server gets encapsulated inside PPP frames which are encapsulated inside the SSL/TLS tunnel. The tunnel itself is built using kernel PPP support, which materializes in the form of a ppp0 network interface.
SSLTunnel requires the following:
- PPP daemon (tested with ppp-2.4.3-6)
- PPP kernel support, like a ppp0 interface (minimally ppp_generic, ppp_async, ppp_deflate kernel modules)
- OpenSSL (tested with openssl-0.9.8a-1)
This describes roughly how SSLTunnel works:
- the server listens on port 443 of the destination machine
- the client connects himself (if need be, through a relay like Squid, ISA-Server, the proxy does not have *ANY* mean to check if it is a navigator HTTPS Web server session, because the beginning of the not crypted session and the SSL negotiation are exactly identical)
- at the establishment of the connection, the server forks
- the server sends its certificate, the client checks that it is well signed by an authority it trusts
- the client sends his certificate
- the server checks this certificate and seeks if it corresponds to a certificate declared in its base
- the crypted session starts
- the server sends its banner with its version number and its protocol version
- the client receives the banner, checks and sends his
- the client forks, opens a pty, launches pppd in client mode on this pty, without specifying which IP address it wants
- the server gets PPP parameters from the user file, changes its identity, opens a pty, forks and launches pppd on this pty with the options given by the file
- the PPP session is established between the two ends, the program at each end cyphers/uncyphers and reads/sends the data in the pty connected to pppd.
Server
The following section describes how to get the source code for SSLTunnel, how to compile and patch it, how to configure it and how to set it up.
Server compilation
At the moment of this writing, the last stable version of SSLTunnel is 1.15, which can be obtained from here.
Before compiling the server components of SSLTunnel, I applied the following patch to SSLTunnel 1.15:
--- ssltunnel-1.15/server/main.c.old 2005-11-13 18:45:56.000000000 +0000 +++ ssltunnel-1.15/server/main.c 2005-11-13 18:29:14.000000000 +0000 @@ -796,7 +796,7 @@ ctx=SSL_CTX_new(meth); /* Load our keys and certificates*/ - if(!(SSL_CTX_use_certificate_chain_file(ctx, certfile))) + if(!(SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM))) berr_exit("Can't read certificate file"); if(!(SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM)))
This patch essentially allows using a PEM-encoded X.509 certificate file for the server certificate instead of a PKCS#12-encoded chain of certificates, which eases the configuration and certificate generation a lot.
tar xvfz ssltunnel-.tar.gz cd ssltunnel- ./configure --disable-client make make install
This will install the following files:
- /usr/local/libexec/pppserver
The VPN server daemon.
- /usr/local/etc/ssltunnel/tunnel.conf
pppserver configuration file.
- /usr/local/etc/ssltunnel/tunnel.conf.default
Default configuration file.
- /usr/local/sbin/pppwho
Used to query the utmp(3) file mantained by pppserver with the list of currently established tunnels.
Server certificate generation
Once the server components of SSLTunnel are built and installed, the pppserver certificate and its corresponding private key must be created. For information on how to create a CA using OpenSSL and generating server and client certificates, read Setting up Certificate Authority (CA) using OpenSSL.
Server configuration
The CA certificate will be installed as /usr/local/etc/ssltunnel/cacert.pem. The pppserver signed certificate will be installed as /usr/local/etc/ssltunnel/server.pem. The VPN private key will be installed as /usr/local/etc/ssltunnel/server.key and will be properly protected (0600 permission mask).
The pppserver configuration is stored in /usr/local/etc/ssltunnel/tunnel.conf, and should look like this:
keyfile /usr/local/etc/ssltunnel/server.key certfile /usr/local/etc/ssltunnel/server.pem cacertfile /usr/local/etc/ssltunnel/cacert.pem userfile /usr/local/etc/ssltunnel/users wtmp /var/log/ssltunnel.wtmp pidfile /var/run/pppserver.pid timeout 20 maxusers 10 port 443 #listenaddr 192.168.0.1,192.168.1.1 lockdir /var/lock/ssltunnel
Following is a brief description of every configuration option:
- keyfile points to the VPN server private key.
- certfile points to the VPN server certificate.
- cacertfile points to the CA certificate.
- userfile points to the file that defines which users are allowed to request a tunnel to be established.
- wtmp points to a utmp(3) file that is maintained by pppserver. This file stores information about currently established tunnels and can be queried by using the pppwho command.
- pidfile points to the file that holds the PID of the currently pppserver daemon.
- timeout defines how much time must be elapsed for a tunnel request to be declared unsatisfiable.
- maxusers defines the maximum number of simultaneous tunnels that can be established.
- port defines the port used by the SSL/TLS tunnel.
- listenaddr is an optional comma-separated list of IP addresses that can be used to tell the VPN server which interfaces it should listen to.
- lockdir points to the directory used to store pppserver locks.
Finally, the /usr/local/etc/ssltunnel/users file must be modified in order to declare which users should be recognized by pppserver and allowed to establish an SSL/TLS tunnel.
The format of this file consists of one or more user blocks, each one referencing a remote user and its related options. Each user block is separated from the following one by a blank line.
A user block consists of several options:
- user
The user option holds the X.509 distinguised name of the client certificate for which its owner is allowed to establish an SSL/TLS tunnel. The following command extracts the distinguised name from the X.509 client certificate:
openssl x509 -nout -subject < client.cert
For example:
user /C=ES/O=felipe-alfaro.org/OU=IT/cn=Felipe Alfaro
-
fingerprint
The optional fingerprint option specifies the fingerprint for the client certificate associated with this user. It can be calculated with the following command:
openssl x509 -noout -fingerprint < certificat_client
- command
The command option holds the path to the PPP daemon executable. This is usually /usr/sbin/pppd.
- pty
The pty option defines the pseudo-terminal number that will be used by the PPP daemon. This is usually 1.
- args
The args option defines the additional arguments that will be supplied when invoking the PPP server specified by the command option.
At least one argument must be supplied to the PPP server. This argument defines the local IP address for the tunnel interface and the remote IP address for the tunnel interface, separated by a colon.
For example, if the local IP address for the tunnel, on the VPN server machine, is 192.168.1.1, and the remote IP address for the tunnel, on the VPN client, is 192.168.1.2, the args option will look like this:
args 192.168.1.1:192.168.1.2
- uid
gidAllows to change Unix identity before running pppd: permits to reduce the privileges. Attention, it will be necessary that used user and group have the right to run pppd! Obviously, that also implies that pppd is setuid root, so that it can set up routes, handle ARP table, etc.
If these lines aren’t present, everything will be executed as root.
The resulting /usr/local/etc/ssltunnel/users file should look like this:
user /C=ES/O=felipe-alfaro.org/OU=IT/cn=Felipe Alfaro
command /usr/sbin/pppd
pty 1
args 192.168.1.1:192.168.1.2
user /C=ES/…
Server start
Once the configuration user files have been modified, the pppserver VPN server daemon can be started with the following command:
/usr/local/libexec/pppserver /usr/local/etc/ssltunnel/tunnel.conf
There should be a new process named pppserver. pppserver uses the syslog local6 facility to log errors, so in case the daemon does not start properly, check /var/log/messages to see why it failed to start.
Client
The following section enumerates the steps used to build, compile, configure and run the VPN client software.
Client compilation
Before building the client software, it is recommended to apply the following patch:
--- ssltunnel-1.15/client/main.c.old 2005-11-13 18:46:59.000000000 +0000 +++ ssltunnel-1.15/client/main.c 2005-11-13 18:38:47.000000000 +000 @@ -626,7 +626,7 @@ ctx=SSL_CTX_new(meth); /* Load our keys and certificates*/ - if(!(SSL_CTX_use_certificate_chain_file(ctx, certfile))) + if(!(SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM))) berr_exit("Can't read certificate file"); if(!(SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM)))
This patch allows using a PEM-encoded certificate for the VPN client instead of a PKCS#12-encoded certificate chain, which makes things a lot easier.
The commands used to extract, build and install the VPN client are the following:
tar xvfz ssltunnel-.tar.gz cd ssltunnel- ./configure --disable-server make make install
This will install the following files:
- /usr/local/man/man5/ssltunnelrc.5
The manual page for the VPN client configuration file.
- /usr/local/man/man1/pppclient.1
The manual page for the pppclientVPN client.
- /usr/local/bin/pppclient
The VPN client.
Client certificate generation
Once the client components of SSLTunnel are built and installed, the pppclient X.509 user certificate and its corresponding private key must be created. For information on how to generate the client certificate, read Setting up Certificate Authority (CA) using OpenSSL.
Client configuration
The CA certificate will be installed as /home/user/cacert.pem. The pppclient signed user certificate will be installed as /home/user/client.pem. The client private key will be installed as /home/user/client.key and will be properly protected (0600 permission mask).
The VPN client configuration file is usually stored in the /home/user/.stunnelrc, although it can be overridden when invoking pppclient, and should look like this:
verbose 1 remotehost 192.168.0.20 port 443 localppp /usr/sbin/pppd ipparam tunnel #bsdppp 0 #peer tunnelserver localproxyarp 0 #useproxy 0 #proxy A.B.C.D #proxyport 8080 #proxyuser user #proxypass pass localechoint 10 localechofail 10 localdebug 1 timeout 20 cacertfile /home/user/cacert.pem keyfile /home/user/client.key certfile /home/user/client.pem daemon 0 autoreconnect 0 logfile /home/user/pppclient.log
Following is a brief description of every configuration option:
- verbose, when set to 1, increases the level of verbosity. Setting it to 0 makes pppclient to be quiet.
- remotehost specifies the IP address of the VPN server machine (the one running pppserver
- port specifies the port used by pppserver to negotiate and establish the SSL/TLS tunnel.
- localppp points to the PPP daemon executable.
- ipparam specifies a tag which is passed to PPP to determine which configuration rules should be obeyed in order to set up routes, update ARP entries and so on.
- bsdppp, when set to 1 specifies whether to use userland PPP support in *BSD.
- peer defines which PPP peer to call as defined in /etc/ppp/peers/peer
- localproxyarp, when set to 1 specifies that ARP proxying should be performed.
- useproxy, when set to 1 specifies that the client must pass through a HTTP proxy before reaching the VPN server.
- proxyport specifies the proxy port number, if any.
- proxyuser specifies the username used to authenticate against the proxy server, if any.
- proxypass specifies the password used to authenticate against the proxy server, if any.
- localechoint defines the local echo internal, in seconds, used as a keepalive.
- localechofail specifies the number of failed echo retries that would trigger the SSL/TLS tunnel down at the client.
- localdebug, when set to 1 forces the PPP daemon to be launched in debug mode.
- timeout the maximum amount of time used to established the SSL/TLS tunnel. If this time is exceeded, the VPN client will give up.
- keyfile points to the VPN client private key.
- certfile points to the VPN client certificate.
- cacertfile points to the CA certificate.
- daemon, when set to 1 request pppclient to daemonize itself and detach from the terminal.
- autoreconnect, when set to 1 request pppclient to re-establish the tunnel if it is broken down by any unexpected reason.
- logfile points to the log file where pppclient will log its errors or debug messages.
There is a sample pppclient file located inside the SSLTunnel source code, named client/tunnel.conf.
Client start
Once the pppclient configuration has been created, the pppclient VPN client daemon can be started with the following command:
/usr/local/bin/pppserver [optional path to configuration file]
The pppclient VPN client should chat like this with the VPN server:
22:52:47 Connecting to 192.168.0.20 22:52:47 Connected 22:52:48 SSL connect successful 22:52:48 Server version : 1.15 22:52:48 Server Protocol version : 1.0 22:52:48 forking ppp 22:52:48 45 45 22:52:48 46 < ----- 22:52:51 45 96 22:52:51 17 17 22:52:51 66 21 22:52:51 -----> 21 22:52:51 21 89 22:52:00 89 13 22:52:01 13 < -----
To check the SSL/TLS tunnel has been set up by checking the state of the ppp0 network interface:
ppp0 Link ecanp:Point-to-Point Protocol inet addr:192.168.1.2 P-t-P:192.168.1.1 Mask:255.255.255.255 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1 RX packets:5 errors:0 dropped:0 overruns:0 frame:0 TX packets:5 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:3 RX bytes:66 (66.0 b) TX bytes:72 (72.0 b)
If everything has gone right, it should be possible to ping our remote VPN peer:
ping 192.168.1.1
Acknowledgements
This document has been created based on the information contained in the README file from the SSL Tunnel documentation.
FreeBSD firewall using PF
FreeBSD supports OpenBSD’s powerful firewall PF since version 5.3. The scenario I was pursuing was firewalling one of my FreeBSD machines:
Incoming firewalling
- Only incoming SSH connections from known SSH clients should be accepted.
- Only incoming Syslog traffic from known Syslog clients should be accepted.
- Only incoming ICMP Echo-Reply, ICMP Echo-Request and ICMP Destination-Unreachable datagrams should be accepted. Any other ICMP datagram is potentially dangerous.
- No other incoming traffic should be allowed, but should get logged.
Outgoing firewalling
- Only outgoing DNS queries to known DNS servers should be accepted.
- Only outgoing NTP traffic to know NTP servers should be accepted.
- Only outgoing ICMP Echo-Reply, ICMP Echo-Request and ICMP Destination-Unreachable datagrams should be accepted. Any other ICMP datagram is potentially dangerous.
- No other outgoing traffic should be allowed, but should get logged.
The contents of /etc/pf.conf
should look lite this:
scrub in all pass quick on lo0 all icmp_types = "{ echorep, unreach, echoreq }" syslog_sources = "{ 192.168.0.124, 192.168.0.125, 192.168.0.126 }" ssh_sources = "{ 192.168.0.90, 192.168.0.91 }" ntp_servers = "{ 192.168.0.125 }" dns_servers = "{ 192.168.0.124 }" block in log all pass in on rl0 inet proto icmp icmp-type $icmp_types keep state pass in on rl0 proto tcp from $ssh_sources to self port { 22 } flags S/SA keep state pass in on rl0 proto udp from $syslog_sources to self port { 514 } block out log all pass out on rl0 inet proto icmp icmp-type $icmp_types keep state pass out on rl0 proto udp from self to $dns_servers port { 53 } keep state pass out on rl0 proto udp from self to $ntp_servers port { 123 } keep state
To enable PF and PF logging support to start automatically during boot, the following lines should be added to /etc/rc.conf
:
pf_enable="YES"
pf_rules="/etc/pf.conf"
pf_program="/sbin/pfctl"
pflog_enable="YES"
pflog_logfile="/var/log/pflog"
pflog_program="/sbin/pflogd"
WPA Enterprise
This document explains how to set up WPA/WPA2 Enterprise using EAP-TTLS (with PAP) as the authentication mechanism.
Introduction
The original IEEE 802.11 standard defined two basic security mechanisms:
- Open System Authentication, which offers no security at all since any Wireless client can associate with a Wireless Access Point configured in such a way.
Open System Authentication can be useful in public Wireless networks, like those found in airports or public areas. However, this security mechanisms offers no authentication and no confidentiality: data is sent into the air in the clear at the data-link layer, so no encryption and authentication is provided by the upper layers, the transmission can be eavesdropped, hijacked or manipulated.
- Wired Equivalent Privacy, which uses up to four shared-secret keys to “secure” the data transmission at the data-link layer.
One of these four shared-secret keys must be supplied to a Wireless client wanting to associate with the Wireless Access Point. Since there are only four keys available for WEP, some of them will have to be shared among the Wireless clients when the number of Wireless clients exceeds four.
This shared-secret scheme is not scalable, and does not cope well with revocation: trying to revoke access to a Wireless client usually means changing all the WEP keys and redistributing them to the appropriate Wireless clients (since the revoked client is usually a person who still knows some WEP keys and his brain can’t be easily modified to make him forget those WEP keys). Redistributing one or more keys to a large population is infeasible with current key distribution mechanisms, so here is where WPA Enterprise comes into play.
To enhance the security in IEEE 802.11, the IEEE 802.11i has been proposed. In addition to introducing protocols for key management and establishment, it also defines encryption and authentication improvements. In order to manage security keys automatically, the IEEE 802.11i has defined algorithms and protocols for key management and establishment. As conventional WEP is known to be vulnerable, the IEEE 802.11i has specified enhanced encryption algorithms to provide stronger privacy. The IEEE 802.11i also incorporates IEEE 802.1x as its authentication enhancement. The IEEE 802.1x standard is a port-based network access control to authenticate and authorize devices interconnected by various IEEE 802 LANs. The IEEE 802.11i is expected to play a critical role in improving the overall security of current and
future WLANs.
The new security standard, 802.11i, which was ratified in June 2004, fixes all WEP weaknesses. It is divided into three main categories:
- Temporary Key Integrity Protocol (TKIP) is a short-term solution that fixes all WEP weaknesses. TKIP can be used with old 802.11 equipment (after a driver/firmware upgrade) and provides integrity and confidentiality.
- Counter Mode with CBC-MAC Protocol (CCMP) [RFC2610] is a new protocol, designed from ground up. It uses AES [FIPS 197] as its cryptographic algorithm, and, since this is more CPU intensive than RC4 (used in WEP and TKIP), new 802.11 hardware may be required. Some drivers can implement CCMP in software. CCMP provides integrity and confidentiality.
- 802.1X Port-Based Network Access Control, either when using TKIP or CCMP, 802.1X is used for authentication.
In addition, an optional encryption method called “Wireless Robust Authentication Protocol” (WRAP) may be used instead of CCMP. WRAP was the original AES-based proposal for 802.11i, but was replaced by CCMP since it became plagued by property encumbrances. Support for WRAP is optional, but CCMP support is mandatory in 802.11i.
The 802.1X-2001 standard states:
“Port-based network access control makes use of the physical access characteristics of IEEE 802 LAN infrastructures in order to provide a means of authenticating and authorizing devices attached to a LAN port that has point-to-point connection characteristics, and of preventing access to that port in cases which the authentication and authorization fails. A port in this context is a single point of attachment to the LAN infrastructure.” — 802.1X-2001, page 1.
In order to fix the WEP vulnerabilities, the Wi-Fi Alliance took a “snapshot” of the standard (based on draft 3), and called it Wi-Fi Protected Access (WPA). One requirement was that existing 802.11 equipment could be used with WPA, so WPA is basically TKIP + 802.1X.
WPA is not the long term solution. To get a Robust Secure Network (RSN), the hardware must support and use CCMP. RSN is basically CCMP + 802.1X. RSN may also be called WPA2.
If TKIP is used instead of CCMP, it is called Transition Security Network (TSN). TSN is basically TKIP + 802.1X. TSN is also know as WPA.
- TSN = TKIP + 802.1X = WPA
- RSN = CCMP + 802.1X = WPA2
Extensible Authentication Protocol
Extensible Authentication Protocol (EAP) [RFC 3748] is just the transport protocol optimized for authentication, not the authentication method itself:
“[EAP is] an authentication framework which supports multiple authentication methods. EAP typically runs directly over data link layers such as Point-to-Point Protocol (PPP) or IEEE 802, without requiring IP. EAP provides its own support for duplicate elimination and retransmission, but is reliant on lower layer ordering guarantees. Fragmentation is not supported within EAP itself; however, individual EAP methods may support this.” — RFC 3748, page 3
In 802.1X terminology:
- Supplicant, is a network client asking for authentication in order to access a resource, usually associating with a Wireless Access Point, or requesting access to a wired Ethernet switch.
The Supplicant must supply some form of credentials to an Authentication Server in order to access the requested resource. This credentials can be in the form of user/password combination, a Kerberos ticket, an X.509 client certificate, and so on.
- Authenticator, usually acts as a proxy between the Supplicant and the Authentication Server, although in Wireless networks it is itself the resource being requested by the Supplicant: the Wireless Access Point.
- Authentication Server, is the network component in charge of validating the credentials supplied by the Supplicant.
802.1X uses the Extensible Authentication Protocol (EAP). EAP supports several different authentication mechanisms. Some of them are:
- EAP-MD5: MD5-Challenge requires username/password, and is equivalent to the PPP CHAP protocol [RFC1994].
Requests contain a challenge to the end user. CHAP requires the challenge to be encrypted with a shared secret between the Supplicant and the Authentication Server.
This method does not provide dictionary attack resistance, mutual authentication, or key derivation, and has therefore little use in a wireless authentication enviroment.
EAP-MD5 should not be used alone, but encapsulated inside some other EAP mechanisms, like EAP-TTLS or PEAP.
- Generic Token Card (EAP-GTC): This EAP mechanism allows the exchange of cleartext authentication credentials across the network.
EAP-GTC is usually used as an EAP method to exchange a username and a password, like in PAP (Password Authentication Protocol) or CHAP (Challenge Handshake Authentication Protocol). Since credentials are sent in the clear, it is usually tunneled inside EAP-TTLS or PEAP.
- Lightweight EAP (LEAP): A username/password combination is sent to a Authentication Server (RADIUS) for authentication. LEAP consists of two MS-CHAP version 1 exchanges. One authenticates the network to the user, and the second authenticates the user to the network. Dynamic keys are derived from the two MS-CHAP exchanges.
Many of the security problems of LEAP stem from the use of MS-CHAP version 1, which has numerous security problems (like being subject to dictionary attacks).
LEAP is a proprietary protocol developed by Cisco, and is not considered secure. Cisco is phasing out LEAP in favor of PEAP.
- EAP-TLS: Creates a TLS session within EAP, between the Supplicant and the Authentication Server. Both the server and the client(s) need a valid X.509 certificate, and therefore a PKI.
This method provides mutual authentication through certificate exchanges. The user is required to submit a digital certificate to the Authentication Server for validation, but the Authentication Server must also supply a certificate for the user to validate it. The client can check the certificate validity against a list of trusted CA, thus preventing the Wireless client from associating with a rogue Wireless Access Point.
EAP-TLS provides:
- Strong cryptographic protection, by providing cryptographic protection of the session.
- Athentication of both the Supplicant and the Authentication Server, by means of using mutual authentication via X.509 digital certificates.
- Key derivation, which allows for dynamic keying and alleviates the problems derived from the fact of using static keys.
The problem with EAP-TLS is that it requires a Public Key Infraestructure, generating and signing digital certificates for both the Authentication Server and any possible Supplicant, which can make it unfeasible for small organizations which lack expertise and knowledge.
EAP-TLS is described in [RFC2716].
- EAP-TTLS: Sets up a encrypted TLS-tunnel for safe transport of authentication data. Within the TLS tunnel, (any) other authentication methods may be used.
EAP-TTLS encapsulates another authentication mechanisms. Thus, EAP-TTLS is usually called the outer authentication, while the tunneled mechanism is usually called the inner authentication.
EAP-TTLS consists of two phases:
- Phase 1: A TLS tunnel is established between the Supplicant and the Authentication Server. The X.509 digital certificate of the Authentication Server is used by the Supplicant to verify its identity and thus to validate the network authenticity.
It is very common for this phase to use an anonymous user to avoid sending any user identity in the clear, supplying the real user identity during the inner authentication.
This phase is usually called the outer authentication.
- Phase 2: The TLS tunnel is used to encrypt an older authentication protocol, like an EAP (EAP-MD5, EAP-MSCHAPv2) or non-EAP (PAP, CHAP) authentication protocol that authenticates the Supplicant to the Authentication Server and the network.
This phase is usually called the inner authentication.
The difference with respect to EAP-TLS is that only the Authentication Server is required to own a digital certificate (Supplicant certificates are optional). The Authentication Server digital certificate is used in the outer authentication, that is, in order to establish the TLS tunnel from the Supplicant to the Authentication Server.
EAP-TTLS can tunnel another inner EAP mechanism or an inner non-EAP mechanism. Some non-EAP mechanisms are:
- PAP (Password Authentication Protocol)
- PAP (Challenge Handshake Authentication Protocol)
EAP-TTLS was developed by Funk Software and Meetinghouse, and is currently an IETF draft.
- Phase 1: A TLS tunnel is established between the Supplicant and the Authentication Server. The X.509 digital certificate of the Authentication Server is used by the Supplicant to verify its identity and thus to validate the network authenticity.
- Protected EAP (PEAP): Uses, as EAP-TTLS, an encrypted TLS-tunnel. Supplicant certificates are optional, but Authentication Server certificates are required.
PEAP is very similar to EAP-TTLS, but requires the inner authentication to be another EAP exchange, that is, PEAP can only use EAP-compatible authentication methods. PEAP starts the TLS tunnel, then triggers EAP one more time, encapsulated inside the tunnel, in order to perform the authentication.
Was developed by Microsoft, Cisco, and RSA Security, and is currently an IETF draft.
- EAP-MSCHAPv2: Requires username/password, and is basically an EAP encapsulation of MS-CHAP-v2 [RFC2759]. Usually used inside of a PEAP-encrypted tunnel.
Was developed by Microsoft, and is currently an IETF draft.
Scenario
I’m going to describe how to configure a Wireless Access Point for WPA/WPA2 Enterprise.
Many modern Wireless Access Points support at least WPA Enterprise. Some do also support WPA2 Enterprise, like Apple’s AirPort Extreme Base Station and AirPort Express Base Station. I will use a D-Link DWL-AP2000+ 802.11g 2.4Ghz Wireless Access Point since it’s cheap, works well and supports WPA Enterprise.
The Supplicant (Wireless client) must also support WPA Enterprise. Mac OS X has a built-in supplicant which is WPA/WPA2 Enterprise compatible. Linux and FreeBSD have wpa_supplicant, which supports many of the EAP authentication mechanisms listed above. I will use Mac OS X built-in Supplicant.
The Authentication Server must run a RADIUS-compatible network daemon. I will use FreeRADIUS 1.0.4 as it is open source, free, works well and supports 802.1X. I will run FreeRADIUS inside an VMware Virtual Machine running Fedora Linux Core Development.
EAP-TTLS requires the use of a X.509 certificate for the RADIUS service. I will use OpenSSL to set up a Certificate Authority and generate a X.509 certificate for the RADIUS service.
I have opted to use EAP-TTLS (outer authentication) with inner PAP since it is natively supported by Mac OS X and wpa_supplicant, and it is easy to configure. The inner PAP is provided via EPA-GTC (Generic Token Card). Since PAP sends user names and passwords in the clear, it must be encapsulated inside an EAP mechanisms that provides protection against replaying, eavesdropping, etc.
Generating the X.509 certificates
For more information on setting up a Certificate Authority (CA), creating the private keys, generating the certificate requests and signing those certificates, read Setting up Certificate Authority (CA) using OpenSSL.
Creating the RADIUS X.509 certificate
Generate a new unsigned certificate and its corresponding private key:
openssl req -new -days 365 -newkey rsa:1024 -keyout /etc/pki/CA/sslkey.pem -out /etc/pki/CA/sslcert.pem
The -nodes option can be used to avoid using a pass-phrase to protect the private key. This is optional, since FreeRADIUS can use a pass-phrase protected private key with no problems at all.
Signing the RADIUS X.509 certificate
To sign this certificate:
openssl ca -in /etc/pki/CA/sslcert.pem -out /etc/pki/CA/cert.pem
Installing the RADIUS X.509 certificate
The certificate and its corresponding private key, plus the CA certificate, must be installed into /etc/raddb/certs in order to use EAP-TLS or EAP-TTLS:
Install the RADIUS private key:
mv /etc/pki/CA/sslkey.pem /etc/raddb/certs/RADIUS-key.pem
Install the RADIUS signed X.509 certificate:
mv /etc/pki/CA/cert.pem /etc/raddb/certs/RADIUS-cert.pem
Install the CA certificate:
cp /etc/pki/CA/cacert.pem /etc/raddb/certs/cacert.pem
/etc/pki/CA/sslcert.pem holds the unsigned X.509 RADIUS certificate, so it can be safely removed:
rm /etc/pki/CA/sslcert.pem
Configuring FreeRADIUS
/etc/raddb/clients.conf
The Authenticator will proxy the Supplicant authentication request to the Authentication Server. The Authenticator shares a secret, a pass-phrase, with the RADIUS server. This shared-secret is stored in the /etc/raddb/clients.conf file.
Edit /etc/raddb/clients.conf:
client 192.168.0.0/25 { secret = TheSharedSecretBetweenRADIUSAndTheWAP shortname = MyNetwork }
The client directive specifies the IP subnet from which Supplicants can request authentication via 802.1X. The secret directive specifies the secret shared between the Authenticator (the Wireless Access Point) and the RADIUS server. The shortname directive is a descriptive mnemonic.
The Wireless Access Point must be configured to use WPA Enterprise. The following parameters must be configured:
- RADIUS Server IP: The IP address of the FreeRADIUS server (192.168.0.19).
- RADIUS Port: The port of the FreeRADIUS server (usually 1812/UDP).
- RADIUS Shared Secret: TheSharedSecretBetweenRADIUSAndTheWAP.
/etc/raddb/certs/random
FreeRADIUS stores 1024 bytes of entropy (randomness) in file /etc/raddb/certs/random, but since this is a configuration file, it is usually pre-established. Thus, it is a good idea to reseed it:
dd if=/dev/random of=/etc/raddb/certs/random bs=1 count=1024
/etc/raddb/eap.conf
- Change the default EAP module from EAP-MD5 to EAP-TTLS:
This can be useful if the Supplicant does not force the EAP method to be an specific one. Since Mac OS X built-in supplicant prefers EAP-TTLS with inner PAP, it is a good idea to change the default EAP method:
eap { # Invoke the default supported EAP type when # EAP-Identity response is received. # # The incoming EAP messages DO NOT specify which EAP # type they will be using, so it MUST be set here. # # For now, only one default EAP type may be used at a time. # # If the EAP-Type attribute is set by another module, # then that EAP type takes precedence over the # default type configured here. # default_eap_type = ttls
- Make sure the EAP-GTC module is enabled:
PAP is tunneled inside EAP-TTLS through EAP-GTC:
gtc { # The default challenge, which many clients # ignore.. #challenge = "Password: " # The plain-text response which comes back # is put into a User-Password attribute, # and passed to another module for # authentication. This allows the EAP-GTC # response to be checked against plain-text, # or crypt'd passwords. # # If you say "Local" instead of "PAP", then # the module will look for a User-Password # configured for the request, and do the # authentication itself. # auth_type = PAP }
- Enable the EAP-TLS module:
The EAP-TTLS module depends on EAP-TLS, so EAP-TLS, which is disabled by default, must be enabled:
tls { # Use private_key_password if the RADIUS private key, # stored in RADIUS-key.pem, was protected by a # pass-phrase when it was generated. # private_key_password = whatever private_key_file = ${raddbdir}/certs/RADIUS-key.pem # If Private key & Certificate are located in # the same file, then private_key_file & # certificate_file must contain the same file # name. certificate_file = ${raddbdir}/certs/RADIUS-cert.pem # Trusted Root CA list CA_file = ${raddbdir}/certs/cacert.pem dh_file = ${raddbdir}/certs/dh random_file = ${raddbdir}/certs/random # # This can never exceed the size of a RADIUS # packet (4096 bytes), and is preferably half # that, to accomodate other attributes in # RADIUS packet. On most APs the MAX packet # length is configured between 1500 - 1600 # In these cases, fragment size should be # 1024 or less. # # fragment_size = 1024 # include_length is a flag which is # by default set to yes If set to # yes, Total Length of the message is # included in EVERY packet we send. # If set to no, Total Length of the # message is included ONLY in the # First packet of a fragment series. # # include_length = yes # Check the Certificate Revocation List # # 1) Copy CA certificates and CRLs to same directory. # 2) Execute 'c_rehash '. # 'c_rehash' is OpenSSL's command. # 3) Add 'CA_path=' # to radiusd.conf's tls section. # 4) uncomment the line below. # 5) Restart radiusd # check_crl = yes # # If check_cert_cn is set, the value will # be xlat'ed and checked against the CN # in the client certificate. If the values # do not match, the certificate verification # will fail rejecting the user. # # check_cert_cn = %{User-Name} }
- Enable the EAP-TTLS module, which depends on EAP-TLS:
ttls { # The tunneled EAP session needs a default # EAP type which is separate from the one for # the non-tunneled EAP module. Inside of the # TTLS tunnel, we recommend using EAP-MD5. # If the request does not contain an EAP # conversation, then this configuration entry # is ignored. default_eap_type = gtc # The tunneled authentication request does # not usually contain useful attributes # like 'Calling-Station-Id', etc. These # attributes are outside of the tunnel, # and normally unavailable to the tunneled # authentication request. # # By setting this configuration entry to # 'yes', any attribute which NOT in the # tunneled authentication request, but # which IS available outside of the tunnel, # is copied to the tunneled request. # # allowed values: {no, yes} # copy_request_to_tunnel = no # The reply attributes sent to the NAS are # usually based on the name of the user # 'outside' of the tunnel (usually # 'anonymous'). If you want to send the # reply attributes based on the user name # inside of the tunnel, then set this # configuration entry to 'yes', and the reply # to the NAS will be taken from the reply to # the tunneled request. # # allowed values: {no, yes} # use_tunneled_reply = no }
The default_eap_type directive is configured so, by default, EAP-GTC (configured for PAP) is tunneled inside EAP-TTLS. This is EAP-TTLS with inner PAP.
/etc/raddb/users
This file holds the credentials for the RADIUS users. In this scenario, every Supplicant must supply valid credentials in order to be able to associate with the Wireless Access Point. Those credentials are stored in this file.
For every user, the file stores its user name and its corresponding password, via the User-Password RADIUS attribute.
A sample /etc/raddb/users file:
"testuser" User-Password == "secret" "otheruser" User-Password == "othersecret"
Testing FreeRADIUS
Once FreeRADIUS has been configured to support EAP-TTLS with inner PAP, we need to check if it starts up properly:
/usr/sin/radiusd -X
If FreeRADIUS is working properly, it should spit out something like this:
... Listening on authentication *:1812 Ready to process requests.
If so, press Ctrl+C to stop FreeRADIUS and configure it to start up automatically at next reboot, then start it as a network daemon:
chkconfig radiusd on service radiusd start
Opening the firewall
Next, punch a hole in the firewall to allow RADIUS traffic to pass in. RADIUS authentication service uses port 1812/UDP and 1812/TCP.
Edit /etc/sysconfig/iptables and add the following to lines at the end of the file, before the -j REJECT rule:
-A RH-Firewall-1-INPUT -p udp -m udp --dport 1812 -j ACCEPT -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 1812 -j ACCEPT
NOTE: This assumes the default firewall configuration used by Fedora, where the INPUT and FORWARD chains are blended together into the RH-Firewall-1-INPUT chain.
Then, restart the firewall:
service iptables restart
Configuring the Supplicant
The Mac OS X Supplicant is very straightforward to set up:
- Open the Wireless preferences popup.
- Choose Other…
- Select “WPA Enterprise” from the Wireless Security dropdown.
- Choose “TTLS – PAP” from the 802.1X Configuration dropdown.
This is not needed if the EAP default module was changed from MD5 to TTLS in the /etc/raddb/eap.conf file.
- Enter the Network Name
- Enter the credentials into the User Name and Password fields.
- Click OK.
The Mac OS X Supplicant will complain that the CA certificate used to sign the RADIUS X.509 certificate is not knowm, that is, the CA certificate is not stored in the Key Ring. This is only a warning, so we can click on Continue to proceed.
The Supplicant should start the EAP-TTLS with inner PAP authentication and, after a few seconds, the Wireless network port should have associated with the Wireless Access Point.
The FreeRADIUS /var/log/radius/radius.log log file should reveal the following entries:
Info: Using deprecated naslist file. Support for this will go away soon. Info: rlm_exec: Wait=yes but no output defined. Did you mean output=none? Info: Ready to process requests. Info: rlm_eap_md5: Issuing Challenge Info: rlm_eap_tls: Length Included Error: TLS_accept:error in SSLv3 read client certificate A Info: rlm_eap_tls: Length Included Info: (other): SSL negotiation finished successfully Info: rlm_eap_tls: Length Included
The “Error: TLS_accept:error in SSLv3 read client certificate A” means the Supplicant didn’t supply an X.509 client certificate. This is not exactly an error, since EAP-TTLS does not mandate Supplicants to supply an X.509 client certificate (only EAP-TLS mandates this).
Adding static routes to the Linksys WRT54G
Static routes are stored in a NVRAM variable called static_route. This NVRAM variable is a blank-delimited list of static route entries. Each entry has the following format:
SUBNET_ADDRESS:SUBNET_MASK:GATEWAY:METRIC:INTERFACE
- SUBNET_ADDRESS is the IP subnet address, calculated by applying the netmask to the gateway address, for example.
- SUBNET_MASK is the subnet mask used to disguise which part, of a given IP address, corresponds to the subnet and which part correspond to the host.
- GATEWAY is the IP address of the gateway used to reach the subnet.
- METRIC is the route metric. Routes to the same destination with lower metrics are preferred over those with higher metrics. So, this is usually set to 1 for single-path routes.
- INTERFACE is the interface name used to reach the GATEWAY. Usually it is not needed, as this can be disguised from the current routing table, but the WRT54G implementation of static routes requires this. It is usually vlan0 for LAN-reachable gateways.
During the next boot, the /etc/init.d/S40network initscript will read the static_route NVRAM variable and will inject static entries into the routing table derived from it.
Configuring a silent network interface
A silent network interface is one whose main purpose is to passively monitor for traffic while not revealing or advertising its presence. By default, network interfaces in UNIX-like systems, even when configured with no IP address, could send or respond to ARP traffic, thus defeating its stealthy operation.
To prevent a network interface from sending or responding to ARP traffic, one can configure the network interface to ignore it by supplying the -arp option to ifconfig. This will put the interface into NOARP mode and, when configured with no IP address, will become stealth.
For example:
# ifconfig eth1
eth1 Link encap:Ethernet HWaddr 00:00:00:00:00:00
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
Interrupt:17 Base address:0x4000
# ifconfig eth1 -arp
# ifconfig eth1
eth1 Link encap:Ethernet HWaddr 00:00:00:00:00:00
UP BROADCAST NOARP MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
Interrupt:17 Base address:0x4000
In Fedora Core this can be easily achieved by adding the following line to the network interface configuration file, located in /etc/sysconfig/network-scripts:
ARP=no
For example, this line can be added to file /etc/sysconfig/network-scripts/ifcfg-eth1 so next time interface eth1 is brought up, it will be configured in NOARP mode. This can be done manually using two different commands:
- ifconfig eth1 -arp
- ip link set dev eth1 arp off
To re-enable ARP support:
- ifconfig eth1 arp
- ip link set dev eth1 arp on
How to disable Bonjour in Apple Mac OS X Tiger
I personally don’t want Bonjour (Zeroconf, mDNSResponder, Rendezvous) running all the time, because I rarely use it and because it gives away information such as your username, what services you’re running, computer name and more, depending on what you’re running. From a security perspective, you’re making it easy for an attacker to enumerate services and usernames without even having to do active scanning a lot of the time.
In order to permanently disabled the mDNSResponder daemon, run the following command:
launchctl unload -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
This will unload the daemon from memory and will modify the .plist file so the service will be permanently disabled and won’t be loaded during next startup. In fact, the previous command adds the lines highlighted in bold to the “/System/Library/LaunchDaemons/com.apple.mDNSResponder.plist” file:
cat /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<true/>
<key>Label</key>
<string>com.apple.mDNSResponder</string>
<key>OnDemand</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/usr/sbin/mDNSResponder</string>
<string>-launchdaemon</string>
</array>
<key>ServiceIPC</key>
<false/>
</dict>
</plist>
To reenable the service, simply issue:
launchctl load -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
which will, in turn, remove the previously highlighted lines in bold from the “.plist” file.
NOTE: Disabling Bonjour breaks iTunes support for remote speakers.
Slow or hanged login
Login in Mac OS X could stall when nameservers don’t respond to queries or do it slowly. This can happen during network outages, for example.
I discovered this today, with Mac OS X 10.3.9, while trying to log in. It took forever: the Dock started up, but finder would hang. Accidentally, I found that turning off all network interfaces (like AirPort), solved the problem, Further investigations revealed that my ADSL router had stopped forwarding packets and thus, it was impossible to reach any nameserver.
After a reboot, everything started working properly. However, I was intrigued about the reasons of the stalls during log in. By using “tcpdump” to capture traffic, I discover that my PowerBook was sending out some spureous queries against my ISP’s DNS nameserver:
16:05:33.975493 IP 192.168.0.xx.49152 > 195.235.113.3.domain: 30686+ PTR? 91.0.168.192.in-addr.arpa. (43)
16:05:34.034175 IP 195.235.113.3.domain > 192.168.0.xx.49152: 30686 NXDomain 0/1/0 (120)
192.168.0.xx is the IPv4 address assigned to my AirPort Express NIC, while 195.235.113.3 is my ISP DNS IPv4 address.
Why my system is sending out this PTR query is still a mistery to me and I haven’t been able to block it. It turns out that some component of Mac OS X is also sending out IPv4 (A) and IPv6 (AAAA) queries for “idisk.mac.com”. These can be easily blocked by adding the following entries to “/etc/hosts”:
# Mac OS X queries for these entries during log in,
# which can cause stalls if there is no Internet
# connectivity.
17.250.248.77 idisk.mac.com
::1 idisk.mac.com
Now, login is a little bit faster, but I guess it will hang the next time my router stops working properly.