Ma configuration IPv6

IPv6, ça fait des années que tout le monde en parle, ça apporte plein de bonnes choses, mais on y migre que très lentement. Il faut dire que j'ai toujours détesté les différents guides que j'ai trouvé. Ces derniers étaient soit d'un niveau débutant et n'expliquaient que ce que je savais déjà, soit destinés aux experts et je n'y comprenais rien. Du coup voici comment j'ai mis en place IPv6 sur ma dedibox tournant sous Arch Linux.

Pourquoi IPv6 ?

Je vais commencer par un argument politique : pour soutenir les petits acteurs et favoriser l'innovation. Actuellement, les stocks d'IPv4 sont par endroits épuisés, tout a été distribué à différentes entités qui se font un plaisir d'investir dessus. Si vous aussi vous pensez que les nouveaux petits acteurs innovants ne devraient pas avoir besoin d'acheter des IPv4 à prix d'or auprès de requins des télécoms, alors ne faites pas en sorte que ce soit une nécessité.

Ensuite un premier argument technique : simplifier les réseaux. Le NAT et, pire, le CGNAT sont des technologies complexes aux effets de bords on ne peut plus néfastes. Les adeptes du jeu en ligne ou de l'auto-hébergement en savent quelque chose.

Et enfin parce pour les serveurs web c'est quand même nettement plus simple de faire en sorte que chaque application soit servie sur une adresse IP différente. Fini les problèmes avec les clients ne supportant pas le SNI ou la prise de tête savoir quel certificat de sécurité présenter lorsque le client n'indique pas de domaine connu.

dhcpcd

De base, ma dedibox installée sous Arch Linux utilise dhcpcd pour sa connectivité IPv4. Ça tombe bien car j'ai un très mauvais souvenir de dibbler et dhclient, ce dernier étant pourtant recommandé par la documentation d'online.

C'est partit, on commence par dé-commenter duid et noipv6rs du /etc/dhcpcd.conf et on colle le DUID fourni sur l'interface de gestion dans /var/lib/dhcpcd/duid (ou /etc/dhcpcd.duid pour dhcpcd 6, l'emplacement a changé avec dhcpcd 7). Ensuite attaquons nous à la configuration de l'interface réseau, ici eno1 :

interface eno1
  static ip_address=198.51.100.42
  static routers=198.51.100.1
  static domain_name_servers=192.0.2.10 192.0.2.12
  static ip6_address=2001:db8::42
  ipv6rs
  iaid 1
  ia_pd 2 eno2/0

Ce que l'on avait de base :

  • static ip_address : mon adresse IPv4 ;
  • static routers : l'adresse IPv4 du routeur ;
  • static domain_name_servers : les adresses des serveur DNS ;

Ce que l'on ajoute :

  • static ip6_address : une adresse IP tirée du bloc qui nous est alloué ;
  • ipv6rs : autorise la découverte de routes IPv6 sur cette interface (nous l'avons désactivée globalement) ;
  • iaid 1 : associe un identifiant à notre interface ;
  • ia_pd 2 eno2/0 : on demande la délégation du préfixe IPv6 qui nous est attribué et, vu que nous serons de « routeur », nous l'assignons à une autre interface.

Ici, l'interface eno2 correspond à mon RPN comme ça, si un jour j'ai d'autres machines dessus, ces dernières pourront utiliser les adresses IPv6 de mon bloc.

Plus d'adresses

C'est bien joli d'avoir configuré dhcpcd, mais ce dernier ne nous donne qu'une seule IPv6 et il n'y a rien pour en avoir d'autres. J'ai donc créé deux fichiers :

  • /usr/bin/myipv6ctl : un script permettant d'ajouter et retirer un lot d'IPv6 sur mon interface ;
  • /etc/systemd/system/myipv6ctl.service : un service oneshot pour systemd appelant le script précédent.

Pour myipv6ctl j'ai eu la flemme de faire un vrai programme lisant un fichier de config, alors les adresses IP et l'interface sont directement en dur à l'intérieur. Un détail qui a son importance, lors de l'ajout des adresses j'utilise preferred_lft 0 afin que pour les connexions sortantes j'utilise toujours l'adresse fournie par dhcpcd et non une au hasard.

Niveau code ça donne ceci :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#!/bin/sh
#
# Copyright (c) 2017, Rodolphe Breard
# Author: Rodolphe Breard
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

set -euo pipefail
IFS=$'\n\t'

INTERFACE="eno1"
IP_LIST=("2001:db8::69", "2001:db8::beef", "2001:db8::dead")

usage() {
    >&2 echo "usage: $0 <command>"
    >&2 echo ""
    >&2 echo "Commands:"
    >&2 echo "     add"
    >&2 echo "     remove|rm"
    exit 1
}

ip_exists() {
    IP="$1"
    ip address show dev "$INTERFACE" | grep "$IP"
}

ip_add() {
    IP="$1"
    if [ ! $(ip_exists "$1") ]; then
        ip address add "${IP}/128" dev "$INTERFACE" preferred_lft 0
    fi
}

ip_remove() {
    IP="$1"
    if [ $(ip_exists "$1") ]; then
        ip address del "$IP" dev "$INTERFACE"
    fi
}

ip_apply() {
    ACTION="$1"
    for ip in ${IP_LIST[@]}; do
        "ip_$ACTION" "$ip"
    done
}

if [ "$#" -lt 1 ]; then
    usage "$0"
fi
case "$1" in
    "add")
        ip_apply "add"
        ;;
    "remove"|"rm")
        ip_apply "remove"
        ;;
    *)
        usage "$0"
        ;;
esac

N'oubliez pas de le rendre exécutable à l'aide d'un sudo chmod a+x /usr/bin/myipv6ctl.

[Unit]
Description=Setup IPv6 additional addresses
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/myipv6ctl add
RemainAfterExit=true
ExecStop=/usr/bin/myipv6ctl remove
StandardOutput=journal

[Install]
WantedBy=multi-user.target

Un petit coup de sudo systemctl enable myipv6ctl.service puis de sudo systemctl start myipv6ctl.service et c'est fini !

Reverse IPv6

Afin que les gens puissent trouver le nom de domaine associé à une de nos adresses IPv6, nous allons monter un serveur DNS capable de répondre à ce genre de requêtes. N'oubliez pas de lui donner délégation, chez online.net ça se fait via l'interface de gestion IPv6.

Pour le serveur DNS, j'utilise PowerDNS configuré avec bind-config=/etc/powerdns/named.conf. Dans ce named.conf on indique la zone sur laquelle nous faisons autorité et où se trouve le fichier de configuration associé :

zone "0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa" in {
    type master;
    file "/etc/powerdns/zones/0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.zone"
};

Et donc le fichier de zone lui même :

$ORIGIN 0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
$TTL    1h

@                                       IN      SOA     example.com. admin.example.com. (
                                                        2017120201       ; Serial
                                                        8h               ; Refresh
                                                        3h               ; Retry
                                                        4w               ; Expire
                                                        1h               ; Negative Response TTL
                                                )
                                        IN      NS      example.com.
2.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN      PTR     example.com.
9.6.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN      PTR     toto.example.com.
f.e.e.b.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN      PTR     titi.example.com.
d.a.e.d.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN      PTR     tutu.example.com.

Pour tester, vous pouvez utiliser dig:

dig +short -x 2001:db8::42

Si rien ne sort, préciser l'adresse de votre serveur DNS afin de vérifier si c'est lui qui a un problème ou non :

dig +short -x 2001:db8::42 @198.51.100.42

Tags