Port Knocking  & Netfilter 

Avoir un serveur à la maison avec un routeur  Linux c'est très bien, le problème est que si nous voulons avoir accès depuis l'extérieure à notre machine et bien il faut ouvrir des Ports sur ce routeur, comme par exemple le port 80 pour un serveur Web ou 22 pour un serveur SSH.
Et là les problèmes arrivent, on va voir pourquoi dans la suite de ce tuto.

Netfilter: Un composant du kernel linux à partir de la version 2.4, on ne peut pas dialoguer directement avec Netfilter, les développeurs ont donc mis au point la commande iptables, qui est strictement lié au code de Netfilter. Pour plus d'Info.

* Le tuto qui suit sur Port Knocking & Netfilter et pour une approche des principes, est pour éveiller votre curiosités, pour allez plus loin dans les détailles g00gle et votre ami.

Je suis parti d'un article sur " Se protéger contre les attaques à l'aide de Netfilter " de Hakin9 Numero 22, pour comprendre Netfilter.

J'ai eu besoin de 3 machines, toute sous Linux.

Machine 1: Serveur ssh sur le port 22
Machine 2: Client du serveur SSH
Machine 3: Pirate !!


NETFILTER

Par  defaut NetFilter est fourni avec trois trables principales : Filter, Nat, Mangle.

    - Filter: Pour le filtrage des paquets
    - Nat  : Pour la traduction d'adresses et de ports
    - Mangle : Pour la transformation des options des paquets Qos

Par defaut sur une machine Linux, ou netfilter est installé, tout est autoriser par défaut, pour le voir en mode console en root : iptables -L -n -v sur Machine 1

Chain INPUT (policy ACCEPT 129 packets, 13250 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 49 packets, 5882 bytes)
 pkts bytes target     prot opt in     out     source               destination

La politique par default sur les trois chaines ( INPUT, FORWARD, OUTPUT ) est ACCEPT, comme on le voit sur le tableau du dessus

on va travailler sur la table Filter de Netfilter.

Ci joint le schéma de principe de la table filter de netfilter:
.




Sur cette même machine pour voir les ports ouvert on tape : nmap -sS localhost

nmap -sS localhost

Starting Nmap 4.20 ( http://insecure.org ) at 2007-03-26 15:20 GMT
Interesting ports on localhost:
Not shown: 1695 closed ports
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
MAC Address: 00:00:00:00:00:00 (MSI)

Nmap finished: 1 IP address (1 host up) scanned in 1.341 seconds

Donc sur la machine 1, les ports 22 ( SSH ) & 80 ( WWW) sont ouverts.

Donc on va écrire un petit bout de script, pour avoir une protection, on l'appelle: firwall.sh

#firwall.sh
#!/bin/sh
#Effacement de toute les régles de netfilter
iptables -F  
iptables -X  
#politique par default, tout est interdit.
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
#autorisation loopback
iptables -A INPUT -i io -j ACCEPT
iptables -A OUTPUT -o io -j ACCEPT
#autorisation ICMP pour le ping
iptables -A INPUT -p icmp -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT
#autorisation DNS
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A INPUT -p udp --sport 53 -j ACCEPT
#autorisation pour surfer sur le WEB
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --sport 80 -j ACCEPT

On le lance en Root : sh firwall.sh
Pour voir que bien pris en compte : iptables -L -n -v

Chain INPUT (policy DROP 41 packets, 5161 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  io     *       0.0.0.0/0            0.0.0.0/0
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0
    2   242 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0           udp spt:53
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp spt:80
     
Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  *      io      0.0.0.0/0            0.0.0.0/0
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0
    2   165 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0           udp dpt:53
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:80

Là nous avons protegés notre machine 1, que pour faire de la navigation par le port 80. Le port 53 est pour l'interogation et la réponse du serveur DNS.
Dans Policy DROP se sont les paquets qui sont mis à la poubelle directement.


Et coté pirate machine 3 : avec un lancement d'un scan de notre machine 1 avec un : nmap -sS xxx.xxx.xxx.xxx
Starting Nmap 4.20 ( http://insecure.org ) at 2007-03-27 11:22 GMT
All 1697 scanned ports on xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx) are filtered
MAC Address: 00:00:00:00:00:00 (MSI)

Nmap finished: 1 IP address (1 host up) scanned in 36.455 seconds
Donc à priori pas de port ouvert vu par notre pirate, mais il sait lire la doc de la commande nmap...

voilà maintenant une nouvelle commande: nmap -g 80 -sS xxx.xxx.xxx.xxx

nmap -g 80 -sS xxx.xxx.xxx.xxx                                            
Starting Nmap 4.20 ( http://insecure.org ) at 2007-03-27 11:28 GMT
Interesting ports on xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx):
Not shown: 1695 closed ports
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
MAC Address: 00:00:00:00:00:00 (MSI)

Nmap finished: 1 IP address (1 host up) scanned in 0.286 seconds

BINGO pour notre pirate il voit le port 22 ( SSH ) alors qu'il n'y a pas d'autorisation pour passer dans notre config du firewall ( script ), si nous avions un serveur samba, il semble y avoir des solutions pour justement pourvoir monter des partages à traver le port 80.

Alors il faut trouver un autre moyen de configurer notre netfilter, et la solution est le suivi de connexion avec le module ip_conntrack du Kernel:

Ip_conntrack est capable de déterminer 4 types d'états différents d'une connexion : NEW, ESTABLISHED, RELATED, INVALID:

NEW : pour une nouvelle connexion
ESTABLISHED : la suite de NEW, pour une connexion établie entre deux points.
RELATED : Comme pour le mode actif de FTP, le serveur qui initialise la communication ( pas le même port que la demande )
INVALID : Paquet réseau qui ne satisfait pas les régles réseaux.

Voilà un schéma.




On va donc refaire un script qui prend en compte le suivi de connexion, avec ip_conntrack.

#!/bin/sh
#modules suivi de connexion
modprobe ip_conntrack
#Sup de la configuration de netfilter
iptables -F
iptables -X
#politique par default, tout est interdit.
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
#autorisation loopback
iptables -A INPUT -i io -j ACCEPT
iptables -A OUTPUT -o io -j ACCEPT
#autorisation ICMP
iptables -A INPUT -p icmp -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT
#autorisation Sortantes TCP LAN->WAN
iptables -A OUTPUT -p tcp -m multiport --dports 80 -m state --state NEW,ESTABLISHED -j ACCEPT
#autorisation Reponses TCP WAN->LAN
iptables -A INPUT -p tcp -m multiport --sports 80 -m state --state ESTABLISHED -j ACCEPT
#autorisation Sortantes UDP LAN->WAN
iptables -A OUTPUT -p udp -m multiport --dports 53 -m state --state NEW,ESTABLISHED -j ACCEPT
#autorisation Reponses UDP WAN->LAN
iptables -A INPUT -p udp -m multiport --sports 53 -m state --state ESTABLISHED -j ACCEPT

en rouge le chargement du module ip_conntrack, dans le nouveau script
lsmod | grep ip pour voir ci le module est bien monter

une fois enregisté,  on lance notre script, ensuite un petit : iptables -L -n -v

Chain INPUT (policy DROP 37 packets, 7390 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  io     *       0.0.0.0/0            0.0.0.0/0
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           state ESTABLISHED
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           multiport sports 80 state ESTABLISHED
    2   242 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0           multiport sports 53 state ESTABLISHED
  
Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy DROP 8 packets, 836 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  *      io      0.0.0.0/0            0.0.0.0/0
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           multiport dports 80 state NEW,ESTABLISHED
    2   165 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0           multiport dports 53 state NEW,ESTABLISHED


J'espère que touy le monde avait bien compris que la chaine :
         INPUT     : Les connexions entrante dans notre Netfilter
         OUTPUT : Les connexions sortantes dans notre Netfilter
     FORWARD : le FORWARD de ports.
              DROP : Poubelle

Revenons à notre script.

#autorisation Sortantes TCP LAN->WAN
iptables -A OUTPUT -p tcp -m multiport --dports 80 -m state --state NEW,ESTABLISHED -j ACCEPT

On autorise ( ACCEPT ) le port 80 pour les nouvelles connexions, pour d'autres ports à ouvrir, on ajoute simplement avec une virgule comme par exemple le 443 ( 80,443 )

#autorisation Reponses TCP WAN->LAN

iptables -A INPUT -p tcp -m multiport --sports 80 -m state --state ESTABLISHED -j ACCEPT

On autorise ( ACCEPT ) les réponses du port 80 que pour les connexions déja établies, donc qui fait suite à une NEW,ESTABLISHED.

Le même principe pour le protocole UDP.

Pour cette régle :

#autorisation ICMP
iptables -A INPUT -p icmp -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT

Je peut pinger de le machine, mais on peut pas me pinger.



Coté pirate "machine 3" pour vérifier avec la même commande : nmap -g 80 -sS xxx.xxx.xxx.xxx

nmap -g 80 -sS xxx.xxx.xxx.xxx                                            
Starting Nmap 4.20 ( http://insecure.org ) at 2007-04-12 10:24 GMT
All 1697 scanned ports on  xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx): are filtered
MAC Address: 00:00:00:00:00:00 (MSI)

Nmap finished: 1 IP address (1 host up) scanned in 36.452 seconds

Donc coté pirate il peut en jugé qu'il y a bien une machine de l'autre coté "are filtered", qui est protegé par un Firewall. Mais il ne voit pas les eventuelles ports ouverts.

Voilà mes bases pour la construction d'un fichier script pour Netfilter, j'éspère que cela vous à permis de voir & peut être comprendre le principe.


Port Knocking ( frappement ou toc toc sur les ports TCP )

Le port knock consiste à autoriser l'accès à un port TCP, pas l'envoi d'une séquence de paquet UDP ou TCP, le deamon Knock regarde les tentatives sur les ports de notre machine et si une séquence est reconnue, alors il va agire directement sur le comportement du firewall ( Netfilter dans notre cas ), avec des régles Iptables à établir, ou toutes autres commandes interne de notre serveur.

Pour l'envoi d'une séquence il faut disposer d'un client qui est disponible sur différente plate forme.
Pour plus d'information sur le produit : http://www.zeroflux.org/cgi-bin/cvstrac.cgi/knock/wiki

pour l'installation du deamon sur notre serveur sous Debian:
apt-get install knockd

Aprés l'installation, deux fichiers de configuration sur notre machine :

dans /etc/default: knockd à modifier

cat knockd
################################################
#
# knockd's default file, for generic sys config
#
################################################

# control if we start knockd at init or not
# 1 = start
# anything else = don't start
START_KNOCKD=1

# command line options
KNOCKD_OPTS="-i eth0"

l'option eth0 qui conrespont à votre carte reseau.

dans /etc:  knockd.conf  c'est le fichier de configuration des séquences et des actions.

[options]
        logfile = /var/log/knockd.log

[openSSH]
        sequence    = 7000,8000,9000
        seq_timeout = 5
        command     = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT && /sbin/iptables -A OUTPUT -m state --state NEW,ESTABLISHED -j ACCEPT
        tcpflags    = syn
[closeSSH]
        sequence    = 9000,8000,7000
        seq_timeout = 5
        command     = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT && /sbin/iptables -D OUTPUT -m state --state NEW,ESTABLISHED -j ACCEPT
        tcpflags    = syn

Logfile : Création d'un fichier de log de notre deamon dans
/var/log/knockd.log.

La sequence: le ou les ports ou l'on va faire toc toc dans un ordre bien précise. ici 7000, 8000, 9000 en tcp.

Le nombres de ports et 65535, les ports en dessous de 1023 sont réserver à l'usage du compte Root ( ou administrateur ).
de 1024 à 49151 sont des ports connus et enregistrés et de 49152 à 65535 ce sont des ports dynamiques ou privés.

Seq_timeout : Interval de temps de notre toc toc maxi 
Command : la commande appliquée à IPTABLES pour le passage de la connexion sur le port 22 ( SSH ), avec en variable l'adresse IP du client.
tcpflags : type de flags

Voila fini pour la configuration du deamon.

Lancement du toc toc avec le client windows : c:\knock "IPdelamachine" 7000:tcp 8000:tcp 9000:tcp

maintenant un scan de port pour vérifier que notre machine accepte bien la connexion sur le port 22.

nmap -sS IP -p 22,80

Starting Nmap 4.20 ( http://insecure.org ) at 2007-04-12 11:19 Romance Daylight Time
Interesting ports on xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx):
PORT   STATE    SERVICE
22/tcp open     ssh
80/tcp filtered http
MAC Address: 00:00:00:00:00:00 (MSI)

Nmap finished: 1 IP address (1 host up) scanned in 1.526 seconds

Donc la séquence à bien fonctionné, et coté pirate ???

La même commande mais de la machine 3 :
nmap -sS IP -p 22,80

Starting Nmap 4.20 ( http://insecure.org ) at 2007-04-12 11:24 GMT
Interesting ports on  xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx):
PORT   STATE    SERVICE
22/tcp filtered ssh
80/tcp filtered http
MAC Address: 00:00:00:00:00:00 (MSI)

Nmap finished: 1 IP address (1 host up) scanned in 1.406 seconds


Nous voyons bien que d'une autre machine le port 22 marqué filtered, il n'ait pas vu ouvert d'une autre machine.



L'un des principaux defaut de cette technique c'est qu'ellle est bassé sur l'adresse IP du client qui initie la séquence du toc toc, et elle peut étre usurpé par une autre personne.

Bien refermer le port 22 avec l'autre séquence.


















  INDEX du site