27 avril 2024

Source-Routing, ou comment router en fonction de la source

Encore un article sur le réseau… Oui, c’est la période…

Et pour le coup, on va parler de « source routing », ou l’art et la manière de router un paquet non pas en fonction de sa destination (mais on peu aussi en parallèle) mais surtout, en fonction d’où il vient.

Et mine de rien, ce peut être utile.

Ici, je présente le concept dans un cas simple, dans la série d’articles sur Strongswan, on en reparlera dans un cadre plus particulier.

 

I – Le problème

Le problème se passe au niveau de ma seconde IP FO (que j’utilise pour mon serveur mail).

Le routeur est configuré ainsi au niveau du réseau :

auto eth0
iface eth0 inet static
 address XXX.XXX.XXX.XXX
 netmask 255.255.255.0
 gateway GATEWAY

[...]

auto eth4
iface eth4 inet static
 address YYY.YYY.YYY.YYY
 netmask 255.255.255.0

Et les quelques règles :

iptables -t nat -A PREROUTING -d YYY.YYY.YYY.YYY -p tcp -m multiport --dports 25,80,443,465,587,993,4190 -j DNAT --to-destination 10.10.1.100
iptables -t filter -A FORWARD -p tcp -d 10.10.1.100 -m multiport --dports 25,80,443,465,587,993,4190 -j ACCEPT


iptables -t nat -A POSTROUTING -s 10.10.1.100 -p tcp -m multiport --dports 25,80,443,465,587 -j SNAT --to YYY.YYY.YYY.YYY

En entrée, je redirige tout ce qui concerne le mail et aussi les ports web (pour le certificat Let’s Encrypt du serveur mail).

En sortie, le serveur mail peut utiliser les differents smtp (25,465,587) et aussi le web (80,443).

Et une fois en production, tout semble fonctionner sans soucis.

Les communications se font bien, les IPS sources sont correctes, a priori, tout parait parfait.

Mais en y regardant de plus près, les flux sont « curieux » …

A  travers mes outils de monitoring, je me suis rendu compte que les paquets à destination de IP.EXTERNE.MAIL arrivent bien sur eth4 sur le routeur, mais les retours partent depuis eth0… Hum…

De même, quand mon serveur de messagerie communique avec l’extérieur, du routeur, il sort bien avec l’IP IP.EXTERNE.MAIL, mais la aussi, par l’interface eth0.

En volumétrie OUT sur l’interface eth4 du routeur, c’est nada, walou, queuchi…
Si en soit, ça ne m’a jamais bloqué et n’empêche en rien le bon fonctionnement, ça m’ennuie, car mes mesures ne sont pas correctes.
Et je suis du genre à aimer les trucs bien fagotés.

Mais au final, pourquoi donc cette diablerie ?

Et bien, c’est ainsi que fonctionne Linux par défaut. Par défaut, la table de routage, c’est la table main :

# ip route show table main

default via GATEWAY dev eth0 onlink

Et on voit bien que le moyen d’atteindre une gateway (celle d’Online donc), c’est sur eth0.

Mais il faut savoir comment cette table est appelée, et ça, c’est :

# ip rule

0:     from all lookup local
32766: from all lookup main
32767: from all lookup default

En fait, la règle 32766 stipule que quelque soit la provenance, on regarde la table main.

Quelque soit la provenance ? Tiens, intéressant… C’est la qu’on va pouvoir router en fonction de la source !

 

II – Nouvelle table

Au niveau du routeur, on va créer la nouvelle table de routage.

Si vous voulez les nommer, vous pouvez alors utiliser le fichier /etc/iproute2/rt_tables

1 matable1

Dans ce cas, vous pouvez utiliser dans les commandes soit le chiffre soit le nom.

L’idée est d’ajouter, dans cette table une route vers la Gateway en passant bien par eth4.

# ip route add default via GATEWAY dev eth4 table 1

Et :

RTNETLINK answers: Network is unreachable

Pourquoi j’ai cette erreur ?

En fait, selon vos routes de bases, ça peut passer sans encombre.

Chez moi, ma VM routeur, après boot affiche deux routes :

XXX.XXX.XXX.0   0.0.0.0   255.255.255.0 ... eth0
YYY.YYY.YYY.YYY   0.0.0.0   255.255.255.0 ... eth4

Ces deux routes étant inutiles, elles sont supprimées par mon script postboot (firewall, route, etc..)

Donc, si comme moi, vous êtes bloqué, c’est tout simple :

# ip route add GATEWAY dev eth4 table 1
# ip route add default via GATEWAY dev eth4 table 1
# ip route del GATEWAY dev eth4 table 1

Avant d’ajouter la route, on ajoute l’host, et on peut le supprimer ensuite.

 

II – Depuis le routeur lui même

Un premier test intéressant est de pinguer depuis l’extérieur le routeur, mais sur son IP secondaire.

Côté routeur :

# tcpdump icmp -i eth4

nous montre bien les requests.

Et les replys, on les voit sur

# tcpdump icmp -i eth0

Donc, il faut déjà faire en sorte que le routeur lui même, quand il sort avec l’IPFO, utilise bien le bon lien.

On a vu avant que c’est ip rule qui dicte l’utilisation de la table main :

# ip rule

0:     from all lookup local
32766: from all lookup main
32767: from all lookup default

Les règles sont suivies dans l’ordre.

Donc, si avant 32766 on indique que ce qui vient de YYY.YYY.YYY.YYY passe par la table 1, ça devrait être bon :

# ip rule add priority 1000 from YYY.YYY.YYY.YYY to 0.0.0.0/0 table 1

Pour tester, pinguer votre routeur depuis l’extérieur et regardez d’où partent les réponses…

Par contre, cette règle est un poil trop restrictive.

En effet, si vous tentez de pinguer YYY.YYY.YYY.YYY depuis une VM interne, la nouvelle table est utilisée et elle ne contient rien pour nos réseaux.

On pourrait la peupler, mais le plus simple est de faire une nouvelle règle :

# ip rule add priority 999 from YYY.YYY.YYY.YYY to 10.0.0.0/8 table main

Règle dont la priorité est plus faible (donc exécutée avant) qui spécifie que depuis l’IP externe vers les réseaux internes, on prend la table main.

Notre ip rule donne alors :

# ip rule

0: from all lookup local
999: from YYY.YYY.YYY.YYY to 10.0.0.0/8 lookup main
1000: from  YYY.YYY.YYY.YYY lookup rt1
32766: from all lookup main
32767: from all lookup default

Simple non ?

 

III – Le serveur Mail

Pour lui, rien de compliqué, la logique est la même :

# ip rule add priority 500 from 10.10.1.100 to 0.0.0.0/0 table 1

Mais de la même façon que pour le routeur, il faut aussi ceci avant :

# ip rule add priority 499 from 10.10.1.100 to 10.0.0/8 table main

Ceci afin que si la machine mail doivent s’adresser à une autre VM en passant par le routeur, elle prenne la table main.

Bon, en théorie, celle ci, je n’en ai plus besoin vu que j’ai revu mon routage avec mes VPNS (sisi, promis, l’article VPN arrive bientot ! )

Au final on a ceci :

#ip rule

0: from all lookup local
499: from 10.10.1.100 to 10.0.0.0/8 lookup main
500: from 10.10.1.100 lookup rt1
999: from YYY.YYY.YYY.YYY to 10.0.0.0/8 lookup main
1000: from  YYY.YYY.YYY.YYY lookup rt1
32766: from all lookup main
32767: from all lookup default

Et voila !

Mais on peut être encore plus pervers et imaginer router en fonction du port de destination !


Envie de me soutenir et de me payer un café  ? C’est sur la page Don !

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *