Filtrage iptables pour tunnel ssh

Bonjour,
j’ai besoin de pouvoir joindre un serveur connecté derrière un routeur 4G.
Pour ce faire, j’ai créé un tunnel ssh avec un autre serveur dont je dispose sur internet, ça fonctionne bien, le soucis arrive quand je veux restreindre l’accès pour des questions de sécurité.
J’ai ouvert le tunnel avec la commande:

autossh -4 -f user@serveur_internet -R 5001:localhost:22 -N

Donc pour me connecter à mon serveur derrière la 4G, je rentre cette commande:

ssh  -J user@serveur_internet -p 5001 user@localhost

Tant que le pare-feu sur serveur_internet est complètement ouvert, pas de soucis.
Ensuite je me dis que je ne vais pas tout laisser ouvert, donc je mets la police INPUT à DROP par défaut, et j’ouvre seulement le port 5001:
Ci-dessous les premières lignes de mon fichier /etc/iptables/rules.v4:

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
-A INPUT  -p tcp -m tcp --dport 5001 -j ACCEPT

Et la ça ne passe plus.
J’ai essayé de voir en mettant les logs sur debug, je vois des lignes comme celle-ci :

ID=13841 DF PROTO=TCP SPT=55338 DPT=22 WINDOW=501 RES=0x00 ACK PSH URGP=0

Je m’attendais à voir DPT=5001 mais pas du tout, donc il y a un truc qui m’échappe.
Quelqu’un peut’il m’aider ?
Merci d’avance

Je me suis aperçu qu’il faut que j’autorise également le port 22, et la c’est bon.
Ce que je ne m’explique pas, c’est qu’un tunnel pour mysql 9306=>3306 par exemple, j’ai seulement le 9306 à ouvrir, idem pour http.

Avant de se connecter à un tunnel SSH; il faut établir une connexion SSH. Et pour établir une connexion SSH, il faut bien autoriser le port SSH, non ?

Ok, mais du coup pourquoi pour http ou sql, il suffit d’ouvrir uniquement les ports ‹ tunelés › ?

Si tu veux qu’on ait une chance de te répondre, tu dois montrer le dispositif complet : tunnels, règles iptables…

Avant de parler technique, je vais parler relationnel.
Dans les intervenants ‹ aidants › des forums, on trouve 2 types de profils

  • ceux qui sont la réellement pour aider, avec un vrai sens de l’écoute
  • et ceux qui sont la pour se mettre en avant, répondants aux demandes d’aides avec condescendance - suffisance - etc …
    Bref, pour ceux-la passez votre chemin.
    Je reviens au sujet.
    Après quelques tests, j’ai remarqué 2 fonctionnement differents pour les tunnels ssh:

Quand je créé un tunnel avec la commande « autossh -4 -f user@serveur_internet -R 5001:localhost:22 -N » , puis que j’emprunte ce tunnel avec « ssh -J user@serveur_internet -p 5001 user@localhost » , je m’apperçois qu’il n’y a pas à ouvrir le port 5001 mais le 22 sur le serveur tunnel, donc ssh se connecte au port 22 et ajoute à se demande de connexion qu’il evut emprunter le tunnel 5001

Alors que qand je créé un tunnel avec la commande « autossh -4 -f user@serveur_internet -R 9306:localhost:3306 -N », puis que j’emprunte ce tunnel avec la commande « mysql -h serveur_internet -u user -ppassword -P 9306 », je peux laisser le port 3306 fermé, il faut par contre que le port 9306 soit ouvert, c’est donc un fonctionnement différent.

D’une façon ou d’une autre, si. C’est peut-être déjà autorisé par une autre règle sur localhost (127.0.0.1). Mais si tu ne veux pas montrer le jeu de règles complet, on ne peut pas vérifier pour toi.

Normal, ce port n’est pas en écoute sur serveur_internet.

Normal, il est en écoute sur serveur_internet. Et cette fois la connexion ne sera pas autorisée par une règle localhost, l’accès se faisant sur une adresse IP publique de serveur_internet.

A mon avis c’est un peu plus nuancé, mais je ne suis pas ici pour débattre de cela.

Non, vraiment pas:
je viens de tester avec un fichier de regles volontairement très restreint:
contenu de /etc/iptables/rules.v4:

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i lo -j ACCEPT
COMMIT

puis
netfilter-persistent reload (j’uitilise iptables-persistent)

vérification avec iptables -L:

Chain INPUT (policy DROP)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh
ACCEPT     all  --  anywhere             anywhere            

Chain FORWARD (policy DROP)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination 

Donc je n’ai bien que le port 22 d’ouvert.
ensuite

ssh -J user@serveur_internet -p 5001 user@localhost

et pas soucis, le tunnel fonctionne.

Voilà:

Ce n’était pas sur localhost mais l’interface de loopback (ce qui est encore plus large). J’y étais presque.

Non, tu as tout ouvert sur l’interface de loopback.

Ok, on donc du coup bien un fonctionnement spécifique.
=> pour mysql, (ou http ou autres), il faut laisser le port ‹ tunnelé › ouvert en entrée et c’est tout.
=> pour ssh il faut laisser le port dédié (en prinicpe 22) ouvert en entrée, et le port ‹ tunnelé › ouvert en loopback.

La différence vient seulement de la façon dont tu te connectes depuis le poste client.
Pour mysql ou autres, tu te connectes directement au port tunnelé de serveur_internet.
Pour ssh, tu te connectes indirectement au port tunnelé de localhost par l’intermédiaire de serveur_internet (option -J). Il y a donc un second tunnel entre le client et serveur_internet.
Tu aurais le même fonctionnement que pour mysql si tu te connectais directement au port tunnelé de serveur_internet depuis le client avec

ssh  -p 5001 user@serveur_internet

Réciproquement, pour mysql tu aurais le même fonctionnement que pour ssh si tu établissais un tunnel entre le client et serveur_internet et te connectais au port tunnelé local.