I herd you liek tunnels… (updated)

Tags: , , , , ,
1 Comment »

so i put a tunnel in your tunnel so you can route while you route. Une fois n’est pas coutume, Xzibit résume assez bien la situation.

Mais revenons quelques heures en arrière.

Alors que nos tunnels IPsec fonctionnent sans broncher depuis nos dernières experiences, l’un des objectifs finaux de l’opération montrait le boût de son nez: router des réseaux à travers nos fâmeuses liaisons IPsec. Et “ça marche pas”(tm).
Plus précisemment, il apparaît impossible de joindre d’autres réseaux que ceux liés par IPsec, ou plus particulièrement la SPD, et en y reflechissant à deux fois, ceci est parfaitement normal. La solution ? Un tunnel par dessus le tunnel !

Fort heureusement, nos UNIX modernes bénéficient de systèmes de tunneling peu coûteux en overhead, et parmi eux, gre(4). Pourquoi gre(4) et non gif(4) ? honteuse réponse: IPsec + domU + gif == kernel panic. Si.

En réalité, la mise en place d’un tel mécanisme est beaucoup plus simple qu’il n’y parait, nous allons simplement utiliser la liaison déjà établie par IPsec, 10.0.0.1 vers 10.0.0.2 selon l’exemple du billet précédent, pour établir un tunnel qui ne sera pas soumis à la base stricte d’IPsec et nous permettra de router ce que bon nous semble d’un bout du tunnel à l’autre.

Cela est à nouveau pris en charge très natuellement par NetBSD; il suffit, pour mettre en place cette nouvelle interconnexion, de créer un fichier /etc/ifconfig.gre0 de la forme suivante:

create
inet 10.0.1.1 10.0.1.2 netmask 255.255.255.255
tunnel 10.0.0.1 10.0.0.2 up

pour que s’établisse, sur notre interconnexion IPsec (10.0.0.1 – 10.0.0.2), une nouvelle liaison (10.0.1.1 – 10.0.1.2) libre d’être utilisée comme pivot de routage.

Attention ! Afin que ce petit monde fonctionne sans soucis à chaque démarrage, il ne faudra pas utiliser /etc/ifaliases comme je l’annonçais dans le précédent billet, mais compléter le fichier /etc/ifconfig.iface de cette façon:

up
inet 1.2.3.4 netmask 0xffffff00
inet 10.0.0.1 netmask 0xffffffff alias

car autrement, les alias seront montés après les tunnels gre(4), ifaliases étant manifestement appelé à la suite de ifconfig.if.

More to come…

Y’a plus simple mais c’est moins rigolo (updated)

Tags: , ,
4 Comments »

02 / 08 / 2011 – Mise à jour il-ne-faut-pas utiliser lo0 comme interface pivot, il ne faut pas. Pour une raison que j’ignore totalement, aucun autre protocole qu’ICMP n’a jamais fonctionné pendant nos tests, si d’aucuns ont une explication rationelle, je suis toutes ouïes. Le problème est résolu en utilisant les interfaces physiques.

IPsec. À l’évocation de ce terme technique, vous avez avalé d’un trait votre Gin Tonic, vous éteignez votre écran en espérant qu’il s’agisse d’un mauvais rève et vous décrivez des cercles dans votre bureau en vous frappant la tête avec une règle metallique.
Je le sais, j’étais pareil.

Et puis, avec l’ami mat, nous avons lu, épluché, factorisé, testé, pesté, hurlé, et finalement, je vous propose un petite petite bafouille sur l’art de mettre en place un tunnel IPsec entre deux machines NetBSD. Ouais.

Il me semble que cette configuration est assez classique, jugez plutot: une passerelle, chez vous, disposant d’un bridge vers un réseau quelconque d’opérateur qui fournit une adresse IP fixe publique (si ce n’est pas le cas, vous savez ce qu’il vous reste à faire), et de l’autre coté, une machine dédiée dont vous disposez chez l’un des multiples hébergeurs low-cost aujourd’hui disponibles.
Petite particularité, cette dernière, dans mon cas, est une machine virtuelle NetBSD, un domU hebergé par un dom0 Debian/GNU Linux.

En raison de cette particularité, la première étape consiste à manipuler iptables afin de translater les differents protocoles nécessaires à IPsec directement vers ma machine virtuelle. Sur mon dom0, j’ajoute donc les règles suivantes:

# isakmp
-A PREROUTING -i eth0 -p udp -m udp --dport 500 -j DNAT --to-destination 192.168.2.1:500
# isakmp + nat-t
-A PREROUTING -i eth0 -p udp -m udp --dport 4500 -j DNAT --to-destination 192.168.2.1:4500
# protocole ESP
-A PREROUTING -i eth0 -p esp -j DNAT --to-destination 192.168.2.1
# protocole AH
-A PREROUTING -i eth0 -p ah -j DNAT --to-destination 192.168.2.1

Nous considérerons que l’IP publique de cette machine est 1.2.3.4, l’IP privée du domU est 192.168.2.1.

Le logiciel que nous utiliserons pour établir notre tunnel IPsec, d’un coté et de l’autre, sera le fâmeux racoon.

Je vous jette en pâture la configuration simplifiée que j’utilise, cette dernière étant expliquée point par point à cette adresse:

# cat /etc/racoon/racoon.conf
path pre_shared_key "/etc/racoon/psk.txt";

padding {
    maximum_length 20;
    randomize off;
    strict_check off;
    exclusive_tail off;
}

listen
{
    isakmp 192.168.2.1 [500];
}

remote anonymous
{
    exchange_mode aggressive;
    dpd_delay 20;

    weak_phase1_check on;

    proposal
    {
        encryption_algorithm 3des;
        hash_algorithm sha1;
        authentication_method pre_shared_key;
        dh_group 2;
    }
}

sainfo anonymous
{
    pfs_group 2;
    encryption_algorithm 3des;
    authentication_algorithm hmac_sha1;
    compression_algorithm deflate;
}

Notez que je fais écouter isakmp sur l’adresse privée du domU.
Il faudra créer le fichier /etc/racoon/psk.txt avec des droits stricts (0600), qui contiendra l’adresse IP du peer et une passphrase:

# cat /etc/racoon/psk.txt
5.6.7.8 unepassphrasedunfortbeaugabarit

5.6.7.8 étant l’IP publique de ma passerelle.
Coté passerelle, justement, nous créons l’exacte copie de cette configuration en remplaçant l’ip d’écoute de isakmp et l’ip publique présente dans le fichier /etc/racoon/psk.txt par l’IP publique de notre machine hébergée (1.2.3.4, donc).

Ceci étant fait, il faut maintenant indiquer au noyau pour quels sous-réseaux il est nécessaire de crypter le trafic IP. Cette indication est donnée via l’outil setkey, qui lira le fichier /etc/ipsec.conf sous NetBSD (nous y reviendrons). Un peu de concentration, voici son contenu sur la machine hébergée:

# on fait le ménage
flush;
spdflush;
# et on indique nos routes
spdadd 10.0.0.1/32 10.0.0.2/32  any -P out ipsec esp/tunnel/192.168.2.1-5.6.7.8/require;
spdadd 10.0.0.2/32 10.0.0.1/32 any -P in ipsec esp/tunnel/5.6.7.8-192.168.2.1/require;

Ici, 10.0.0.1 est le “réseau” (une IP unique dans mon cas) joignable à travers IPsec, via le tunnel établi entre l’IP privée de mon domU et l’IP publique de ma passerelle. De l’autre côté, le “réseau” est 10.0.0.2.
Afin de clarifier les choses, voici la configuration coté passerelle:

flush;
spdflush;
spdadd 10.0.0.2/32 10.0.0.1/32  any -P out ipsec esp/tunnel/5.6.7.8-1.2.3.4/require;
spdadd 10.0.0.1/32 10.0.0.2/32 any -P in ipsec esp/tunnel/1.2.3.4-5.6.7.8/require;

Miroir miroir, c’est suykidikihé, on observe que la configuration est l’exacte symétrie de celle présente sur la machine hébergée à cette difference près que notre passerelle s’adresse à une IP publique, le dom0, de l’autre coté, s’occuppe de translater tout ce merdier en IP privée.
Ça va, vous suivez toujours ?
Il ne reste qu’une opération à mener pour que ces réseaux se voient: router effectivement ces divers réseaux entre eux; mais voila, pour l’instant les IPs endpoint du tunnel IPsec n’existent pas, et pour pallier à cela, nous allons une fois de plus abuser de l’ami loopback nous allons utiliser des alias sur les interfaces physiques (virtuelles dans le cas du domU) . Par exemple, sur notre domU:

# ifconfig xennet0 alias 10.0.0.1 netmask 255.255.255.255

Et sur notre passerelle:

# ifconfig sip0 alias 10.0.0.2 netmask 255.255.255.255

Reste à effectivement router ces “réseaux” entre eux, par exemple sur la passerelle:

# route add -host 10.0.0.1 10.0.0.2

Avant d’automatiser tout ce petit monde, vous pouvez d’ores et déjà réaliser quelques tests “live”. Chargez d’abord vos règles SPD des deux côtés:

# setkey -f /etc/ipsec.conf

Puis démarrez racoon en mode debug + verbose, sans passer en tâche de fond:

# racoon -F -d -v -f /etc/racoon/racoon.conf

Une fois satisfaits, nous allons pouvoir automatiser ces opérations afin qu’elles soient prises en compte à chaque boot. Non, nous n’allons pas écrire un script à la con.
Tout d’abord, nous préparons nos interfaces d’alias à l’aide du fichier /etc/ifaliases, sur notre machine hebergée par exemple:

# cat /etc/ifaliases
10.0.0.1 xennet0 255.255.255.255

Puis nous mettons en place les routes statiques:

# cat /etc/route.conf
host 10.0.0.2 10.0.0.1

Enfin, nous indiquons à rc qu’il devra charger la base SPD et démarrer racoon à l’aide du fichier /etc/rc.conf:

ipsec=YES
racoon=YES

Et nous y voila, une connectique sûre, standard et bidirectionelle en un tournemain.

En terme de latence, ça donne ça:
Sans IPsec

64 bytes from 1.2.3.4: icmp_seq=0 ttl=52 time=21.770 ms

Avec IPsec

64 bytes from 10.0.0.1: icmp_seq=0 ttl=255 time=21.869 ms

Tranquille hein.

Je vous livre en sus les quelques liens qui nous ont aidé à peaufiner notre configuration:

  • http://www.kame.net/newsletter/20001119/
  • http://www.netbsd.org/docs/network/ipsec/
  • http://www.netbsd.org/docs/network/ipsec/rasvpn.html
  • http://wtf.hijacked.us/wiki/index.php/IPSEC-Racoon
  • http://www.mad-hacking.net/documentation/linux/networking/ipsec/nat-vpn.xml
  • http://www.lacave.net/~fred/racoon/config.html

Et vous souhaite une bonne nuit.

Rapid’CGI PHP, nginx et NetBSD

Tags: , , ,
3 Comments »

Il y a une foultitude de documentations sur la façon de faire tourner PHP via fastCGI sur un nginx, et à chaque fois, j’ai l’impression de lire des tambouilles copiées/collées de ci et de là. Ça cause de scripts (non portables la plupart du temps), de wrappers, et autres solutions capillotractées, et ça me plaît pas. En dépilant un peu, j’ai abouti à une solution que je trouve élégante… sous NetBSD evidemment :)

Tout d’abord, il s’agit de compiler PHP avec le support fastCGI, sans pollution avec le module CGI. Ceci est réalisé grâce au fichier /etc/mk.conf et la directive suivante:

PKG_OPTIONS.php=        -cgi fastcgi

Un make install clean plus loin, on peut s’assurer du support fastCGI d’un des binaires générés de cette façon:

$ /usr/pkg/libexec/cgi-bin/php -h|grep -i bind
  -b
|
 Bind Path for external FASTCGI Server mode

Il existe dans pkgsrc un outil spécialement dédié à gérer ce type d’implémentation, il s’agit de www/spawn-fcgi, que nous installons donc sans hésiter. spawn-fcgi a le bon goût d’être controlé par le fichier /etc/rc.conf, ainsi, après avoir copié /usr/pkg/share/examples/rc.d/spawnfcgi dans le repertoire /etc/rc.d, on configure le logiciel de cette façon:

$ grep spawn /etc/rc.conf
spawnfcgi=YES
spawnfcgi_jobs="php"
spawnfcgi_php_command="/usr/pkg/libexec/cgi-bin/php"
spawnfcgi_php_args=""
spawnfcgi_php_user="nginx"
spawnfcgi_php_address="127.0.0.1"
spawnfcgi_php_port="9000"
spawnfcgi_php_children="3"

Attention toutefois, il existe un minuscule bug dans rc.d/spawnfcgi que j’ai signalé au mainteneur, voici le patch trivial à appliquer:

--- /usr/pkg/share/examples/rc.d/spawnfcgi      2011-07-24
12:57:38.000000000 +0200
+++ /etc/rc.d/spawnfcgi 2011-07-24 17:16:49.000000000 +0200
@@ -38,6 +38,7 @@
                job_user=$(eval echo \$${name}_${job}_user)
                job_cwd=$(eval echo \$${name}_${job}_cwd)                                       job_socket=$(eval echo \$${name}_${job}_socket)
+               job_port=$(eval echo \$${name}_${job}_port)
                job_socket_mode=$(eval echo \$${name}_${job}_socket_mode)
                job_address=$(eval echo \$${name}_${job}_address)
                job_children=$(eval echo \$${name}_${job}_children)

Update bon, on est jamais mieux servi que par soi-même toussa, j’ai donc corrigé le package dans pkgsrc current. Un ptit cvs up -dP -rHEAD et tout devrait rouler.
Nous pouvons alors démarrer spawnfcgi comme n’importe quel autre service:

$ sudo /etc/rc.d/spawnfcgi start

Et de constater:

$ ps axuww|grep php
nginx     795  0.0  0.8  26412  8012 ?       Is    5:16PM  0:00.17 /usr/pkg/libexec/cgi-bin/php
nginx   18322  0.0  0.7  26412  7816 ?       Is    5:16PM  0:00.14 /usr/pkg/libexec/cgi-bin/php
nginx   22540  0.0  0.8  26412  8012 ?       Is    5:16PM  0:00.18 /usr/pkg/libexec/cgi-bin/php

Eeeeeexcellent Smithers.

Il ne reste alors plus qu’à configurer nginx pour qu’il passe à PHP en mode fastCGI les pages de script à interpréter:

        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /home/user/www$fastcgi_script_name;
            include        /usr/pkg/etc/nginx/fastcgi_params;
        }

Il faudra evidemment prendre soin de remplacer /home/user/www par le chemin de votre documentroot. Il doit d’ailleurs certainement y avoir une variable pour s’épargner cela…

On oublie pas le petit phpinfo() qui va bien:

pkgsrc/net/nagstamon… ça arrive (commited)

Tags: , ,
No Comments »

Il y a quelques jours, nico me faisait découvrir nagstamon. Ce fabuleux petit outil est le pendant du plugin Nagios Checker pour Firefox pour votre bureau UNIX/Linux.

Nagstamon est disponible dans le repository unstable de Debian, mais devinez quoi, pas dans pkgsrc. Ntt.. ntt.. ntt… je ne pouvais pas laisser ce vide perdurer.

Pkgsrc est actuellement en status freeze afin de préparer la sortie de pkgsrc-2010Q1, aussi, nous ne sommes autorisés à commiter que des correctifs mineurs ou impactant la sécurité. Ainsi, pour l’impatient qui souhaite essayer sur le champs ce package, j’ai mis en ligne un .shar du futur package ici même, à déployer dans /usr/pkgsrc/net/nagstamon.

update

À vos CVS :)

Gestion des hôtes dans syslog.conf

Tags: ,
1 Comment »

J’ai, dans mon réseau, des équipements capables d’utiliser le protocole syslog. Bien évidemment, je me suis mis en tête de mettre en route cette fonctionnalité, et ainsi de configurer ma passerelle NetBSD afin qu’elle serve également de serveur syslog.

Syslog est démarré par défaut sous NetBSD, mais uniquement en “secure mode”. On peut constater cela dans le fichier /etc/defaults/rc.conf :

# grep ^syslog /etc/defaults/rc.conf
syslogd=YES             syslogd_flags="-s"      # -s "secure" unix domain only

Le flag "-s" ordonne à syslogd de n’écouter que sur une socket UNIX, au lieu d’une socket UDP. La première étape consiste donc à ajouter dans le fichier /etc/rc.conf la ligne suivante :

syslogd_flags=""

La partie moins triviale réside dans la séparation des logs fonction des hôtes desquels ils proviennent. Je n’ai pas trouvé le man de syslog.conf très explicite, et plusieurs tests ont été nécessaires pour comprendre le mécanisme d’”attachement” d’événements. Voici une partie de mon fichier /etc/syslog.conf :

+host1,host2
*.*                                                     /var/log/hosts.log
-host1,host2

*.err;kern.*;auth.notice;authpriv.none;mail.crit        /dev/console
*.info;auth,authpriv,cron,ftp,kern,lpr,mail.none        /var/log/messages
kern.debug                                              /var/log/messages

L’astuce réside evidemment dans les 3 premières lignes. Il faut les comprendre de cette façon :

  • Pour tous les messages en provenance de host1 et host2, on applique les règles qui suivent
  • Tout type de message est écrit dans /var/log/hosts.log
  • Pour toute autre machine (y compris la machine locale), on applique les règles qui suivent
  • Suivent les règles par defaut du fichier syslog.conf

Moyennant quoi, j’ai désormais un fichier de log distinct par équipement.

Au feu, tournez à gauche

Tags: , , , ,
3 Comments »

Pour des raisons évidentes, j’ai décidé de rendre un peu moins aisée (i.e. pas immédiate) la découverte de mon IP. Plus précisemment, pour certains protocoles et pour certaines machines, je veux que l’IP vue par mon/mes peers ne soit pas directement l’IP que mon fournisseur d’accès m’affecte.

J’ajoute, mais cela n’a evidemment aucun rapport avec cet article, que certains pays intellectuellement plus développés ont recemment confirmé que le partage de fichiers sur le réseau n’était pas illégal sur leur sol.

Le postulat est donc le suivant: seules certaines machines de mon réseau privé devront “sortir” sur une passerelle differente, et uniquement pour certains ports et protocoles.

Pour réaliser cette petite tambouille, j’ai à ma disposition :

  • Un serveur dédié ou virtuel hébergé “ailleurs”, possédant une interface sur une DMZ
  • Le serveur en question fonctionne sous GNU/Linux, on gère donc le NAT et le firewalling grâce à iptables
  • Une passerelle qui me relie à l’Internet par le biais de mon fournisseur d’accès
  • Cette passerelle fonctionne sous NetBSD 5.0.2, on gère le NAT et le firewalling grâce à pf (notez qu’ipf ne permettrait pas, à ma connaissance, d’utiliser les fonctions qui nous seront nécessaires)

La première étape consiste à établir un lien VPN entre la passerelle et le serveur dédié. J’ai utilisé OpenVPN, solution de choix de par sa simplicité, sa souplesse et sa grande stabilité. Étant donné qu’il existe un nombre incalculable de documentations sur cet outil, je colle ici mes configurations client et serveur sans plus de détails :

Sur le serveur :

tls-server

port 4444
dev tun
proto udp
local mon.serveur.dedie

cd /home/imil/etc/openvpn
ca keys/ca.crt
cert keys/dedie.crt
key keys/dedie.key
dh keys/dh1024.pem

client-config-dir ccd

server 10.20.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt

client-to-client
route 192.168.1.0 255.255.255.0

comp-lzo

keepalive 10 60
ping-timer-rem
persist-tun
persist-key

status openvpn-status.log

verb 3

Sur le client :

tls-client

proto udp
dev tun0

remote mon.serveur.dedie 4444

nobind

cd /usr/pkg/etc/openvpn/dedie-keys
ca ca.crt
cert monhost.crt
key monhost.key

comp-lzo

keepalive 10 60
ping-timer-rem
persist-tun
persist-key

pull

verb 3
log /var/log/openvpn.log

Une fois OpenVPN démarré sur chaque point, une interface tun0 monte, avec coté serveur une IP du type 10.20.0.1 et côté client, 10.20.0.6.
Notez que, coté serveur dédié, on verra arriver une machine depuis la passerelle avec son IP réelle sur le réseau domestique, soit ici 192.168.1.0/24. Ainsi, c’est ce sous-réseau que nous devons NATer sur le dédié GNU/Linux.

Une particularité de mon montage est que je ne souhaite pas utiliser l’IP publique principale de mon serveur public car celle-ci possède un reverse sur mon domaine et est facilement identifiable. Par chance, mon hébergeur me donne la possibilité d’ajouter des alias IP routés sur l’interface publique. En l’occurence, c’est précisemment sur cet alias que j’effectue un source NAT plutot que du MASQUERADING :

### règles INPUT
# iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT # j'autorise en entrée les connexions établies et connexes
# iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT # j'autorise l'echo-request
# iptables -A INPUT -p udp -m udp --dport 4444 -j ACCEPT # j'autorise la connexion vers OpenVPN
# iptables -A INPUT -i eth0 -j REJECT --reject-with icmp-port-unreachable # et je rejette tout le reste sur l'interface eth0
### règles de NAT
# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source mon.alias.ip.public

Désormais, si sur ma passerelle je plaçais une route par defaut sur 10.20.0.1 (le boût du tunnel sur le serveur dédié), les machines de mon réseau 192.168.1.0/24 apparaîtraient avec l’IP mon.alias.ip.public.
Cependant, seulement certaines machines, et surtout certains protocoles devront être soumis à cette politique, et c’est grâce à pf, et en particulier la directive route-to, que nous allons mettre en place ce routage conditionnel. Voici les lignes corresponsantes du fichier pf.conf de notre passerelle NetBSD :

int_if="xennet0"

[...]

pass in on $int_if route-to (tun0 10.20.0.1) proto tcp from 192.168.1.10 \
        to any port 80
pass in on $int_if route-to (tun0 10.20.0.1) proto udp from 192.168.1.10 \
        to any port > 10000

Décodage: Concernant le traffic qui arrive sur l’interface interne $int_if, toute demande en provenance de l’IP 192.168.1.10 à destination du protocole HTTP devra être routée vers l’interface tun0 en utilisant l’adresse de passerelle 10.20.0.1.
toute demande en provenance de l’IP 192.168.1.10 à destination de ports UDP supérieurs à 10000 devra être routée vers l’interface tun0 en utilisant l’adresse de passerelle 10.20.0.1.

J’utilise ce routage depuis hier soir, l’overhead du lien VPN est minimal et l’ensemble se comporte correctement. Je ne prétend pas, avec ce système, bénéficier d’un anonymat hors du commun, mais il me permet au moins de ne pas exposer mon IP publique.

WP Theme & Icons based on GlossyBlue by N.Design Studio
Banner from www.trynthlas.com
Entries RSS Comments RSS Log in
Performance Optimization WordPress Plugins by W3 EDGE