diff --git a/content/add.sh b/content/add.sh new file mode 100755 index 0000000..5f5441d --- /dev/null +++ b/content/add.sh @@ -0,0 +1,18 @@ +#!/bin/bash +if [[ -z "$@" ]]; then + echo "add.sh " + exit 1 +fi +title="$@" +filename="$(echo $@ | tr ' ' '_' | tr '[:upper:]' '[:lower:]')" +if [[ -e $filename.md ]]; then + echo "$filename.md already exists" + exit 1 +fi +echo "Title: $title" >> $filename.md +echo "Date: $(date -Iminutes)" >> $filename.md +echo "Author: Wxcafé" >> $filename.md +echo "Category: " >> $filename.md +echo "Slug: " >> $filename.md +echo -e '\n'>> $filename.md +vim +7 $filename.md -s <( echo -n A) diff --git a/content/envie-partout-temps-nulle-part.md b/content/envie-partout-temps-nulle-part.md new file mode 100644 index 0000000..13fea24 --- /dev/null +++ b/content/envie-partout-temps-nulle-part.md @@ -0,0 +1,30 @@ +Title: Envie partout, temps nulle part +Date: 2016-06-13T09:11+02:00 +Author: Wxcafé +Category: Note +Slug: envie-partout-temps-nulle-part + +Ça fait assez longtemps que j'ai pas posté ici, j'en suis bien conscient, et +j'écris donc ce petit post pour dire que c'est le cas, pourquoi c'est le cas, et +que ça va pas durer. + +J'ai beaucoup de choses qui me prennent pas mal de temps en ce moment, +notamment: + +- un boulot, je suis en stage +- la rédaction d'un rapport, puisque... je suis en stage +- la recherche d'une alternance, pour l'an prochain +- un bon nombre de démarches administratives variées +- insert autre raison here. + +par contre, j'ai /énormément/ de choses dont j'aimerais parler, notamment: + +- de la redondance de routeurs, avec CARP, PfSync, dhcpsync et ifstated +- du backup de confs réseau avec Oxidized +- des mésaventures avec debian et nvidia +- du junk hacking sur une liseuse ukrainienne +- des backups automatisés via puppet +- encore d'autres trucs, que j'ai oublié la comme ça mais ça va revenir + + +Du coup, vous inquietez pas, j'ai pas oublié ce blog, et je reviens vite. diff --git a/content/let's_encrypt.md b/content/let's_encrypt.md new file mode 100644 index 0000000..7c67ee1 --- /dev/null +++ b/content/let's_encrypt.md @@ -0,0 +1,165 @@ +Title: Let's Encrypt, enfin +Date: 2015-12-13T18:48+0100 +Author: Wxcafé +Category: Tutoriel +Slug: lets-encrypt-enfin + +Vous avez peut être vu que ce blog, entre autres sites que j'administre, n'est +disponible depuis quelques jours qu'en HTTPS, et avec un certificat valide. Bon, +si vous êtes là, vous avez déjà entendu parler de Let's Encrypt, mais pour les +deux trois du fond on va résumer: + +LE est une nouvelle autorité de certification (ceux qui valident les certificats +SSL), basée sur une organisation, et dont le but est de fournir des certificats +valides, automatiquement et gratuitement. Leur certificat racine est signé par +IdenTrust, et est donc considéré valide par tous les navigateurs modernes. + +Bon, maintenant qu'on est tous au même point, voyons comment ça marche. Depuis +dix jours LE est ouvert en bêta publique, donc il n'est plus nécessaire de +préciser les domaines pour lesquels on veut un certificat sur un formulaire, +comme c'était le cas pendant la période de bêta fermée. Le système qui est +utilisé repose sur le protocole ACME (Automatic Certificate Management +Environment), qui automatise complètement la signature des certificats. Du coup, +les certificats que délivre LE ne sont valides que 90 jours, ce qui serait super +chiant avec une autorité de certification classique, mais qui la veut simplement +dire qu'il faut mettre un cron en place. + +Bref, comment mettre en place vos certificats? On va faire ça sans trop modifier +vos sites, et en automatisant au maximum. LE utilise, dans son système par +défaut, un fichier sur le site web, dont le serveur de certification vérifie +l'existence lors de la requête (si le fichier est présent avec le bon contenu, +c'est que le client tourne bien sur ce domaine, et donc que la personne qui +a demandé le certificat contrôle bien le domaine). Ce fichier est situé dans un +dossier dans la racine, `.well-known`. Plutôt que de se faire chier a gérer ce +dossier pour tous nos vhosts nginx, on va simplement créer un alias vers un +dossier commun sur le système de fichier, que tous les vhosts partagerons, et +qui permettra aussi de valider tous les domaines pour lesquels on veut un +certificat à la fois (avec un AltName) (sur un seul serveur, par contre. Enfin +si vous voulez vraiment vous pouvez faire des mounts cross-serveurs (avec du +sshfs ou des trucs du genre), mais c'est un peu sale quand même. Et faudra quand +même distribuer le certificat après, donc bon...). + +Donc, on va rajouter ça dans nos blocs `server` : + +```shell +location /.well-known { + alias /srv/letsencrypt/.well-known; +} +``` + +(bien sûr il faut créer le dossier, hein.) +Après, on `git clone https://github.com/letsencrypt/letsencrypt`, dans `/opt/` ou +dans `/usr/local/`, peu importe, on le clone quelque part, et on cd dans le +dossier en question. Une fois là, on demande un certificat : + +```shell +sudo ./letsencrypt-auto certonly \ + -a webroot \ + --webroot-path /srv/letsencrypt/ \ + -d <domaine> \ + -d <altName1> \ + -d <altName2> \ + --server https://acme-v01.api.letsencrypt.org/directory +``` + +Normalement, maintenant, on a un certificat valide dans +`/etc/letsencrypt/live/<domaine>/`. Reste à configurer nginx pour qu'il serve +nos sites en https en utilisant notre nouveau certificat. Perso, j'utilise une +template qui ressemble à ça : + +```shell +server { + listen 80; + listen [::]:80; + server_name SERVERNAME; + return 302 https://$server_name$request_uri; +} + +server { + listen 443 ssl; + listen [::]:443 ssl; + ssl_certificate /etc/letsencrypt/live/DOMAIN/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/DOMAIN/privkey.pem; + ssl_dhparam /etc/nginx/dhparams.4096; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"; + ssl_prefer_server_ciphers on; + add_header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"; + + root SERVERROOT; + + index index.html index.htm; + + server_name SERVERNAME; + + server_tokens off; + client_max_body_size 5m; + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + location /.well-known { + alias /srv/letsencrypt/.well-known; + } + + location / { + try_files $uri $uri/ =404; + } +} +``` + +Alors c'est pas /tout à fait ça/ d'un point de vue parano du TLS (genre je +devrais désactiver TLS 1.0 et EECDH+aRSA+RC4, notamment) mais ça marche pas trop +mal et c'est plus compatible comme ça (mon telephone est sous Android 4.4, donc +je suis content d'avoir encore TLS 1.0 par exemple). + +Vous pouvez ajouter votre domaine à la liste préloadée dans Chrome/ium, Firefox, +IE, Edge, Safari, le Tor Browser Bundle, etc... +[ici](https://hstspreload.appspot.com/) (oui ça fait clairement site de +phishing, mais apparemment c'est serieux...) + +Enfin, il nous faut un renouvellement automatique, puisque notre certificat ne +sera valide que 90 jours. On va utiliser un cron tout con, avec un script : + +```shell +00 01 */14 * * /usr/local/bin/cert-renew 2>&1 | mail -s "certificates renewal report" <votre email> +``` + +(oubliez pas que ça doit aller dans le crontab du root) +Et le script qui va bien : + +```shell +#!/bin/bash + +if [[ $UID != 0 ]]; then + echo "please run as root" + exit 1 +fi + +cd /opt/letsencrypt/ + +git pull 2>&1 >> /dev/null + + +# Renewing the cert +./letsencrypt-auto certonly \ + -a webroot --webroot-path /srv/letsencrypt \ + -d <domaine> \ + -d <altName1> \ + -d <altName2> \ + --server https://acme-v01.api.letsencrypt.org/directory \ + --renew \ + 2>&1 + +systemctl restart nginx +exit 0 +``` + +Notez bien le `--renew` qui spécifie qu'on renouvelle le certificat, le `git pull` +qui met à jour le client, et le `systemctl restart nginx` qui prend en compte le +nouveau certificat automatiquement + +Et puis voilà, normalement avec ça vous devriez pouvoir chopper des certificats +valides. C'est plutôt cool, en pratique. + +Merci Let's Encrypt diff --git a/content/openvpn-openbsd.md b/content/openvpn-openbsd.md new file mode 100644 index 0000000..9f4bd4b --- /dev/null +++ b/content/openvpn-openbsd.md @@ -0,0 +1,174 @@ +Title: OpenVPN on OpenBSD +Date: 2016-11-30T23:59+01:00 +Author: Wxcafé +Category: Tutorial +Slug: openvpn-openbsd + +So this is a small article, because I wanted to see if I could write more if +I just wrote small things like that about a single, simple thing I did, without +too much detail and fluff + +Also, I'm writing this in English, while I usually write in French. I'm +switching language because I believe English is a lot easier to express +technical concepts in, or at least I'm more fluent in it when it comes to +expressing technical concepts, and I believe now that my audience (at least, the +people I know/talk to on twitter/IRC/etc...) speak or read English much more +than French, and so it makes more sense for me to write in English here. +Therefore, I'll be writing in English only on this blog from now on. + + +(French version :) +De plus, j'écris ceci en Anglais, alors que j'écrivais ici habituellement en +Français. Je change de langue, parce qu'il me semble qu'il est plus facile +d'exprimer des concepts techniques en Anglais qu'en Français, ou en tout cas +que cela m'est plus facile personnellement, mais aussi parce que je pense que +mon audience (ou en tout cas, les gens que je connais/auxquels je parle sur +twitter/IRC/etc...), parlent ou lisent l'Anglais bien plus que le Français, et +il est donc plus logique pour moi d'écrire en Anglais ici. +J'écrirais donc uniquement en Anglais sur ce blog a partir de maintenant. + +So, now that that's done, I can go on and write that "small article" I promised +at the top. + +So, the idea is that I had a FreeBSD OpenVPN box that I used to have +a semi-decent Internet connection while at school (my school blocks all ports +that are not tcp/80 or tcp/443 or udp/53, basically. And apparently udp/443 +too...). I wanted to try running that VM on OpenBSD, because of three things : + +1. I really like OpenBSD, and wanted to have a VM that I could do some +experiments on without breaking all of my stuff, +2. I found a way to run OpenBSD on the provider I used for that box, +[vultr](https://vultr.com), and +3. why not? + +Anyway, so once you've installed the OS, the first thing to do is + + ::bash + $ doas pkg_add openvpn + +... + +well okay the first thing to do is to + + # vi /etc/doas.conf + +and put this in it : + + ::bash + permit keepenv :wheel as root + permit nopass root as root + +once this is done, you can now go and install the packages, before creating the +CA: + + $ doas pkg_add vim openvpn easy-rsa + $ cd /usr/local/share/easy-rsa + $ doas ./easyrsa init-pki + $ doas ./easyrsa gen-dh + $ doas ./easyrsa build-ca [nopass] + $ doas ./easyrsa build-server-full [CN of the server] [nopass] + $ doas ./easyrsa build-client-full [CN of a client] [nopass] + +please note that you can use passwords on all of those, but then you'll have to +type them every time you use one of them. I see no problem with having +a password on the CA and the client, but the server should be able to restart by +itself in my opinion. + +Anyway, now we can write the config for OpenVPN: + + $ doas mkdir /etc/openvpn/ + $ doas vim /etc/openvpn/openvpn.conf + +We'll run with these settings : + + dev tap + tls-server + cert /usr/local/share/easy-rsa/pki/issued/[CN of the server].crt + key /usr/local/share/easy-rsa/pki/private/[CN of the server].key + ca /usr/local/share/easy-rsa/pki/ca.crt + dh /usr/local/share/easy-rsa/pki/dh.pem + proto udp + port 53 + verb 3 + status /var/log/openvpn-status.log + ifconfig 172.16.0.10 255.255.0.0 + route-gateway 172.16.0.10 + persist-key + persist-tun + keepalive 10 120 + server 172.16.0.0 255.255.0.0 + client-to-client + tls-cipher TLS-DHE-RSA-WITH-AES-256-CBC-SHA TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA + push "route 172.16.0.0 255.255.0.0" + +Of course, feel free to edit that to match whatever you need. + +Anyway, the next thing we need to do is to configure pf. + +What, you thought that was it? Of course we're gonna filter this, it's an +internet-facing server! + + $ doas vim /etc/pf.conf + +So, here is the pf configuration file : + + # $OpenBSD: pf.conf,v 1.54 2014/08/23 05:49:42 deraadt Exp $ + # + # See pf.conf(5) and /etc/examples/pf.conf + + set block-policy drop + set skip on lo0 + block return in on ! lo0 proto tcp to port 6000:6010 + match in all scrub (no-df random-id max-mss 1440) + + block log all + + match out on egress from (tap0:network) to any nat-to (egress:0) + pass out quick + + # ssh + pass in on egress proto tcp from any to (egress) port 22 + + # mosh + pass in on egress proto udp from any to any port 60000:61000 + + # snmp + pass in on egress proto udp from [IP of my SNMP server] to any port 161 + pass in on egress proto udp from [IPv6 block of my SNMP server]/48 to any port 161 + + # openvpn + pass in on egress proto udp from any to (egress) port 53 + pass in on egress proto udp from any to (egress) port 443 rdr-to (egress:0) port 53 + pass in on tap0 + +So, this should be easy enough to read, but just in case : we skip lo, we block +X, we scrub weird packets, we block and log by default. + +Then, we NAT everything that comes out of the VPN and to the 'net. We let what +comes from the server out too, tho that could be improved... + +The next three blocks are easy, and then in the OpenVPN block, we let in port +udp/53, we redirect port udp/443 to udp/53, and we let everything in from the +VPN. + +We have to reload pf and add a sysctl knob if we want to actually route packets +coming from the VPN: + + $ doas pfctl -f /etc/pf.conf + $ echo 'net.inet.ip.forwarding=1' | doas tee -a /etc/sysctl.conf + +And now, we simply enable the OpenVPN service, and we're done: + + $ doas rcctl enable openvpn + $ doas rcctl enable pflogd + $ doas rcctl start openvpn + $ doas rcctl start pflogd + $ doas rcctl ls on # to check + +That's it! It was actually pretty easy, I guess. + +Also, if you don't know what's wrong and want to get a detailed log, run +`/usr/local/sbin/opvnpn --verb 11 --config /etc/openvpn/openvpn.conf` + + +Seeya! diff --git a/content/openwrt-usbnet.md b/content/openwrt-usbnet.md new file mode 100644 index 0000000..34d1518 --- /dev/null +++ b/content/openwrt-usbnet.md @@ -0,0 +1,132 @@ +Title: OpenWRT, l'USBNet, et l'histoire des 4Mo +Date: 2015-10-16 10:27 +Author: Wxcafe +Category: Hacking +Slug: openwrt-usbnet + +Donc, j'ai récemment obtenu un [TP-Link +TL-MR12U](http://www.dx.com/p/tp-link-tl-mr12u-portable-5200mah-mobile-battery-3g-router-white-231188), +qui est vendu comme "routeur 3G portable", mais qui est en réalité une grosse +batterie avec une antenne wifi, un port USB, et un port Ethernet. Perso, ça me +va, vu que je comptais de toute façon pas prendre un deuxième abonnement 3G +juste pour ce truc là (surtout vu la couverture 3G qu'on se tape en France...) + +Bref, tout ça pour dire : quand j'ai reçu ce truc, j'ai tout de suite commencé +par y installer OpenWRT (parce que de 1, je parle pas chinois, et de 2, j'aime +bien avoir des firmwares corrects sur mes routeurs). Bon, c'est super simple, il +suffit de chopper ce fichier +\[binaire\] [la](http://downloads.openwrt.org/chaos_calmer/15.05/ar71xx/generic/openwrt-15.05-ar71xx-generic-tl-mr12u-v1-squashfs-factory.bin), +et de trouver la page d'update (pas forcément super simple en chinois, mais avec +un peu de temps, ça se fait. C'est celle avec un bouton upload). Ensuite on +upload l'image sur le bouzin, et c'est parti. Pas de signatures, pas de +vérifications, osef total, mais bon pour le coup ça m'arrange. + +Une fois ceci fait, je me trouva bien démuni de ne pas pouvoir utiliser le +partage de connexion USB de mon intelliphone android, car l'image OpenWRT par +defaut ne comprend pas USBNet, et ne peut donc pas créer de réseau sur de l'USB. +Qu'à cela ne tienne, me dis-je! Je vais l'installer! +Je courra donc installer le package grâce à `opkg`. Las! Le système n'avait plus +de place. + +... Atta. Le système avait plus de place? J'ai encore rien mis dessus! + +Eh bah ouais. Il se trouve que TP-Link, en 2015, trouve que 4Mo de flash sur un +routeur, c'est largement suffisant, et que de toute façon personne aura jamais +besoin de plus. + +Serieux, mettre 8Mo c'était tellement plus cher? u_u + +Bon, bref, je vais pas m'étendre la dessus. J'ai décidé de saisir mes petits +bras, et de tenter de pousser bien fort pour convaincre OpenWRT qu'il était tout +a fait possible de faire rentrer à la fois le système de base avec LuCi, uhttpd, +un serveur DHCP, etc; et USBNet, dans 4Mo. Ça à pas été vraiment facile, et j'ai +du virer pas mal de trucs, mais... ça fonctionne! + +Bon, alors, comme je suis quelqu'un de sympa, je vais vous filer à la fois le +fichier de config et l'image finale. Si vous voulez pas utiliser une image qui +vient d'un mec que vous connaissez pas, vous pouvez toujours la rebuilder vous +même. Mais avant ça, je vais vite fait expliquer ce qui est dans l'image et ce +qui n'y est pas + +Alors, pour faire rentrer tout ça, vous vous doutez que j'ai du faire quelques +concessions. J'ai donc viré tout ce qui a trait à *PPP*, *PPPoE*, le client +*DHCPv6*, tous les *outils de debug*, quelques *fonctionnalités de busybox*, et +bien sûr *opkg*. Dans ce qui à été ajouté, simplement ce qui est nécessaire au +fonctionnement de *l'USBNet*. + +Une petite modification doit être effectuée pour que le tout fonctionne : le +fichier `package/feeds/luci/luci/Makefile` doit être modifié pour que la +dépendance sur `luci-proto-ppp` ne soit plus présente. Ainsi, on passe de + +```makefile +LUCI_DEPENDS:= \ + +uhttpd +uhttpd-mod-ubus +luci-mod-admin-full +luci-theme-bootstrap \ + +luci-app-firewall +luci-proto-ppp +libiwinfo-lua +IPV6:luci-proto-ipv6 +``` + +à + +```makefile +LUCI_DEPENDS:= \ + +uhttpd +uhttpd-mod-ubus +luci-mod-admin-full +luci-theme-bootstrap \ + +luci-app-firewall +libiwinfo-lua +IPV6:luci-proto-ipv6 +``` + +Une fois que c'est fait, ça devrait mieux marcher (et ça sauve un peu +d'espace...) + +Bon. Le fichier de config est +[là](http://pub.wxcafe.net/static/openwrt/tl-mr12u/config), l'image finale est +[là](http://pub.wxcafe.net/static/openwrt/tl-mr12u/openwrt-15.05-wx-ar71xx-generic-tl-mr12u-v1-squashfs-factory.bin), +et j'ai une petite surprise. + +Bien sûr, le switch situé sur le côté du TL-MR12U ne fonctionne pas sous +OpenWRT de base, parce que c'est un truc lié au hardware et que du coup c'est +assez compliqué à gérer sur une base de matos aussi grande que celle d'OpenWRT. +Bah j'ai à peu près trouvé comment le faire fonctionner. +Voilà le code : + +```shell +#!/bin/sh +if [ $ACTION == "released" ]; then + if [ $BUTTON == "BTN_0" ]; then + # Position is 3G + logger "slider 3G" + elif [ $BUTTON == "BTN_1" ]; then + # Position is Router + logger "slider Router" + fi +elif [ $BUTTON == "BTN_1" ] || [ $BUTTON == "BTN_0" ]; then + if grep -qe "sw1.*in hi" /sys/kernel/debug/gpio\ + && grep -qe "sw2.*in hi" /sys/kernel/debug/gpio; then + # Position is AP + logger "slider AP" + fi +fi +``` + +Et ça va dans `/etc/hotplug.d/button/00-buttons` (créez le chemin, il existera +pas à la base). Du coup là comme ça ça fait rien, ça loggue juste les events. +Mais comme vous êtes pas cons vous avez peut être deviné qu'on pouvait très bien +activer l'USBNet que quand l'interrupteur est en position 3G, le wifi et +l'ethernet quand il est en position AP, et juste la batterie quand il est en +position Router. Par exemple. + +Tiens, d'ailleurs. Pour activer le partage de connexion, suffit pas d'ajouter le +support USBNet. Il faut aussi configurer le système pour qu'il demande un lease +DHCP, toussa. Du coup vous pouvez (peut être, j'ai pas testé) le faire par LuCi, +mais sinon vous pouvez le faire en CLI : + +```shell +uci del network.wan +uci set network.wan=interface +uci set network.wan.ifname=usb0 +uci set network.wan.proto=dhcp +uci commit network +ifup wan +``` + +Et pouf, ça marche. + +Voilà. Amusez vous bien avec votre grosse batterie portable, qui fait maintenant +point d'accès wifi/partage de connexion 3G/whatever. diff --git a/content/redondance_de_routeurs,_avec_openbsd_et_freebsd.md b/content/redondance_de_routeurs,_avec_openbsd_et_freebsd.md new file mode 100644 index 0000000..1f66ea7 --- /dev/null +++ b/content/redondance_de_routeurs,_avec_openbsd_et_freebsd.md @@ -0,0 +1,405 @@ +Title: Redondance de routeurs, avec OpenBSD et FreeBSD +Date: 2016-07-29T17:53+02:00 +Author: Wxcafé +Category: +Slug: redondance-routeurs-openbsd-freebsd + +Depuis le début de mon DUT (il y a deux ans), j'ai découvert le monde du réseau, +alors que j'étais plus système auparavant. Au cours de ce processus, j'ai +pu observer quelques coutumes étranges de ce milieu. Ainsi donc, dans cet étrange +domaine, il arrive parfois qu'on cherche à avoir un réseau stable pendant une +période relativement longue. Bien évidemment, ceci se trouve être un problème +Complexe®, a cause notamment des différents constructeurs de matériel réseau, et +des différents systèmes d'exploitation des machines qui font passer les chatons +dans les tuyaux. + +Bref, en général on règle ce problème de façon relativement simple : en +utilisant un système stable, _par exemple_ OpenBSD. Cependant, ça ne suffit pas +toujours: on peut aussi rencontrer des erreurs hardware. Et puis même OpenBSD +peut rencontrer des problèmes softwares aussi, de temps en temps. Il paraît. +J'ai lu un truc la dessus quelque part. + +Bref, après cette intro complètement objective, on va parler de redondance de +routeurs (c'est a dire la mise en place de deux routeurs hardwares en même +temps, avec un qui prend le relai de l'autre en cas de problème). On va aussi +faire en sorte qu'ils utilisent deux réseaux externes différents (d'opérateurs +séparés, par exemple), pour faire bonne mesure. +Vu que c'est un projet pour mon DUT à la base, et qu'on a fait que du Linux la +bas, j'ai décidé de le réaliser avec un OpenBSD et un FreeBSD, sur un laptop et +une Cubieboard 2 (une board ARM qui traînait chez moi), en utilisant des VLANs +(puisqu'ils n'ont qu'une seule NIC). C'est aussi pour ça qu'il y a un FreeBSD, +vu que la Cubieboard ne supporte qu'assez mal OpenBSD (en tout cas d'après mon +expérience) + +Tout d'abord, je vais mettre [ici](https://pub.wxcafe.net/static/redondance.pdf) +le rapport produit pour mon DUT, comme le veut la tradition du TL;DR (tu le sens +mon LaTeX?). Si vous voulez pas lire cette explication, vous pouvez lire l'autre +explication qui est en PDF et orientée pour des profs de DUT. Si vous êtes prof +de DUT j'imagine que ça peut être intéressant. + +Bon, donc la première chose a faire c'est de définir quelques trucs. La +redondance, on l'a dit, c'est le fait d'avoir plusieurs équipements effectuant +une tâche similaire, pour qu'en cas de panne l'un prenne la place de l'autre +sans interruption. Quelques acronymes : + +- CARP, *Common Address Redundancy +Protocol*, est un protocole (développé par OpenBSD pour remplacer VRRP) qui +permet de faire de la redondance entre des équipements IP, en leur permettant +de partager une adresse IP en switchant rapidement en cas de problème avec l'un +des équipements. + +- PF, *Packet Filter*, est le firewall d'OpenBSD et de FreeBSD. +Enfin, des versions différentes. Mais l'idée est la. (en pratique, la version de +FreeBSD est plus ancienne mais supporte le multi-CPU, contrairement a celle +d'OpenBSD (mais bon, on connait le support multi-CPU d'OpenBSD...)). + +- PfSync, *Packet Filter Synchronisation*, est un service qui permet de +synchroniser la table d'état de deux instances de PF. De cette façon, quand un +des deux crashe, le second peut reprendre les connexions en cours et évite de +couper trop de transmissions. + +- IfStated est un petit programme qui permet de vérifier l'état d'une interface +réseau régulièrement et de lancer des commandes en fonction de l'état de celle +ci. + + +Bon, maintenant que ces définitions sont claires, passons à la réalisation. Le +système OpenBSD sera le serveur primaire, et le FreeBSD sera la réplique, car +OpenBSD est capable de routage multipath (répartition du traffic entre deux +routes de manière égale), ce que FreeBSD ne sait pas faire. Ainsi, si R1 (la +machine OpenBSD) est primaire, elle est capable de transférer une partie du +traffic vers R2 (la machine FreeBSD). Si elle s'arrête de fonctionner, R2 n'a +pas besoin de faire de multipath, puisqu'a ce moment la une seule route valide +est encore disponible. + +La première chose à faire est de configurer le réseau sur nos deux machines. +Puisqu'elles ont toutes les deux une seule interface réseau, nous utilisons des +VLANs (en conjonction avec un switch correct, je vous laisse trouver la +configuration de celui-ci. Il faut connecter les deux machines sur des ports +Trunk). Le VLAN 300 sera utilisé pour le réseau interne, le 400 pour le réseau +externe A et le 500 pour le réseau externe B. Ainsi, on aura un réseau qui +ressemble à ceci : + +``` +╭──╮ ╭─────────────╮ ╭──╮ +│ │ │ Switch │ │ │ +│R1│ │ │ │R2│ +│ │ │ │ │ │ +╰──╯ ╰─────────────╯ ╰──╯ + ╚════════╝ ╚═════════╝ +``` + +en terme physique, et ceci : + +``` + ╔══════╗ ╔══════╗ +╭──╮ ╭────╮ ╭─────╮ ╭────╮ ╭──╮ +│OP│ │ │ │ │ │ │ │OP│ +│ │ │ R1 │ │ LAN │ │ R2 │ │ │ +│A │ │ │ │ │ │ │ │B │ +╰──╯ ╰────╯ ╰─────╯ ╰────╯ ╰──╯ + ╚════════╝ ╚════════╝ +``` + +au niveau réseau. +On va aussi utiliser le réseau 30.30.30.0/24 sur le réseau interne pour cet +exemple. + +Pour ce faire, on configure les routeurs ainsi : + +#### R1 (OpenBSD): + +**/etc/hostname.em0:** + +``` +up +``` + +**/etc/hostname.vlan0:** + +``` +inet 30.30.30.1 255.255.255.0 30.30.30.255 vlan 300 vlandev em0 +``` + +**/etc/hostname.vlan1:** + +``` +dhcp vlan 400 vlandev em0 +``` + +#### R2 (FreeBSD): + +**/etc/rc.conf** + +``` +[...] +vlans_dcw0="300 500" +ifconfig_dwc0_300="inet 30.30.30.2 netmask 255.255.255.0" +ifconfig_dwc0_500="DHCP" +``` + +Une fois ceci fait, nos machines sont configurées sur leurs réseaux externes +respectifs (via DHCP, adaptez si votre réseau externe utilise une autre +méthode) et sur le réseau interne. Il faut bien entendu remplacer les noms +d'interfaces (`em0`, `dcw0`) par le noms des interfaces présentes sur vos +machines. + +Nous allons maintenant configurer la redondance elle même avec CARP. Le réseau +avec lequel nous allons nous retrouver ressemble à ceci : + +``` + ╭───────╮ + ╔═════│ VIP │══════╗ + ║ ╰───────╯ ║ + ║ ║ ║ +╭──╮ ╭────╮ ╭─────╮ ╭────╮ ╭──╮ +│OP│ │ │ │ │ │ │ │OP│ +│ │ │ R1 │ │ LAN │ │ R2 │ │ │ +│A │ │ │ │ │ │ │ │B │ +╰──╯ ╰────╯ ╰─────╯ ╰────╯ ╰──╯ + ╚════════╝ ╚════════╝ +``` + +La configuration de CARP se fait en fait comme pour une interface réseau +classique : + +#### R1: + +**/etc/hostname.carp0:** + +``` +vhid 125 pass pwd12345 carpdev vlan0 advbase 3 advskew 1 state master +30.30.30.254 netmask 255.255.255.0 +``` + +#### R2: + +**/etc/rc.conf:** + +``` +[...] +ifconfig_dwc0_300_alias0="vhid 125 advbase 3 advskew 200 \ + state backup pass pwd12345 alias 30.30.30.254/24" +``` + +Une fois que CARP est mis en place, nous configurons PF, pour filtrer les flux +que nous laissons passer sur notre réseau. Les configurations suivantes, +différentes pour R1 et R2 (puisque FreeBSD et OpenBSD n'utilisent pas les mêmes +versions de PF), sont évidemment à modifier en fonction de votre installation: +elles sont très minimales (ne laissant même pas passer le http...) + +#### Pour R1: + +**/etc/pf.conf:** + +``` +set skip on lo + +# définition des variables +int="30.30.30.0/24" +ext="0.0.0.0/0" +int_addr="30.30.30.1" +int_if="vlan0" +ext_if="vlan1" + +# defaut : bloquage +block all + +# vérification des paquets, anti-spoofing +antispoof for $int_if +antispoof for $ext_if + +# nous laissons passer l'icmp +pass proto icmp + +# nous mettons en place le NAT de l'interieur vers Internet +pass in on $int_if from $int to any keep state +pass out on $ext_if from $int to $ext nat-to $int_if keep state + +# carp, pfsync et dhcpsync +pass out on $int_if proto carp keep state +pass quick on $int_if proto pfsync keep state +pass in on $int_if proto udp to any port 8067 keep state +pass out on $int_if proto udp to any port 8067 keep state + +# nous laissons passer les connexions SSH vers le routeur +pass in on $int_if proto tcp from $int to $int_addr port ssh keep state +pass out on $int_if proto tcp from $int_addr port ssh to $int keep state +``` + +#### Et pour R2: + +**/etc/pf.conf:** + +``` +set skip on lo + +# définition des variables +int="30.30.30.0/24" +ext="0.0.0.0/0" +int_addr="30.30.30.2" +int_if="dwc0.300" +ext_if="dwc0.500" + +# défaut : bloquage +block all + +# vérification des paquets, anti-spoofing +antispoof for $int_if +antispoof for $ext_if + +# nous laissons passer l'icmp +pass proto icmp + +# nous mettons en place le NAT de l'interieur vers Internet +nat on $ext_if from $int to any -> ($ext_if) +pass in on $int_if from $int to any keep state +pass out on $ext_if from any to $ext + +# carp, pfsync et dhcpsync +pass out on $int_if inet proto carp keep state +pass quick on $int_if inet proto pfsync keep state +pass in on $int_if inet proto udp to port 8067 keep state +pass out on $int_if inet proto udp to port 8067 keep state + +# nous laissons passer les connexions SSH vers le routeur +pass in on $int_if inet proto tcp from $int to $int_addr \ +port ssh keep state +pass out on $int_if inet proto tcp from $int to $int_addr \ +port ssh keep state +``` + +Une fois que PF est configuré, on passe a pfsync, qui permet de synchroniser +l'état de deux instances de PF, même de versions différentes (je trouve ce truc +génial): + +#### Pour R1: + +**/etc/hostname.pfsync0:** + +``` +syncdev vlan0 syncpeer 30.30.30.2 +``` + +#### Et pour R2: + +**/etc/rc.conf:** + +``` +pfsync_enable="YES" +pfsync_syncdev="dwc0.300" +pfsync_syncpeer="30.30.30.1" +``` + +Passons à ifstated. Puisque R1 supporte le multihoming mais pas R2, nous allons +faire en sorte que R1 aie une route multipath vers R2. De cette façon, R1 (qui +est la machine principale pour CARP, et reçoit donc toutes les connexions venant +du réseau interne), transmet la moitié de ces connexions vers R2, qui les gère +comme nécessaire. Si R1 arrête de fonctionner, R2 récupère l'ensemble des +connexions (grâce a CARP), qui ne sont pas interrompues (grâce a pfsync). Si R2 +arrête de fonctionner, ifstated rentre en action et retire la route multipath de +R1 vers R2, ce qui permet d'éviter de transmettre la moitié des connexions à un +routeur qui ne fonctionne plus (c'est en général une chose a éviter). + +Par conséquent, la configuration d'ifstated n'a à être effectuée que sur R1 : + +**/etc/ifstated.conf:** + +``` +peer = '( "ping -q -c 1 -w 3 30.30.30.2>/dev/null" every 5 )' + +state auto { + if $peer + set-state multihome + if ! $peer + set-state singlehome +} +state multihome { + init { + run "route add -mpath default 30.30.30.2" + } + if ! $peer + set-state singlehome +} +state singlehome { + init { + run "route delete default 30.30.30.2" + } + if $peer + set-state multihome + } + +init-state auto +``` + +Enfin, dernier point a configurer, la synchronisation DHCP. Elle nous permet de +faire en sorte que les machines gardent les mêmes adresses IP même si un des +deux routeurs reste en rade pendant une période prolongée. On configure donc +`isc-dhcpd` sur les deux routeurs, comme suit: + +#### R1: + +**/etc/dhcpd.conf:** + +``` +authoritative; +ddns-update-style none; + +failover peer "dhcp-failover" { + primary; + address 30.30.30.1; + port 8067; + peer address 30.30.30.2; + peer port 8067; +} + +subnet 30.30.30.0 netmask 255.255.255.0 { + option routers 30.30.30.254; + option domain-name-servers 30.30.30.254; + pool { + failover peer "dhcp-failover"; + max-lease-time 86400; + range 30.30.30.10 30.30.30.250; + } +} +``` + +#### Et pour R2: + +**/usr/local/etc/dhcpd.conf:** + +``` +authoritative; +ddns-update-style none; + +failover peer "dhcp-failover" { + secondary; + address 30.30.30.2; + port 8067; + peer address 30.30.30.1; + peer port 8067; +} + +subnet 30.30.30.0 netmask 255.255.255.0 { + option routers 30.30.30.254; + option domain-name-servers 30.30.30.254; + pool { + failover peer "dhcp-failover"; + max-lease-time 86400; + range 30.30.30.10 30.30.30.250; + } +} +``` + +Et voilà! Notre réseau ressemble désormais à ça (j'ai repris le schéma de mon +rapport, j'ai pas le courage de le refaire en texte encore): + +![schéma](https://pub.wxcafe.net/img/schema_redondance_routeurs.png) + +avec le PC1 qui représente le réseau local. + +Si vous avez bien lu la configuration du serveur DHCP, il reste encore à mettre +en place un serveur DNS écoutant sur l'IP virtuelle, donc a priori synchronisé +entre les deux routeurs. Comme c'est quelque chose de simple a mettre en place +et que c'est assez bien documenté ailleurs, je laisse cette tâche comme exercice +aux lecteurs-ices.