Changer l'adresse IP d'un serveur

Aujourd’hui il n’est pas rare d’avoir à changer l’adresse IP d’un serveur, par exemple si vous changez de fournisseur.

Dans mon cas je devais migrer tout mes services, à savoir du web, du mail et du dns, d’un serveur à un autre sans avoir la possibilité de garder mon adresse IP. L’occasion pour moi de vous donner quelques bons conseils sur cette opération toujours un peu délicate. Le but étant d’avoir un minimum de temps de coupure.

Donc la première bonne chose à faire c’est de baisser le TTL de vos enregistrement DNS, c’est tout simplement le temps en secondes pendant lequel l’enregistrement pourra rester en cache sur les serveurs DNS récursifs, comme ça le jour où vous changez l’enregistrement DNS la propagation ira beaucoup plus vite.

Moi je suis passé de 1 jour, ou 86400 secondes, à 5 minutes, soit 300 secondes:

mail 300 IN A 178.33.42.27

Évidement dans mon cas il faudrait attendre un jour le temps que le nouveau TTL se propage et ensuite espérer n’avoir que 5 minutes de problèmes. Mais ça suppose que le serveur DNS de vos visiteurs respecte bien le TTL que vous avez indiqué, et ce n’est pas toujours le cas et puis 5 minutes c’est déjà trop long pour un perfectioniste comme vous non ?

Donc les idées qui viennent ensuite sont de rendre accessible le service depuis l’ancien serveur même si le service tourne sur le nouveau serveur. Surtout si vous avez un VPN entre vos deux serveurs. On peut par exemple monter des proxy inverses voire même faire du NAT mais ces deux solutions ont le désavantage de modifier l’adresse IP source des requêtes, ce qui peut être très gênant si comme moi vous utilisez des antispam basés sur l’adresse IP comme le DNSBL.

La solution que j’ai utilisée c’est tout simplement de faire du routage à travers mon VPN, l’idée est simple mais dans les faits c’est assez compliqué. Voilà un schéma simplifié du réseau:

                 +----------------+                                    +-----------------+
<- 1.2.3.4 eth0 -| Ancien serveur | vpn0 10.0.0.1 <---> 10.0.0.2 vpn0 -| Nouveau serveur |- eth0 5.6.7.8 ->
                 +----------------+                                    +-----------------+

Ce que l’on veut c’est qu’un visiteur qui se connecte sur 1.2.3.4 soit routé dans le VPN jusqu’au service qui tourne sur le nouveau serveur (et qui écoute sur 10.0.0.2 et sur 5.6.7.8).

Une redirection comme ça est un cas d’école avec iptables, par exemple pour le port http:

vieux:~# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport http -j DNAT --to 10.0.0.2

Là le paquet va bien arriver sur 10.0.0.2, mais les paquets retour vont repartir avec l’IP source 5.6.7.8 car c’est la route par défaut pour répondre à l’IP de votre visiteur. Du coup il faut faire une table de routage dédiée à ce traffic pour faire en sorte que tout ce qui arrive sur 10.0.0.2 reparte sur 10.0.0.1

nouveau:~# echo "200 VPN" >> /etc/iproute2/rt_tables
nouveau:~# ip route add default via 10.0.0.1 dev vpn0 table VPN
nouveau:~# iptables -t mangle -A PREROUTING -i vpn0 -p tcp -m connmark --ctstate NEW -j CONNMARK --set-mark 1
nouveau:~# iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
nouveau:~# ip rule add fwmark 1 table VPN

Ici on crée une table de routage “VPN” qui a une route par défaut vers 10.0.0.1. Ensuite avec iptables on matche les connexions tcp qui arrivent sur l’interface vpn0 (CONNMARK) avec le numéro arbitraire 1.

La deuxième règle iptables sert à marquer les paquets qui ont CONNMARK à 1 avec MARK à 1, c’est équivalent à iptables -t mangle -A PREROUTING -m connmark --mark 1 -j MARK --set-mark 1. CONNMARK marque les connections et MARK les paquets mais iproute (la commande suivante) ne comprends que le marquage des paquets.

La dernière commande ip rule add fwmark 1 table VPN permet de dire au système de routage d’utiliser la table de routage “VPN” quand les paquets sont marqués à 1.

À ce stade les paquets retour reviennent bien sur l’ancien serveur, il ne reste plus qu’à faire du source NAT pour qu’ils repartent avec l’IP 1.2.3.4:

vieux:~# iptables -t nat -A POSTROUTING -s 10.0.0.2 -o eth0 -j SNAT --to-source 1.2.3.4

Et voilà, le service est accessible depuis les deux adresses publiques, et dans les deux cas le service verra la vraie adresse source du client.