OpenVPN : installation console sous Mac OS X (sans GUI)

OpenVPN est un logiciel client/serveur permettant d’interconnecter des réseaux privés distants (VPN) de manière sûre et sécurisée par le protocole SSL/TLS. Il est disponible pour la plupart des OS, pour peu que ceux-ci possèdent les drivers réseaux virtuels nécessaires : les drivers TUN/TAP.

Sous Mac OS X, le plus simple est d’utiliser le logiciel Tunnelblick qui est un package contenant OpenVPN, une interface graphique et les modules noyaux pour le réseau. Cela convient parfaitement pour une utilisation client, mais aucunement dans le cas d’une configuration serveur. Les scripts de création des certificats utilisateur ne sont d’ailleurs pas fournis. De plus, dans le cas d’une utilisation à distance par console SSH, l’interface graphique n’est pas disponible.

Ce billet vous détaille les étapes principales de l’installation console d’OpenVPN sous Mac OS X.

  • Installation des drivers réseaux :

Rendez-vous sur le site des drivers TUN/TAP pour Mac OS : http://tuntaposx.sourceforge.net/. Téléchargez et installez le package. N’oubliez pas de redémarrer votre système pour que les modules noyaux soient chargés automatiquement. Pour le vérifier, lancez cette commande et contrôlez sa sortie :

$ kextstat

Si les drivers ne sont pas chargés, vous pouvez le faire manuellement :

$ sudo kextload /Library/Extensions/tun.kext
$ sudo kextload /Library/Extensions/tap.kext

Les périphériques réseaux doivent être présents dans /dev :

$ ls /dev/tun* /dev/tap*
/dev/tun0  /dev/tun1  /dev/tun10 /dev/tun11 /dev/tun12 /dev/tun13 /dev/tun14 /dev/tun15 /dev/tun2  /dev/tun3  /dev/tun4  /dev/tun5  /dev/tun6  /dev/tun7  /dev/tun8  /dev/tun9

Un de ces périphériques sera spécifié dans le fichier de configuration de votre connexion VPN.

  • Installation d’OpenVPN :

Je l’installe par le biais de MacPorts :

$ sudo port install openvpn2
--->  Computing dependencies for openvpn2
--->  Dependencies to be installed: lzo2
--->  Fetching lzo2
--->  Attempting to fetch lzo-2.03.tar.gz from http://www.oberhumer.com/opensource/lzo/download/
--->  Verifying checksum(s) for lzo2
--->  Extracting lzo2
--->  Configuring lzo2
--->  Building lzo2
--->  Staging lzo2 into destroot
--->  Installing lzo2 @2.03_2
--->  Activating lzo2 @2.03_2
--->  Cleaning lzo2
--->  Fetching openvpn2
--->  Attempting to fetch openvpn-2.1.1.tar.gz from http://lil.fr.distfiles.macports.org/openvpn2
--->  Verifying checksum(s) for openvpn2
--->  Extracting openvpn2
--->  Configuring openvpn2
--->  Building openvpn2
--->  Staging openvpn2 into destroot
--->  Installing openvpn2 @2.1.1_2
--->  Activating openvpn2 @2.1.1_2
--->  Cleaning openvpn2

Je vous renvoie à la documentation d’OpenVPN pour configurer votre connexion VPN. Pour ma part, j’ai créé le répertoire /opt/local/etc/openvpn2 pour y stocker les fichiers de configuration.

Pour lancer une connexion VPN, rien de plus simple :

$ cd /opt/local/etc/openvpn2
$ sudo openvpn2 --config vpn-sample.conf
Mon Aug  9 09:51:52 2010 OpenVPN 2.1.1 i386-apple-darwin10.4.0 [SSL] [LZO2] built on Aug  9 2010
Mon Aug  9 09:51:52 2010 NOTE: the current --script-security setting may allow this configuration to call user-defined scripts
Enter Private Key Password:
Mon Aug  9 09:51:55 2010 WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this
Mon Aug  9 09:51:55 2010 Control Channel Authentication: using 'interact.lu/ta.key' as a OpenVPN static key file
Mon Aug  9 09:51:55 2010 Outgoing Control Channel Authentication: Using 160 bit message hash 'SHA1' for HMAC authentication
Mon Aug  9 09:51:55 2010 Incoming Control Channel Authentication: Using 160 bit message hash 'SHA1' for HMAC authentication
Mon Aug  9 09:51:55 2010 LZO compression initialized
Mon Aug  9 09:51:55 2010 Control Channel MTU parms [ L:1542 D:166 EF:66 EB:0 ET:0 EL:0 ]
Mon Aug  9 09:51:55 2010 Data Channel MTU parms [ L:1542 D:1450 EF:42 EB:135 ET:0 EL:0 AF:3/1 ]
Mon Aug  9 09:51:55 2010 Local Options hash (VER=V4): '504e774e'
Mon Aug  9 09:51:55 2010 Expected Remote Options hash (VER=V4): '14168603'
Mon Aug  9 09:51:55 2010 Socket Buffers: R=[42080->65536] S=[9216->65536]
Mon Aug  9 09:51:55 2010 UDPv4 link local: [undef]
Mon Aug  9 09:51:55 2010 UDPv4 link remote: 80.80.80.80:1194
Mon Aug  9 09:51:55 2010 TLS: Initial packet from 80.80.80.80:1194, sid=750c51a1 be4999e0
Mon Aug  9 09:51:56 2010 VERIFY OK: depth=1, /C=FR/ST=FR/L=France/O=Sample/CN=Sample_CA/emailAddress=admin@sample.fr
Mon Aug  9 09:51:56 2010 VERIFY OK: nsCertType=SERVER
Mon Aug  9 09:51:56 2010 VERIFY OK: depth=0, /C=FR/ST=FR/L=France/O=Sample/CN=Sample_CA/emailAddress=admin@sample.fr
Mon Aug  9 09:51:57 2010 Data Channel Encrypt: Cipher 'BF-CBC' initialized with 128 bit key
Mon Aug  9 09:51:57 2010 Data Channel Encrypt: Using 160 bit message hash 'SHA1' for HMAC authentication
Mon Aug  9 09:51:57 2010 Data Channel Decrypt: Cipher 'BF-CBC' initialized with 128 bit key
Mon Aug  9 09:51:57 2010 Data Channel Decrypt: Using 160 bit message hash 'SHA1' for HMAC authentication
Mon Aug  9 09:51:57 2010 Control Channel: TLSv1, cipher TLSv1/SSLv3 DHE-RSA-AES256-SHA, 1024 bit RSA
Mon Aug  9 09:51:57 2010 [server] Peer Connection Initiated with 80.80.80.80:1194
Mon Aug  9 09:51:59 2010 SENT CONTROL [server]: 'PUSH_REQUEST' (status=1)
Mon Aug  9 09:51:59 2010 PUSH: Received control message: 'PUSH_REPLY,route 192.168.201.0 255.255.255.0,ping 10,ping-restart 120,dhcp-option DNS 192.168.100.254,route 192.168.1.0 255.255.255.0,route 192.168.2.0 255.255.255.0,route 192.168.100.0 255.255.255.0,ifconfig 192.168.201.1 192.168.201.2'
Mon Aug  9 09:51:59 2010 OPTIONS IMPORT: timers and/or timeouts modified
Mon Aug  9 09:51:59 2010 OPTIONS IMPORT: --ifconfig/up options modified
Mon Aug  9 09:51:59 2010 OPTIONS IMPORT: route options modified
Mon Aug  9 09:51:59 2010 OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified
Mon Aug  9 09:51:59 2010 ROUTE default_gateway=0.0.0.0
Mon Aug  9 09:51:59 2010 TUN/TAP device /dev/tun0 opened
Mon Aug  9 09:51:59 2010 /sbin/ifconfig tun0 delete
Mon Aug  9 09:51:59 2010 /sbin/ifconfig tun0 192.168.201.1 192.168.201.2 mtu 1500 netmask 255.255.255.255 up
Mon Aug  9 09:51:59 2010 /sbin/route add -net 192.168.201.0 192.168.201.2 255.255.255.0
add net 192.168.201.0: gateway 192.168.201.2
Mon Aug  9 09:51:59 2010 /sbin/route add -net 192.168.1.0 192.168.201.2 255.255.255.0
add net 192.168.1.0: gateway 192.168.201.2
Mon Aug  9 09:51:59 2010 /sbin/route add -net 192.168.2.0 192.168.201.2 255.255.255.0
add net 192.168.2.0: gateway 192.168.201.2
Mon Aug  9 09:51:59 2010 /sbin/route add -net 192.168.100.0 192.168.201.2 255.255.255.0
add net 192.168.100.0: gateway 192.168.201.2
Mon Aug  9 09:51:59 2010 Initialization Sequence Completed

Si vous obtenez à la place l’erreur suivante :

Mon Aug  9 09:49:02 2010 Cannot allocate TUN/TAP dev dynamically
Mon Aug  9 09:49:02 2010 Exiting

Cela signifie que les modules noyaux ne sont pas chargés. Reportez-vous à l’étape précédente pour y remédier.

Si vous devez utiliser un serveur DNS différent de votre connexion Internet, créez une nouvelle configuration réseau  dans Préférences Systèmes / Réseau et utilisez les commandes suivantes pour la changer :

$ networksetup -listlocations
Automatic
Sample VPN
$ sudo networksetup -switchtolocation 'Sample VPN'
found it!
$ sudo networksetup -getcurrentlocation
Sample VPN

Au revoir Tunnelblick !

Fichier de configuration client : openvpn.conf

BackupPC : sauvegarder le serveur localhost

Si vous souhaitez sauvegarder les données locales de votre serveur BackupPC (localhost), il faut effectuer une configuration spécifique afin d’éviter le chiffrement inutile par SSH. Je vous fais part des paramètres que j’ai spécifié sur mon serveur BackupPC (qui est également mon poste de travail) :

$Conf{ClientNameAlias} = '127.0.0.1';
$Conf{XferMethod} = 'rsync';
$Conf{RsyncClientCmd} = '$rsyncPath $argList+';
$Conf{RsyncClientRestoreCmd} = '$rsyncPath $argList+';
$Conf{RsyncShareName} = [
  '/Users/bhuisgen/'
];

Les temps de sauvegarde/restauration devraient d’ailleurs être améliorés.

Apache : désactiver le support SSLv2

<VirtualHost 172.16.0.14:443>
   ServerName www.site.fr
   DocumentRoot /home/www/sites/site.fr/www/html
   ErrorLog /home/www/sites/site.fr/www/logs/error_log
   Customlog /home/www/sites/site.fr/www/logs/access_log combined

   SSLEngine on
   SSLProtocol -all +SSLv3 +TLSv1
   SSLCipherSuite ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM
   SSLCertificateFile /etc/apache2/ssl/www_site_fr.crt
   SSLCertificateKeyFile /etc/apache2/ssl/www_site_fr.key
</VirtualHost>

Nginx : désactiver le support SSLv2

server {
   listen       172.16.0.15:443;
   server_name  mon.site.fr;
   root         /usr/local/www/mon.site.fr;
   index        index.php;

   ssl                  on;
   ssl_certificate      ssl/mon_site_fr.crt;
   ssl_certificate_key  ssl/mon_site_fr.key;
   ssl_session_timeout  5m;
   ssl_protocols SSLv3 TLSv1;
   ssl_ciphers HIGH:!ADH:!MD5;
   ssl_prefer_server_ciphers   on;
}

Java : JAX-WS & exception utilisateur

La gestion des exceptions utilisateur au sein d’un webservice utilisant l’API JAX-WS doit respecter quelques contraintes afin de  transmettre l’ensemble des informations au client SOAP.

Voici un exemple pour une classe d’exception UserFault dont les détails optionnels sont implémentés par la classe UserFaultDetail :

@WebFault
public class UserFault extends Exception {
	private static final long serialVersionUID = 1L;
	private UserFaultDetail userFaultDetail;

	/**
	 * Constructs an <code>UserFault</code> object.
	 *
	 * @param message
	 *            the error message.
	 * @param userFaultDetail
	 *            the error details.
	 */
	public UserFault(String message, UserFaultDetail userFaultDetail) {
		super(message);
		this.userFaultDetail = userFaultDetail;
	}

	/**
	 * Constructs an <code>UserFault</code> object.
	 *
	 * @param message
	 *            the error message.
	 * @param userFaultDetail
	 *            the error details.
	 * @param cause
	 *            the error cause.
	 */
	public UserFault(String message, UserFaultDetail userFaultDetail,
			Throwable cause) {
		super(message, cause);
		this.userFaultDetail = userFaultDetail;
	}

	/**
	 * Returns the error details.
	 *
	 * @return the error details.
	 */
	public UserFaultDetail getFaultInfo() {
		return userFaultDetail;
	}
}
public class UserFaultDetail {
	public static final int ERROR_UNKNOWN = 0;
	public static final int ERROR_INVALIDAPIKEY = -1;
	private int code;

	/**
	 * Constructs a new <code>UserFaultDetail</code> object.
	 */
	public UserFaultDetail ()
	{
		this.code = UserFaultDetail.ERROR_UNKNOWN;
	}

	/**
	 * Constructs a new <code>UserFaultDetail</code> object.
	 * @param code the code of the fault.
	 */
	public UserFaultDetail (int code)
	{
		this.code = code;
	}

	/**
	 * Returns the code of the fault.
	 * @return the code.
	 */
	public int getCode() {
		return code;
	}

	/**
	 * Sets the code of the fault.
	 *
	 * @param code
	 */
	public void setCode(int code) {
		this.code = code;
	}
}

Munin : monitorer la température des disques durs sous FreeBSD & Mac OS X


Je vous fais part de mon patch pour le plugin hddtemp_smartctl de Munin afin que la température des disques durs puisse être monitorée sous FreeBSD, OpenBSD, NetBSD et Mac OS X :

http://exchange.munin-monitoring.org/plugins/hddtemp_smartctl/details

Pour rappel, ce plugin nécessite le port sysutils/smartmontools. La commande smartctl n’étant fonctionnelle que sous root, il faut adapter la configuration de Munin dans le fichier /usr/local/etc/munin/plugin-conf.d/plugins.conf :

[hddtemp_smartctl]
user root

Pour tester le bon fonctionnement du plugin, rien de plus simple :

$ perl /usr/local/etc/munin/plugins/hddtemp_smartctl
disk0.value 50

MySQL : activer le mode lecture seule

Pour empêcher les modifications de vos bases de données lors des opérations de maintenance, il est utile d’activer le mode read only de MySQL :

mysql> set GLOBAL read_only=true;

A cet instant, toutes les requêtes d’écritures seront refusées et seul l’utilisateur root pourra effectuer des modifications. Une fois terminées, il faut réactiver le mode read/write :

mysql> set GLOBAL read_only=false;

A noter qu’il existe la méthode du verrou exclusif. Dans ce cas, la connexion client de l’utilisateur root ne doit pas être coupée (le verrou serait automatiquement relâché) et toutes les requêtes d’écriture des utilisateurs, y compris root, seront mises en attente puis exécutées à la libération du verrou :

mysql> FLUSH TABLES WITH READ LOCK;
mysql> [...]
mysql> UNLOCK TABLES

OpenSSL : vérifier la date d’expiration d’un certificat de sécurité

Script pour vérifier la date d’expiration de vos certificats SSL :

#!/bin/bash
#
# check_cert.sh
#
# Boris HUISGEN <bhuisgen@hbis.fr>
#

if [ $# -eq 0 ];
then
   echo "$Usage: $0 <certificate_file>" ;
   exit 1;
fi

FILE=$1

if [ ! -e $FILE ] ; then
   echo "$1 file does not exist."
   exit 2;
fi

EXPIRE_DATE=$(openssl x509 -in $FILE -noout -enddate | cut -f2 -d=);

echo "Certificate file: $FILE";
echo "Expiration date: $EXPIRE_DATE";

exit 0;

Exemple :

# check_cert.sh /usr/local/etc/openvpn/server.crt
Certificate file: /usr/local/etc/openvpn/server.crt
Expiration date: Jun 24 14:31:45 2011 GMT

Mac OS X : placer les widgets Dashboard directement sur le bureau

Pour pouvoir utiliser vos widgets Dashboard directement depuis votre bureau, un paramètre caché est à activer :

$ defaults write com.apple.dashboard devmode YES

Il faut relancer le Dock ensuite :

$ killall Dock

Activez ensuite Dashboard par la touche F12, sélectionnez le widget et commencez à le déplacer. Tout en ne relâchant pas le bouton de la souris, appuyez sur F12. Le widget demeure à présent sur le bureau. Pour l’enlever, faites l’opération inverse.

Note : ce n’est vraiment utile qu’en configuration multi-écrans, étant donné que les widgets seront toujours au premier plan.

Apache : activer la compression gzip

Après avoir compilé et activé le module mod_deflate d’Apache, la directive suivante est à ajouter au virtual host :

<IfModule mod_deflate.c>
   SetOutputFilter DEFLATE

   # disable compression for broken browsers
   BrowserMatch ^Mozilla/4 gzip-only-text/html
   BrowserMatch ^Mozilla/4\.0[678] no-gzip
   BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
   BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

   # disable compression for images
   SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
   # disable compression for other files
   SetEnvIfNoCase Request_URI \.(?:pdf|htc)$ no-gzip dont-vary
   # disable compression for binaries and archives
   SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
   # proxy cache support
   Header append Vary User-Agent env=!dont-vary

   # deflate log support
   #DeflateFilterNote Input instream
   #DeflateFilterNote Output outstream
   #DeflateFilterNote Ratio ratio
   #LogFormat '"%r" %{outstream}n/%{instream}n (%{ratio}n%%)' deflate
   #Customlog /var/log/apache2/deflate_log deflate
</IfModule>
Haut de page