Le NAT 2/3 – Construire un routeur linux avec iptables

Dans cet article, nous allons voir comment mettre en place un routeur linux. Ce type de routeur peut-être utilisé soit chez soit ou en datacenter quand vous faites de la virtualisation (par exemple, sur un proxmox directement pour donner un accès internet à des VM quand on a qu’une seule IP WAN)

Tous les exemples utiliseront debian 8 (pré-release 3.16.0-4-amd64) et iptables 1.4.21. Il est donc possible que certaines choses varient avec le temps.

Prérequis:

Un serveur debian 8 (physique ou virtuel avec 2 interfaces réseaux)

Configuration réseau utilisé pour cet article:

Ip wan: 1.1.1.1
Réseau local 192.168.1.0/24
Routeur : 192.168.1.254
interface wan: eth0
interface lan: eth1

Que faut-il pour faire un bon routeur ?

– Configurer les interfaces réseaux
– Configurer un serveur de cache DNS (optionnel)
– Configurer un serveur DHCP (optionnel)
– Natter la connexion (création d’un script + démarrage avec le réseau)
– Activer le mode routeur sur le kernel
– Ouvrir un port (optionnel)

 

Configurer les interfaces réseaux

Dans notre exemple, nous allons utiliser une connexion internet avec ip fixe.
Pour commencer, ouvrez le fichier /etc/network/interfaces avec votre éditeur préféré (vim, nano, …)

#Interface WAN
auto eth0 #Démarre l'interface réseau au démarage
iface eth0 inet static #Configuration de l'interface en mode ip fixe
        address 1.1.1.1 #Adresse ip du routeur
        netmask 255.255.255.252 #masque de sous réseau 
        gateway 1.1.1.2 #Paserelle
        dns-nameservers 8.8.8.8 #serveur dns

#Interface lan
auto eth1
iface eth1 inet static
        address 192.168.1.254
        netmask 255.255.255.0

Par défaut, seul eth0 est déclaré et configuré en mode « dhcp ». Il est  donc nécessaire de remplacer les lignes existantes par celles-ci.
Eth0 étant mon ip wan, cette configuration vient directement de mon F.A.I. , dans votre cas, il faut adapter celle-ci à celui-ci directement.
Enfin, il ne faut pas oublier de relancer le service réseau pour appliquer celui-ci.

systemctl restart networking

Normalement, si tout va bien, vous devez avoir un accès internet depuis le routeur. Vous pouvez tester cela via un ping par exemple.

De plus, vous pouvez également tester que l’autre interface fonctionne bien en configurant votre ordinateur dans le même réseau avec par exemple la configuration suivante.
Adresse: 192.168.1.1 Routeur: 192.168.1.254 Dns: 8.8.8.8
Vous devriez pouvoir pinguer 192.168.1.254, mais il n’est pas possible de sortir sur internet pour le moment.

 

Configurer un serveur de cache DNS

Le serveur de cache dns vous permet de faire de la mise en cache sur les résolutions DNS. Cela évite de contacter votre F.A.I. à chaque fois que vous visitez un nom de domaine. Dans notre exemple, nous allons utiliser bind9.

Pour l’installer utiliser la commande suivante.

apt-get install bind9

Maintenant que bind est installé, il va falloir configurer 2 choses pour que celui-ci agisse comme un serveur de cache DNS.

Pour commencer, ouvrez le fichier de configuration  /etc/bind/named.conf.options

1 – Ajout des serveurs dns sur lequel bind transfèrera ses requêtes (ceux de votre F.A.I. ou encore 8.8.8.8 / 8.8.4.4 par exemple).

Pour cela, décomentez les lignes « forwarders » et ajouter vos ip’s comme dans l’exemple ci-dessous.

         forwarders {
                8.8.8.8;
                8.8.4.4;
         };

NB: cette configuration doit se trouver à l’intérieur de la balise options { }; (c’est le cas de l’exemple commenté se trouvant dans le fichier)

2 – Autoriser les clients (ordinateurs du réseau local) à communiquer avec le DNS.

Note: Il est important de ne pas autoriser tout le monde car votre serveur pourrait être utilisé pour réaliser certaines attaques.

En dehors de la balise options  { }; nous allons créer une « ACL » représentant les machines autorisées à utiliser le relais DNS.

acl "localnetwork" {
        127.0.0.1/32;
        192.168.1.0/24;
};

Une fois cela effectué, nous allons autoriser cette « acl » à utiliser notre serveur. Placer cette configuration dans la balise options cette fois.

allow-query { localnetwork; };

Une fois terminé, votre fichier de configuration devrait ressembler à ceci:

acl "localnetwork" {
        127.0.0.1/32;
        192.168.1.0/24;
};

options {
        directory "/var/cache/bind";

        // If there is a firewall between you and nameservers you want
        // to talk to, you may need to fix the firewall to allow multiple
        // ports to talk.  See http://www.kb.cert.org/vuls/id/800113

        // If your ISP provided one or more IP addresses for stable
        // nameservers, you probably want to use them as forwarders.
        // Uncomment the following block, and insert the addresses replacing
        // the all-0's placeholder.

         forwarders {
                8.8.8.8;
                8.8.4.4;
         };

        allow-query { localnetwork; };
        //========================================================================
        // If BIND logs error messages about the root key being expired,
        // you will need to update your keys.  See https://www.isc.org/bind-keys
        //========================================================================
        dnssec-validation auto;

        auth-nxdomain no;    # conform to RFC1035
        listen-on-v6 { any; };
};

Vous pouvez désormais redémarrer bind

systemctl restart bind9

Astuce: vous pouvez vérifier que bind9 fonctionne bien via la commande suivante:

systemctl status bind9

 

Configuration d’un serveur DHCP

Dans cet exemple, nous allons utiliser « isc-dhcp-server » (il existe d’autre serveurs tels que dnsmasq)

apt-get install isc-dhcp-server

Pour commencer, nous allons créer un fichier de configuration vide plutôt que d’utiliser l’originale.

cd /etc/dhcp 
mv dhcpd.conf dhcpd.conf.original
touch dhcpd.conf

Enfin, on édite le fichier dhcpd.conf fraichement créer pour y ajouter la configuration suivante:

option domain-name-servers 192.168.1.254; #Configuration du serveur DNS, c'est l'ip LAN de votre debian routeur.
subnet 192.168.1.0 netmask 255.255.255.0 { #Configuration du réseau local. dans notre cas 192.168.1.0/24
  default-lease-time 86400; #Temps en seconde après le quel le serveur dhcp relache l'ip si elle n'est plus présente sur le réseau
  range 192.168.1.10 192.168.1.100; #Range d'adresse que le dhcp peut allouer au client (compris dans 192.168.1.0/24)
  option routers 192.168.1.254;#Adresse ip du routeur. Identique au serveur dns dans notre cas.
}

Notez qu’il est possible d’utiliser le DHCP pour fixer des ip aux clients. C’est très pratique quand votre machine voyage dans plusieurs réseaux.

Pour cela, ajoutez à la suite de votre configuration

host pc-portable { #Nom de l'hote
  hardware ethernet aa:bb:cc:dd:ee:ff; #Mac adresse de l'hote
  fixed-address 192.168.1.150; #Ip fixe (comprise dans votre réseau) que vous souhaitez donner à votre ip.
}

Nb: vous pouvez donner des ip fixes en dehors de l’option « range » mais celle-ci dois être comprise dans le sous réseau. (dans notre cas 192.168.1.0/24)

Enfin, il vous reste a dire sur quelles interfaces notre serveur DHCP écoutera. Pour cela éditez le fichier /etc/default/isc-dhcp-server

Repérez la ligne INTERFACES= » » et ajouter votre interface réseau LAN. Ce qui donne ceci:

INTERFACES="eth1"

Enfin, plus qu’a redémarrer votre service dhcp via

systemctl restart isc-dhcp-server

Pour tester votre serveur DHCP, connectez un ordinateur sur l’interface eth1 en mode automatique et vous devriez obtenir une adresse ip automatiquement. (c’est le but 🙂 )

Natter la connexion

Pour effectuer le nattage via iptables, nous allons créer un script bash qui sera démarrer au démarrage de l’interface WAN (eth0). Il existe également le paquet iptables-save sur debian qui permet de sauvegarder de manière automatique. Personnellement, j’utiliserai un script maison, car celui-ci est plus clair et surtout facile à commenter.

Ci-dessous, le script utilisé. Dans mon exemple, il sera sauvegardé dans /root/routeur.sh

 

#!/bin/sh
IPT=/sbin/iptables
WANIF=eth0
LANIF=eth1

firewall_start() { #Exécuter lors du routeur.sh start
	
		#==================== INPUT ===================
        #Ces règles s'appliquent aux paquets entrants

        #Tout ce qui sort peut rentrer à nouveau 
        $IPT -A INPUT -i $WANIF -m state --state ESTABLISHED,RELATED -j ACCEPT 
		
		#On ouvre le port 22 depuis le WAN sur notre rotueur pour permettre son management à distance. 
		#Cette étape n'est pas obligatoire et dépend de votre configuration
        $IPT -A INPUT -i $WANIF -p tcp --dport 22 -j ACCEPT 
		
		#On autorise le PING sur l'interface WAN (facultatif)
        $IPT -A INPUT -i $WANIF -p icmp -j ACCEPT
		
		#On laisse passer tout ce qui rentre dans l'interface lan afin de permettre à nos utilisateurs d'utiliser le DHCP et le DNS
        $IPT -A INPUT -i $LANIF -j ACCEPT
		
		#Tout ce qui ne MATCH pas avec les règles précédente > ON jette !
        $IPT -P INPUT DROP
		

		#==================== NAT ===================
        #Ces règles effectuent la réécriture d'adresses du NAT
		
		#Tout ce qui a fini de traverser le routeur (postrouting) et qui sort par le WAN sera NATté
        $IPT -A POSTROUTING -t nat -o $WANIF -j MASQUERADE





		#==================== FORWARD ===================
        #Ces règles s'appliquent au paquets traversant le routeur
		
		#Tout ce qui vient du WAN et sort par le LAN et qui correspond à une réponse est autoriser à passer.
        $IPT -A FORWARD -i $WANIF -m state --state ESTABLISHED,RELATED -j ACCEPT
		
		#Tout ce qui part du LAN est autoriser à traverser le routeur.
        $IPT -A FORWARD -i $LANIF -j ACCEPT
		
		#Tout ce qui ne MATCH pas avec les règles précédente > ON jette !
        $IPT -P FORWARD DROP

		


}

firewall_stop() { #exécuté lors du routeur.sh stop
		
		#Clear des différentes tables d'iptables et remise à zéro de la configuration.
        $IPT -F
        $IPT -t nat -F
        $IPT -P INPUT ACCEPT
        $IPT -P FORWARD ACCEPT
}

firewall_restart() { #exécuté lors du routeur.sh restart
        firewall_stop
        sleep 2
        firewall_start
}

case $1 in 'start' )
firewall_start
;;
'stop' )
firewall_stop
;;
'restart' )
firewall_restart
;;
*)
echo "usage: -bash {start|stop|restart}"
;;
esac

N’oubliez pas de donner les droits d’exécution sur votre script.

chmod ugo+x /root/routeur.sh

Enfin, nous allons lancer celui-ci en même temps que notre interface réseau. Pour cela, ont retourne dans /etc/network/interfaces et on ajoute les lignes suivantes en dessous de l’interface WAN (eth0)

        post-up /root/routeur.sh start
        pre-down /root/routeur.sh stop

Au final, votre fichier devrait ressembler à ceci:

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
        address 1.1.1.1
        netmask 255.255.255.252
        gateway 1.1.1.2
        dns-nameservers 8.8.8.8
        post-up /root/routeur.sh start
        pre-down /root/routeur.sh stop

auto eth1
iface eth1 inet static
        address 192.168.1.254
        netmask 255.255.255.0

 

Activer le mode routeur sur le kernel

Pour activer le mode routeur de manière permanente, il suffit d’éditer le fichier /etc/sysctl.conf

Ensuite, dé commentez la ligne suivante

net.ipv4.ip_forward=1

A ce stade, la configuration sera appliquée de manière automatique au redémarage. Cependant, la configuration n’est pas actif pour le moment.
Vous pouvez activer cela directement avec la commande suivante ou en redémarrant votre machine debian.

 echo "1"> /proc/sys/net/ipv4/ip_forward
 /root/routeur.sh start

Note: a ce stade, vous devriez pouvoir surfer sur le net au travers de votre nouveau routeur !

Ouvrir un port

Pour ouvrir un port, nous allons devoir ajouter une nouvelle règle de NAT dans notre fichier /root/routeur.sh

Ces règles sont à ajouter à la suite de notre section NAT dans le fichier

        #Routage du port 3389
        #On autorise les paquets à traverser vers notre pc local uniquement pour le service.
        #Cette règle est en réalité une règle de FORWARD mais je la met juste à coté de celle de NAT pour faciliter la compréhension.
        $IPT -A FORWARD -i $WANIF -p tcp --dport 3389 -d 192.168.1.150 -j ACCEPT 

        #Tout se qui rentre sur le WAN (input donc) et qui rentre dans le TCP:3389 sera rediriger vers 192.168.1.150:3389 
        $IPT -A PREROUTING -t nat -j DNAT -i $WANIF -p tcp --dport 3389 --to-destination 192.168.1.150:3389 

Nb: le service n’est accessible que depuis l’extérieur (Cette règle ne gère pas le nat loopback qui fera l’objet d’un autre article)

Voila, vous avez désormais un routeur fonctionnel sous debian !

Le NAT 1/3 – Théorie

Internet ne marche pas ! Pourquoi ? (diagnostiquer sa configuration)

Astuces

Si vous souhaitez redémarrer votre script iptables après changement, vous pouvez utiliser la commande suivante

/root/routeur.sh restart

 

 

7 comments

  1. il serait judicieux de dire que les adresses DNS correspondent à celles de google (8.8.x.x) du coup aucun « intérêt ».
    Pour le fond ça a l’air d’être une bonne base à compléter avec d’autres tutos

    1. Salut Adams,
      Le NAT se fait de manière purement logiciel sans Offloading, ton CPU doit probablement saturer.
      As-tu investiguer ce point ? Après c’est la force de routeurs hardware au dela de certaines vitesse. Tu peux décharger du traitement sur des puces dédiés.

      1. Le problème venait des réseau virtuel que j’ai créer avec virsh qui sont limiter a – 3-4 gb/s donc j’ai créer plusieurs réseau virtuel pour contourner le problème.

Laisser un commentaire

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

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.