new articles I guess
This commit is contained in:
parent
975c2f275b
commit
62d8d84001
18
content/add.sh
Executable file
18
content/add.sh
Executable 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)
|
30
content/envie-partout-temps-nulle-part.md
Normal file
30
content/envie-partout-temps-nulle-part.md
Normal 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
165
content/let's_encrypt.md
Normal 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
174
content/openvpn-openbsd.md
Normal 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
132
content/openwrt-usbnet.md
Normal 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
|
||||
[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.
|
405
content/redondance_de_routeurs,_avec_openbsd_et_freebsd.md
Normal file
405
content/redondance_de_routeurs,_avec_openbsd_et_freebsd.md
Normal 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):
|
||||
|
||||

|
||||
|
||||
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.
|
Loading…
x
Reference in New Issue
Block a user