4 votes

nginx use-proxy-protocol avec un cluster Kubernetes

J'ai un cluster Kubernetes avec un équilibreur de charge externe sur un serveur auto-hébergé exécutant NGINX. J'ai essayé d'activer le proxy_protocol afin d'obtenir le real_ip de clients mais les journaux NGINX sont

2020/05/11 14:57:54 [error] 29614#29614: *1325 broken header: "a"5li<c* s       6XoEi{ /0+, 
/5" while reading PROXY protocol, client: 51.178.168.233, server: 0.0.0.0:443

Voici mon fichier de configuration NGINX :

worker_processes 4;
worker_rlimit_nofile 40000;

events {
    worker_connections 8192;
}

stream {

    upstream rancher_servers_http {
        least_conn;
        server <IP_NODE_1>:80 max_fails=3 fail_timeout=5s;
        server <IP_NODE_2>:80 max_fails=3 fail_timeout=5s;
        server <IP_NODE_3>:80 max_fails=3 fail_timeout=5s;
    }
    server {
        listen     80;
        proxy_protocol on;
        proxy_pass rancher_servers_http;
    }

    upstream rancher_servers_https {
        least_conn;
        server <IP_NODE_1>:443 max_fails=3 fail_timeout=5s;
        server <IP_NODE_2>:443 max_fails=3 fail_timeout=5s;
        server <IP_NODE_3>:443 max_fails=3 fail_timeout=5s;
    }

    server {
        listen     443 ssl proxy_protocol;
        ssl_certificate /certs/fullchain.pem;
        ssl_certificate_key /certs/privkey.pem;
        proxy_pass rancher_servers_https;
        proxy_protocol on;
    }
}

Voici mon configmap pour le contrôleur d'entrée :

apiVersion: v1
data:
  compute-full-forwarded-for: "true"
  proxy-body-size: 500M
  proxy-protocol: "true"
  use-forwarded-headers: "true"
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: '{"apiVersion":"v1","data":null,"kind":"ConfigMap","metadata":{"annotations":{},"labels":{"app":"ingress-nginx"},"name":"nginx-configuration","namespace":"ingress-nginx"}}'
  creationTimestamp: "2019-12-09T13:26:59Z"
  labels:
    app: ingress-nginx
  name: nginx-configuration
  namespace: ingress-nginx

Tout fonctionnait bien avant que j'ajoute le proxy_protocol mais maintenant j'ai tous ces broken headers et je ne peux atteindre aucun service derrière les ingresses sans obtenir une connection reset Fehler.

Qu'est-ce qui pourrait clocher dans ma configuration ?

Dois-je utiliser un reverse proxy http au lieu d'un reverse proxy tcp ?

Merci.


Editar :

Je dois aussi dire que je n'ai pas de service de type LoadBalancer dans mon groupe. Devrais-je en avoir un ? Je pense à Metallb mais je ne suis pas sûr de ce que cela signifie. ce qu'il ajoutera à ma configuration car je fais déjà de l'équilibrage de charge sur les nœuds avec nginx.

5voto

Dirbaio Points 213

Nginx vous permet de spécifier si vous voulez utiliser le proxy_protocol dans les requêtes entrantes ou sortantes, et vous confondez les deux.

Pour utiliser proxy_protocol dans entrant vous devez ajouter proxy_protocol au listen une ligne comme celle-ci :

listen     443 ssl proxy_protocol;

Pour utiliser proxy_protocol dans sortant vous devez utiliser l'application autonome proxy_protocol comme ceci :

proxy_protocol on;

Ils sont no la même chose. Dans un équilibreur de charge, entrant Les connexions proviennent des navigateurs, qui ne parlent pas le protocole proxy. Vous voulez le protocole proxy uniquement dans vos requêtes sortantes, vers la nginx-ingress dans votre cluster kubernetes.

Par conséquent, retirez le proxy_protocol de l'argument de la listen et cela devrait fonctionner.

En outre, vous voulez use-forwarded-headers: "false" dans votre configuration de nginx-ingress. Cela permet de contrôler l'utilisation de l'option X-Forwarded-For & co. headers in entrant connexions (du point de vue de la nginx-ingress, c'est à dire sortant de votre équilibreur de charge), et vous utilisez le protocole proxy dans ces derniers au lieu des en-têtes. S'il est activé, vos utilisateurs peuvent être en mesure d'usurper des adresses IP en spécifiant X-Forwarded-For, ce qui peut constituer un problème de sécurité. (seulement si nginx-ingress donne la priorité aux en-têtes sur le protocole proxy, ce dont je ne suis pas sûr)

Une parenthèse : nginx-ingress lui-même équilibre déjà la charge du trafic entre tous les pods. Avec votre architecture, vous exécutez deux "couches" d'équilibreurs de charge, ce qui est probablement inutile. Si vous voulez simplifier les choses, forcez nginx-ingress à s'exécuter sur un seul nœud (avec la commande nodeSelector par exemple) et envoyez simplement tout votre trafic vers ce nœud. Si vous souhaitez conserver l'équilibreur de charge sur une machine dédiée, vous pouvez joindre la quatrième machine au cluster et vous assurer qu'elle n'exécute que nginx-ingress (avec taints et tolérances).

De plus, assurez-vous que vous exécutez nginx-ingress avec hostNetwork : true, sinon vous pouvez avoir encore une fois couche d'équilibrage (kube-proxy, le proxy de service kubernetes)

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X