Tag Archive: linux


Recently, I needed to interconnect two private networks using on one side, a SOHO Cisco 871 router (because it’s silent, and people don’t want a desktop appliance to be as loud as an aircraft), and on the other side, an existing linux box with some services we want to connect to.

The main purpose of this setup is not to get optimal performances nor security, but to test interoperability on the two involved IPSec stack.

NAT configuration on the cisco side will be given as a bonus, at the end of this article, as it might be tricky to deal with simultaneous NAT and VPN.

You will find below the schema of our example setup.

netschemaIn our example, let’s assume our PSK is qFcOx72WVERsNobVsimx

Before we begin to overlook the configuration, let’s recall some points on IPSec.

IPSec is a quite complete protocol that can be used in a vast number of use cases: site to site VPNs, roadwarrior remote access, host to host security, with a focus on either integrity or integrity and confidentiality enforcement.

IPSec is thus commonly considered as a complex technology: its features are described and standardized by over 30 IETF RFCs, and it’s modularity reaches such a point that different implementations may not interoperate out of the box as we will see below. Some bonus features are not even standard (e.g. Opportunistic Encryption).

When two endpoints establish a security association (SA), the endpoint that attempt to establish the SA is called the initiator.

To summarize, the protocol works in two phases:

  • Phase 1:the security association and key management, where the two IPSec endpoints mutually authenticate and exchange keys that will be used on phase 2.
  • Phase 2: the security policy(ies) setup, where the two IPSec endpoints decide to do either encryption or authentication of the secured payload, and if they want to secure host to host, or network to network communications.

Here is the list of the different components that are involved in my sample setup:

  • Debian wheezy with a stock 3.2.54-2 kernel and the racoon and ipsec-tools packages from the official repository (version 1:0.8.0-14 for both these packages).
  • Cisco 871 with a Cisco IOS C870 Software (C870-ADVIPSERVICESK9-M), Version 12.4(15)T7, RELEASE (fc3)

Racoon configuration

To begin with, the configuration of racoon was not especially tricky until I experienced a strange issue: when the tunnel was initiated by the linux box, the phase 1 handshake worked properly, but the phase 2 failed to bring up, with a NO-PROPOSAL-CHOSEN error even if sa parameters were matching. If you have more feedback on this, you’re welcome to contribute in the comments. Edit: I have found what was the problem: I forgot to include the second sainfo section in racoon.conf, and I also made a mistake in the cisco configuration. Refer to the appropriate section for further details.

To avoid getting stuck in this case, I managed to make the linux box passive, and to bring up automatically the tunnel using a trick on the cisco side.

Racoon-issued dead peer detection also made my phase 2 die after timeout, as the cisco agent did not send appropriate replies. I addressed this issue by configuring racoon as a passive DPD responder.

/etc/racoon/racoon.conf

path pre_shared_key "/etc/racoon/psk.txt";
path certificate "/etc/racoon/certs";
log notify;

listen
{
	isakmp 198.51.100.37 [500];
}

remote 192.0.2.13 {
	exchange_mode aggressive,main;
	generate_policy off;
	my_identifier address 198.51.100.37;
	peers_identifier address 192.0.2.13;
	lifetime time 3600 sec;	
	passive on;
	
	proposal {
		encryption_algorithm 3des;
                authentication_method pre_shared_key;
                hash_algorithm sha1;
                dh_group 2;
		lifetime time 3600 sec;
	}
}


sainfo address 10.0.0.0/24[any] any address 10.224.9.0/24[any] any {
{
        pfs_group modp1024;
        encryption_algorithm 3des;
        authentication_algorithm hmac_sha1;
        compression_algorithm deflate;
        lifetime time 3600 sec;
}

sainfo address 10.224.9.0/24[any] any address 10.0.0.0/24[any] any {
{
        pfs_group modp1024;
        encryption_algorithm 3des;
        authentication_algorithm hmac_sha1;
        compression_algorithm deflate;
        lifetime time 3600 sec;
}

/etc/racoon/psk.conf

192.0.2.13 	qFcOx72WVERsNobVsimx

/etc/ipsec-tools.conf

#!/usr/sbin/setkey -f

flush;
spdflush;

spdadd 10.0.0.0/24 10.224.9.0/24 any -P out ipsec
    esp/tunnel/198.51.100.37-192.0.2.13/require;

spdadd 10.224.9.0/24 10.0.0.0/24 any -P in ipsec
    esp/tunnel/192.0.2.13-198.51.100.37/require;

Cisco 871 configuration

To get a nailed-up IPSec tunnel at boot time, I decided to set up a permanent ping probe using the ip sla feature of my IOS.

Edit: There was a mistake in the « crypto isakmp profile » section: when you use the match identity host directive, the identifier that follows is a fqdn, not an IP address. If you want to match IP addresses, use the match identity address directive. This is extremely important, as the phase 2 negociation might screw up because of this.

!
version 12.4
no service pad
service timestamps debug datetime msec
service timestamps log datetime msec
no service password-encryption
!
hostname nettest
!
boot-start-marker
boot-end-marker
!
!
no aaa new-model
!
!
dot11 syslog
ip cef
!
!
no ip dhcp use vrf connected
ip dhcp excluded-address 10.224.9.1
!
ip dhcp pool POOL_VLAN1
   network 10.224.9.0 255.255.255.0
   default-router 10.224.9.1 
!
!
ip domain name example.local
!
multilink bundle-name authenticated
!
!
username admin privilege 15 secret 0 youradminpassword
! 
!
crypto isakmp policy 1
 encr 3des
 authentication pre-share
 group 2
 lifetime 3600
crypto isakmp key qFcOx72WVERsNobVsimx address 198.51.100.37 no-xauth
crypto isakmp keepalive 10 3 periodic
crypto isakmp profile 1
   keyring default
   self-identity address
   match identity address 198.51.100.37
   keepalive 25 retry 3
!
!
crypto ipsec transform-set MyTransformSet esp-3des esp-sha-hmac 
!         
crypto map MyMap local-address FastEthernet4
crypto map MyMap isakmp-profile 1
crypto map MyMap 10 ipsec-isakmp 
 set peer 198.51.100.37
 set transform-set MyTransformSet 
 set pfs group2
 set isakmp-profile 1
 match address 150
!
archive
 log config
  hidekeys
!
!
ip tftp source-interface Vlan1
!
!
!
interface FastEthernet0
!
interface FastEthernet1
!
interface FastEthernet2
!
interface FastEthernet3
!
interface FastEthernet4
 description WAN interface
 ip address 192.0.2.13 255.255.255.0
 duplex auto
 speed auto
 crypto map MyMap
!
interface Vlan1
 description Internal interface
 ip address 10.224.9.1 255.255.255.0
 no autostate
!
ip forward-protocol nd
ip classless
ip route 0.0.0.0 0.0.0.0 192.0.2.13
!
!
no ip http server
no ip http secure-server
!
ip sla 10
 icmp-echo 10.0.0.1 source-interface Vlan1
 timeout 1000
 frequency 1
ip sla schedule 10 life forever start-time now
access-list 150 permit ip 10.224.9.0 0.0.0.255 10.0.0.0 0.0.0.255
!
!
!
!         
control-plane
!
banner motd ^C
*************************************************************
$(hostname) - VPN tests cisco router
Contact: Geoffroy GRAMAIZE
*************************************************************
^C
!
line con 0
 logging synchronous
 login local
 no modem enable
line aux 0
line vty 0 4
 logging synchronous
 login local
!
scheduler max-task-time 5000
end

As promised, If you want your internal network, on the cisco side, to communicate with the internet, you should add the following commands to the above configuration:

interface FastEthernet4
 ip nat outside
!
interface Vlan1
 ip nat inside
!
ip access-list extended NAT_list
 deny   ip 10.0.0.0 0.0.0.255 10.224.9.0 0.0.0.255
 deny   ip 10.224.9.0 0.0.0.255 10.0.0.0 0.0.0.255
 permit ip 10.224.9.0 0.0.0.255 any
!
ip nat inside source list NAT_list interface FastEthernet4 overload
Publicité

Standard TLS sessions have a big issue: they are vulnerable to the « wiretap then crack » attack scheme: any intercepted communication can be stored and deciphered when you’ll have/find/factorize the server private key. Network traffic analysers often provide an option to perform such an operation for debug/protocol validation purposes. « Perfect » forward secrecy has been designed to fight against this issue: when two peers want to establish a TLS tunnel with PFS, after performing the server (or the mutual) authentication, they agree on an ephemeral session key.

TLS perfect forward secrecy can be supported in all recent browsers with Apache 2.3+. Version 2.4 has recently been migrated to Debian Jessie. The configuration you will find below has been made with the Qualys SSL Server Test. This test suite is quite useful to review the configuration of your TLS server: it checks the validity of your certificates, the strength of the cipher suite your server offers and gives you information on how common browsers will behave on your website.

Though the grade I get is not perfect, the configuration that I posted below seems to be, at this i’m writing this post, both the most interoperable and the most robust configuration you can create with Apache.

Replace (or add if applicable) the following configuration directives in your SSL module configuration file (most likely to be found in /etc/apache2/mods-enabled/ssl.conf).

SSLProtocol +TLSv1.2 +TLSv1.1 +TLSv1
SSLCompression off
SSLHonorCipherOrder on
SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:AES256-GCM-SHA384:AES256-SHA256:CAMELLIA256-SHA:ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:CAMELLIA128-SHA

then restart your apache server.

Please refer to the configuration at the bottom of this post


UPDATE: Qualys has updated its browser test suite, integrating Opera 12.15 and Firefox 21 on fedora 19, which are both known for not supporting TLS_ECDHE_RSA_WITH_RC4_128_SHA (0xC011).

Fedora community is well known for building FIPS 140-2 compliant cryptographic modules, and FIPS 140-2 happens not to support TLS_ECDHE_RSA_WITH_RC4_128_SHA.

This federal standard is known to only whitelist some cipher suites. In fact FIPS 140-2 doesn’t allow the use of « next » generation algorhithms (such as ECDHE for ephemeral key exchange, or as Galois/Counter Mode for block ciphers) despite the fact they bring significant improvements in terms of bandwidth and computing overhead.

Considering nowadays cryptographic ecosystem, this standard is to be considered as obsolete, except if you plan to sell any cryptographic product to the US goverment.

Ignoring that fact, today’s main security issue is caused by Apple Safari that still has not mitigated the BEAST vulnerability using the (1/n-1) split record trick.

So here is quite embarassing tradeoff you have to deal with: 1. Let your apple clients be vulnerable to BEAST while supporting PFS for any other browser by recommending CBC modes block ciphers and refusing use of RC4 (this will enhance the security for every browser except Safari), 2. Protect everyone against BEAST by using a crippled stream cipher and support PFS with a best-effort policy.

Bonus reminder: even if 3DES-EDE cipher suites use a 168 bit key, real key strength is 112 bits because of its vulnerability to the meet-in-the-middle attack. You may advertise for legacy support purposes, but if you do so, put these suites at the bottom of your server cipherlist, but do not add export or ADH suites are they are respectively weak and vulnerable.


UPDATE 2: After some browser behaviour analysis, I have achieved to get full PFS support for modern browsers, as shown on the pictures below. To do so, you need to properly enable some Diffie-Hellman ciphers. Doing so doesn’t trip the BEAST vulnerability flag and enables PFS for FIPS-compliant browsers that were not supported. The « Key exchange » subgrade in the Qualys SSL Server Test will decrease because DH parameters length are not great, even if they give a sufficient level of security for now.

This grade deterioration is an apache-specific issue: Apache developpers currently assumes that (EC)DH parameter choice is to be build-specific. According to me, this is not an acceptable solution as it makes long term support more difficult. You should consider bumping (voting for) this bugtracker feature request to get a more flexible way to control DH/ECDH parameters in the future.

Replace (or add if applicable) the following configuration directives in your SSL module configuration file (most likely to be found in /etc/apache2/mods-enabled/ssl.conf).

SSLProtocol +TLSv1.2 +TLSv1.1 +TLSv1
SSLCompression off
SSLHonorCipherOrder on
SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:RC4-SHA:AES256-GCM-SHA384:AES256-SHA256:CAMELLIA256-SHA:ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:CAMELLIA128-SHA

then restart your apache server.

Here is the grade I’ve got with the last configuration:

Below, you can see which cipher suites are selected by your clients.

Expert tip: The (1/n-1) split record trick is implemented in Firefox since a while. Thus, you can safely disable RC4 on Firefox in the advanced configuration menu. To do so, enter ‘about:config’ in your address bar, then search for ‘rc4’ and toggle all the found values to ‘false’. If you experience connections issues, toggle back those parameters to true.


An updated version of these cipher suites has been posted in the post 2015, an overview of TLS

En août 2010, OpenSSH 5.6 a ajouté le support de l’authentification serveur par certificats. Cette fonctionnalité peu évoquée va simplifier votre vie, même sur des réseaux de petite taille.

Si la clé de chacune de vos machines est signée par une autorité, les utilisateurs n’auront besoin que de cette autorité pour authentifier les machines de votre réseau. Ceci signifie entre autre le glas du célèbre et embêtant message:

The authenticity of host 'xxxxx (****:****:****::****:****)' can't be established.
RSA key fingerprint is xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx.

L’ampleur de la manœuvre est proportionnelle au nombre de machines dont vous disposez (sachant que c’est facilement scriptable dans certaines conditions), et bien plus simple que la génération de certificats avec openssl.

Tout au long du tutoriel suivant, on va considérer que nous sommes dans un dossier dédié, inaccessible à d’autre utilisateurs que root.

Étape 1: Générer une paire de clés pour l’autorité de certification

Cette paire de clés est sensible, gardez-la en lieu sûr et de préférence chiffrée.

ssh-keygen -b 4096 -t rsa -C "Mon_autorite" -f ca_cert

Étape 2: Signer la clé publique d’un serveur préalablement générée ou rapatriée

La clé publique du serveur à signer se nommera myhost_key.pub pour la suite du tutoriel.

Vous pouvez (et il est suggéré de) restreindre les noms d’hôtes valides pour votre serveur (dans notre cas hostname valid.hostname.org et server.example.com ).

L’exemple ci-dessous délivre une signature valable 1 an et un jour (option -V). Cette durée peut être changée à volonté; pour plus d’informations, echo $( rtfm -p ) 😉

ssh-keygen -h -s ca_cert -I IdentifiantDeLaClé -V +52w1d \
-n hostname,valid.hostname.org,server.example.com myhost_key.pub

Étape 3: Installer le certificat sur votre serveur

L’étape 2 vous a généré un fichier nommé myhost_key-cert.pub. Ce fichier est à copier dans le même dossier que la clé hôte sur le serveur.

Ajoutez la ligne suivante dans le fichier de configuration du démon OpenSSH (généralement /etc/ssh/sshd_config):

HostCertificate /chemin/vers/les/cles/myhost_key-cert.pub

Redémarrez le démon ssh de la machine concernée.

Répétez l’opération avec tous vos serveurs.

Étape 4: Installer les données de l’autorité sur votre compte client SSH.

Gardez le contenu de ca_cert.pub sous la main, vous allez en avoir besoin pour la suite.

Allez dans le dossier ~/.ssh de l’utilisateur concerné par l’installation de votre autorité.

Créez le fichier known_hosts_cert et ajoutez la ligne suivante et sauvez.

@cert-authority * <contenu du fichier ca_cert.pub>

C’est en place! Deux méthodes ensuite:

  • Connectez-vous directement à un de vos serveurs avec la commande suivante
ssh -oUserKnownHostsFile=~/.ssh/known_hosts_cert hostname
  • Ajoutez la ligne suivante à votre fichier .ssh/config pour les hôtes concernés
UserKnownHostsFile ~/.ssh/known_hosts_cert

Connectez-vous ensuite avec votre commande habituelle.

Répétez cette étape pour tous vos utilisateurs.

À ce point du tutoriel, l’authentification devrait marcher sans alerte, même si vous renouvelez et re-signez la clé de hôte.