Iptables bloque mon reserve proxy Nginx

Le problème exposé dans ce sujet a été résolu.

Bonjour à tous.

J’ai besoin d’une petite aide SVP.

Je suis en train de configurer un VPS pour pouvoir faire tourner un Websercice qui a été développé en Node JS. Et je souhaite faire ceci avec Nginx configuré en reverse proxy. J’ai réussi à configuré ceci, mais quand j’installe Iptables, ça ne fonctionne plus vraiment.

Ce n’est que la 2è fois que je conf Nginx en reverse proxy, et c’est surtout la 1ère fois que je veux le faire cohabiter avec Iptables.

Les technos : iptables-persistent / Nginx 1.18 / Node JS 14

Je fais des curl pour tester. Et quand Iptables est allumé, au bout du 3ème curl, ça se met à ramer et Nginx me retourne une erreur (voir le log de l’erreur plus bas)… Et quand je désactive Iptables, tout fonctionne nickel.

SVP, Y a t-il une règle Iptables particulière à mettre ? Ou une conf Nginx ou Node JS à metttre ?

Voici mes configurations actuelles :

Voici mon Vhost (qui fonctionne si Iptables est désactivé) :

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name exemple.fr;

    #### SSL
    ssl_certificate /etc/letsencrypt/live/exemple.fr/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/exemple.fr/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/exemple.fr/fullchain.pem;
    include includes/ssl.conf;

    location / {
        proxy_pass http://localhost:3000/;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
    }
}

Voici ma conf de iptables (fichier "/etc/iptables/rules.v4") :

### Réinitialiser les règles
*filter

### Restrictions
# Bloquer toutes les connexions entrentes
:INPUT DROP [0:0]
# Bloquer toutes les connexions qui sont redirigées
:FORWARD DROP [0:0]
# Bloquer toutes les connexions sortantes
:OUTPUT DROP [0:0]

### Autorise les connexions déjà établies
# On va essayer d écouter le status, et pour les éléments qui ont le status RELATED ou ESTABLISHED on accepte.
# Nous indiquons avec les paramètres "-m" et "--ctstate" de ne pas fermer les connexions qui sont déjà établies.
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

### Autoriser le LoopBack (localhost)
# Autoriser les éléments à communiquer les uns avec les autres au sein de notre serveur
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT

### Autoriser le ping (requêtes ICMP)
# Autoriser toutes les requetes ping
-A INPUT -p icmp -j ACCEPT
-A OUTPUT -p icmp -j ACCEPT

### SSH
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 22 -j ACCEPT

### DNS (permet entres autre les téléchargements de paquets debian)
-A INPUT -p tcp --dport 53 -j ACCEPT
-A INPUT -p udp --dport 53 -j ACCEPT
-A OUTPUT -p tcp --dport 53 -j ACCEPT
-A OUTPUT -p udp --dport 53 -j ACCEPT

### HTTP + HTTPS
-A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
-A OUTPUT -p tcp -m multiport --dports 80,443 -j ACCEPT

### Mysql
#-A INPUT -p tcp -m tcp --dport 3306 -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 3306 -j ACCEPT

### NTP (horloge du serveur)
-A OUTPUT -p udp --dport 123 -j ACCEPT

### Supprimez les paquets non conformes, tels que les en-têtes mal formés, etc.
-A INPUT -m conntrack --ctstate INVALID -j DROP

### Pour Webservice (normalement pas besoin, car ces ports sont appelés uniquement en localhost)
-A INPUT -p tcp -m multiport --dports 3000,3001 -j ACCEPT
-A OUTPUT -p tcp -m multiport --dports 3000,3001 -j ACCEPT

COMMIT

Voici l’erreur nginx (dans le fichier "/var/log/nginx/error.log") que ça me provoque (quand Iptables est activé) :

2020/10/05 17:25:13 [warn] 485#485: *1 upstream server temporarily disabled while connecting to upstream, client: IP, server: EXEMPLE.fr, request: "POST /login HTTP/2.0", upstream: "http://[::1]:3000/login", host: "EXEMPLE.fr"
2020/10/05 17:28:27 [error] 461#461: *1 connect() failed (111: Connection refused) while connecting to upstream, client: IP, server: EXEMPLE.fr, request: "POST /login HTTP/2.0", upstream: "http://[::1]:3000/login", host: "EXEMPLE.fr"

Merci d’avance.

+0 -0

Bonjour,

Tu as besoin d’un 'upgrade' sur ton reverse proxy ?

Je testerai deux choses :

  • Commenter les lignes 18 et 19 de ta config NGINX.
  • Commenter la ligne 50 de ta config Iptables.

A moins que j’ai loupé quelque chose, ta configuration me semble correcte. En tout cas pour une config brute … c’est vachement pratique Docker ! :p

Sinon petite astuce, ajoute cette entrée dans ta config : proxy_set_header X-Real-Ip $remote_addr; ça permet de transmettre l’IP de l’utilisateur à ton webservice.

Bonjour,

Tu as besoin d’un 'upgrade' sur ton reverse proxy ?

Je testerai deux choses :

  • Commenter les lignes 18 et 19 de ta config NGINX.
  • Commenter la ligne 50 de ta config Iptables.

A moins que j’ai loupé quelque chose, ta configuration me semble correcte. En tout cas pour une config brute … c’est vachement pratique Docker ! :p

Sinon petite astuce, ajoute cette entrée dans ta config : proxy_set_header X-Real-Ip $remote_addr; ça permet de transmettre l’IP de l’utilisateur à ton webservice.

Yarflam

Ok merci pour ta réponse.

J’y ai fais, ça n’a rien changé.

Je t’invites à ajouter les lignes suivantes dans ta conf iptables :

-A INPUT -j LOG --log-prefix "[iptables-in] "
-A OUTPUT -j LOG --log-prefix "[iptables-out] "

Si tu utilises SystemD tu pourras voir avec journalctl -f -k, entre autres, ce qu’iptables bloque. Ça sera plus pratique pour débugger.

iptables -L -n -v permet aussi de voir quelles règles sont appliquées, cependant là ce sera sûrement directement sur la policy.

Notons également que Nginx et ton service semblent communiquer en IPv6 (::1), quelle est ta conf ip6tables ?

+0 -0

Je t’invites à ajouter les lignes suivantes dans ta conf iptables :

-A INPUT -j LOG --log-prefix "[iptables-in] "
-A OUTPUT -j LOG --log-prefix "[iptables-out] "

Si tu utilises SystemD tu pourras voir avec journalctl -f -k, entre autres, ce qu’iptables bloque. Ça sera plus pratique pour débugger.

iptables -L -n -v permet aussi de voir quelles règles sont appliquées, cependant là ce sera sûrement directement sur la policy.

Notons également que Nginx et ton service semblent communiquer en IPv6 (::1), quelle est ta conf ip6tables ?

Breizh

Comment tu sais qu’ils essayent de communiquer entre eux avec l’IPv6 ? EDIT : je pense que tu as du le voir dans mes logs de nginx. Je vais voir ça, et je re. Merci.

Voici les rules pour l’IPv6 :

# Generated by xtables-save v1.8.2 on Fri Sep 11 09:45:08 2020
# Generated by ip6tables-save v1.6.0 on Fri Aug 16 22:26:04 2019
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT
# Completed on Fri Sep 11 09:45:08 2020
+0 -0

comment tu sais qu’ils essayent de communiquer entre eux avec l’IPv6 ?

upstream: "http://[::1]:3000/login", host: "EXEMPLE.fr"

::1 c’est le localhost IPv6.

Voici les rules pour l’IPv6 :

# Generated by xtables-save v1.8.2 on Fri Sep 11 09:45:08 2020
# Generated by ip6tables-save v1.6.0 on Fri Aug 16 22:26:04 2019
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT
# Completed on Fri Sep 11 09:45:08 2020

stephweb

Du coup tu bloques tout IPv6, ce qui expliquerait le problème. Autorise au moins localhost ou utilise explicitement 127.0.0.1.

+0 -0

comment tu sais qu’ils essayent de communiquer entre eux avec l’IPv6 ?

upstream: "http://[::1]:3000/login", host: "EXEMPLE.fr"

::1 c’est le localhost IPv6.

Voici les rules pour l’IPv6 :

# Generated by xtables-save v1.8.2 on Fri Sep 11 09:45:08 2020
# Generated by ip6tables-save v1.6.0 on Fri Aug 16 22:26:04 2019
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT
# Completed on Fri Sep 11 09:45:08 2020

stephweb

Du coup tu bloques tout IPv6, ce qui expliquerait le problème. Autorise au moins localhost ou utilise explicitement 127.0.0.1.

Breizh

1000 mercis !

ou utilise explicitement 127.0.0.1

Du coup dans mon Vhost j’ai mis : proxy_pass http://127.0.0.1:3000/; Et effectivement maintenant ça marche nickel.

Comment ça se fait qu’avec 127.0.0.1 ça marche mais pas avec localhost ? (je n’ai pas encore tout compris). EDIT : imagine car c’est que localhost est un alias vers 127.0.0.1, et qu’en interne ça utilise IPv6 (je ne sais pas comment 'ailleurs ?).

encore merci.

+1 -0

Parce que l’IPv6 étant l’avenir (troll inside, quoique), il est utilisé en premier. Du coup localhost est en priorité résolu en ::1, et non 127.0.0.1. Ceci dit ça doit dépendre de /etc/hosts, et donc sans doute de ta distribution (par défaut du moins), aussi.

Du coup ::1 étant de l’IPv6 et vu que tu bloques tout en IPv6, ça coince. Par contre 127.0.0.1 est explicitement de l’IPv4 où tu autorise bien lo, donc ça passe.

+0 -0

Parce que l’IPv6 étant l’avenir (troll inside, quoique), il est utilisé en premier. Du coup localhost est en priorité résolu en ::1, et non 127.0.0.1. Ceci dit ça doit dépendre de /etc/hosts, et donc sans doute de ta distribution (par défaut du moins), aussi.

Du coup ::1 étant de l’IPv6 et vu que tu bloques tout en IPv6, ça coince. Par contre 127.0.0.1 est explicitement de l’IPv4 où tu autorise bien lo et du coup ça passe.

Breizh

Merci à toi ! ça m’a permis d’apprendre un truc intéressant ! (et ça m’a aussi sauvé ma soirée). 1000 mercis !

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte