new articles I guess

This commit is contained in:
Wxcafé (Clément Hertling) 2016-12-24 00:18:51 +01:00
parent 975c2f275b
commit 62d8d84001
6 changed files with 924 additions and 0 deletions

18
content/add.sh Executable file
View File

@ -0,0 +1,18 @@
#!/bin/bash
if [[ -z "$@" ]]; then
echo "add.sh <title>"
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)

View File

@ -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.

165
content/let's_encrypt.md Normal file
View File

@ -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

174
content/openvpn-openbsd.md Normal file
View File

@ -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!

132
content/openwrt-usbnet.md Normal file
View File

@ -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
[](http://pub.wxcafe.net/static/openwrt/tl-mr12u/config), l'image finale est
[](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.

View File

@ -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.