Aller au contenu
For the complete DHIS2 documentation index, see llms.txt.

Reverse Proxy

Configuration du proxy inverse

Un proxy inverse est un serveur proxy qui agit pour le compte d'un autre serveur. L'utilisation d'un proxy inverse en combinaison avec un conteneur de servlets n'est pas obligatoire mais présente de nombreux avantages :

  • Les requêtes peuvent être mises en correspondance et transmises à plusieurs conteneurs de servlets. Cela rend le système plus flexible et facilite l'exécution de plusieurs instances DHIS2 sur un même serveur. Cela permet également de modifier la configuration du serveur interne sans affecter les clients.

  • L'application DHIS2 peut être exécutée dans un mode autre que super-utilisateur sur un port autre que 80, ce qui réduit la vulnérabilité face au piratage de sessions.

  • Le proxy inverse peut agir comme un serveur SSL unique et être configuré pour inspecter les demandes de contenu malveillant, enregistrer les demandes et les réponses et fournir des messages d'erreur non sensibles, ce qui va améliorer la sécurité.

Configuration de base de Nginx

Nous vous recommandons d'utiliser nginx comme proxy inverse en raison de sa faible empreinte mémoire et sa facilité d'utilisation. Pour l'installer, appelez la commande suivante :

sudo apt-get install -y nginx

nginx peut maintenant être lancé, rechargé et arrêté avec les commandes suivantes :

sudo /etc/init.d/nginx start
sudo /etc/init.d/nginx reload
sudo /etc/init.d/nginx stop

Maintenant que nous avons installé nginx, nous allons continuer la configuration normale du proxy des requêtes vers notre instance Tomcat, qui, nous le supposons, s'exécute avec l'adresse http://localhost:8080. Pour configurer nginx, vous pouvez ouvrir le fichier de configuration en appelant :

sudo nano /etc/nginx/nginx.conf

La configuration de nginx se fait autour d'une hiérarchie de blocs représentant le http, le serveur et l'emplacement, où chaque bloc hérite des paramètres des blocs parents. L'extrait suivant va configurer nginx pour qu'il passe (redirige) les requêtes du port 80 (qui est le port sur lequel nginx écoute par défaut) vers notre instance Tomcat. Ajoutez la configuration suivante dans le fichier nginx.conf :

http {
  gzip on; # Enables compression, incl Web API content-types
  gzip_types
    "application/json;charset=utf-8" application/json
    "application/javascript;charset=utf-8" application/javascript text/javascript
    "application/xml;charset=utf-8" application/xml text/xml
    "text/css;charset=utf-8" text/css
    "text/plain;charset=utf-8" text/plain;

  server {
    listen               80;
    client_max_body_size 10M;

    # Proxy pass to servlet container

    location / {
      proxy_pass                http://localhost:8080/;
      proxy_redirect            off;
      proxy_set_header          Host               $host;
      proxy_set_header          X-Real-IP          $remote_addr;
      proxy_set_header          X-Forwarded-For    $proxy_add_x_forwarded_for;
      proxy_set_header          X-Forwarded-Proto  http;
      proxy_buffer_size         128k;
      proxy_buffers             8 128k;
      proxy_busy_buffers_size   256k;
      proxy_cookie_path         ~*^/(.*) "/$1; SameSite=Lax";
    }
  }
}

Vous pouvez désormais accéder à votre instance DHIS2 à l'adresse http://localhost. Etant donné que le proxy inverse a été installé, nous pouvons améliorer la sécurité en configurant Tomcat pour qu'il n'écoute que les connexions locales. Dans /conf/server.xml, vous pouvez ajouter un attribut address avec la valeur localhost à l'élément Connector pour HTTP 1.1 comme suit :

<Connector address="localhost" protocol="HTTP/1.1" />

Activation de SSL avec nginx

Afin d'améliorer la sécurité, il est recommandé de configurer le serveur qui exécute DHIS2 de manière à ce qu'il communique avec les clients via une connexion cryptée et de s'identifier auprès des clients à l'aide d'un certificat de confiance. Ceci peut être réalisé via SSL qui est un protocole de communication cryptographique fonctionnant au-dessus de TCP/IP. Tout d’abord, installez la bibliothèque openssl requise :

sudo apt-get install -y openssl

Pour configurer nginx de manière à ce qu'il utilise SSL, vous aurez besoin d'un certificat SSL approprié provenant d'un fournisseur SSL. Le coût d'un certificat varie en fonction de la puissance du cryptage. Un certificat abordable de [Rapid SSL Online] (http://www.rapidsslonline.com) devrait répondre à la plupart des besoins. Pour générer le CSR (demande de signature de certificat), vous pouvez appeler la commande ci-dessous. À l'invite du Nom commun, entrez le nom du domaine qualifié pour le site que vous sécurisez.

openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr

Après avoir reçu vos fichiers de certificat (.pem ou .crt), vous devez les placer avec le fichier server.key généré, dans un emplacement accessible par nginx. Le répertoire où se trouve votre fichier nginx.conf peut servir d'emplacement à cet effet.

Vous trouverez ci-dessous un bloc serveur nginx où les fichiers de certificats sont nommés server.crt et server.key. Étant donné que les connexions SSL se font généralement sur le port 443 (HTTPS), nous transmettons les requêtes sur ce port (443) à l'instance DHIS2 qui s'exécute à l'adresse http://localhost:8080. Le premier bloc serveur réécrira toutes les requêtes connectées au port 80 et forcera l'utilisation de HTTPS/SSL. Ceci est également nécessaire car DHIS2 utilise beaucoup de redirections en interne, lesquelles doivent être transmises pour pouvoir utiliser HTTPS. N'oubliez pas de remplacer \<server-ip> par l'IP de votre serveur. Ces blocs doivent remplacer celui de la section précédente.

http {
  gzip on; # Enables compression, incl Web API content-types
  gzip_types
    "application/json;charset=utf-8" application/json
    "application/javascript;charset=utf-8" application/javascript text/javascript
    "application/xml;charset=utf-8" application/xml text/xml
    "text/css;charset=utf-8" text/css
    "text/plain;charset=utf-8" text/plain;

  # HTTP server - rewrite to force use of SSL

  server {
    listen     80;
    rewrite    ^ https://<server-url>$request_uri? permanent;
  }

  # HTTPS server

  server {
    listen               443 ssl;
    client_max_body_size 10M;

    ssl                  on;
    ssl_certificate      server.crt;
    ssl_certificate_key  server.key;

    ssl_session_cache    shared:SSL:20m;
    ssl_session_timeout  10m;

    ssl_protocols              TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers                RC4:HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

    # Proxy pass to servlet container

    location / {
      proxy_pass                http://localhost:8080/;
      proxy_redirect            off;
      proxy_set_header          Host               $host;
      proxy_set_header          X-Real-IP          $remote_addr;
      proxy_set_header          X-Forwarded-For    $proxy_add_x_forwarded_for;
      proxy_set_header          X-Forwarded-Proto  https;
      proxy_buffer_size         128k;
      proxy_buffers             8 128k;
      proxy_busy_buffers_size   256k;
      proxy_cookie_path         ~*^/(.*) "/$1; SameSite=Lax";
    }
  }
}

Notez la dernière valeur de l'en-tête https qui est nécessaire pour informer le conteneur de servlets que la requête arrive par HTTPS. Pour que Tomcat produise correctement les en-têtes d'URL d'Emplacement en utilisant HTTPS, vous devez également ajouter deux autres paramètres au Connector dans le fichier server.xml de Tomcat :

<Connector scheme="https" proxyPort="443" />

Activation de la mise en cache avec nginx

Les demandes de rapports, de graphiques, de cartes et d'autres ressources liées à l'analyse mettent souvent un certain temps avant de recevoir des réponses et peuvent utiliser une grande partie des ressources du serveur. Afin d'améliorer les temps de réponse, de réduire la charge sur le serveur et d'éviter d'éventuels temps d'arrêt, nous pouvons introduire un proxy de cache dans notre configuration de serveur. Le contenu mis en cache sera stocké dans le répertoire /var/cache/nginx, et jusqu'à 250 Mo de stockage y seront alloués. Nginx créera ce répertoire automatiquement.

http {
  ..
  proxy_cache_path  /var/cache/nginx  levels=1:2  keys_zone=dhis:250m  inactive=1d;


  server {
    ..

    # Proxy pass to servlet container and potentially cache response

    location / {
      proxy_pass                http://localhost:8080/;
      proxy_redirect            off;
      proxy_set_header          Host               $host;
      proxy_set_header          X-Real-IP          $remote_addr;
      proxy_set_header          X-Forwarded-For    $proxy_add_x_forwarded_for;
      proxy_set_header          X-Forwarded-Proto  https;
      proxy_buffer_size         128k;
      proxy_buffers             8 128k;
      proxy_busy_buffers_size   256k;
      proxy_cookie_path         ~*^/(.*) "/$1; SameSite=Lax";
      proxy_cache               dhis;
    }
  }
}

Important

Sachez qu'un cache côté serveur court-circuite les fonctions de sécurité de DHIS2 dans le sens où les requêtes qui atteignent le cache côté serveur seront servies directement à partir du cache hors de contrôle de DHIS2 et du conteneur de servlets. Cela signifie que les URL des requêtes peuvent être devinées de même que les rapports récupérés dans le cache par des utilisateurs non autorisés. Par conséquent, si vous collectez des informations sensibles, la mise en place d'un cache côté serveur n'est pas recommandée.

Limitation de débit avec nginx

Certains appels d'API web dans DHIS 2, tels que les API d'analyses, nécessitent beaucoup de calculs. Par conséquent, il est préférable de limiter le débit de ces API afin d'équilibrer l'utilisation des ressources du serveur par les utilisateurs du système. La limitation de débit peut être effectuée avec nginx. Il existe plusieurs approches pour effectuer la limitation de débit et ceci est destiné à documenter l'approche basée sur nginx.

La configuration nginx ci-dessous limitera le débit de l'API Web des analyses et comporte les éléments suivants au niveau des blocs http et emplacement (la configuration est abrégée par souci de concision) :

http {
  ..
  limit_req_zone $binary_remote_addr zone=limit_analytics:10m rate=5r/s;

  server {
    ..

    location ~ ^/api/(\d+/)?analytics(.*)$ {
      limit_req    zone=limit_analytics burst=20;
      proxy_pass   http://localhost:8080/api/$1analytics$2$is_args$args;
      ..
    }
  }
}

Les différents éléments de la configuration peuvent être décrits comme suit :

  • limit_req_zone $binary_remote_addr : la limitation du débit est effectuée par adresse IP de requête.
  • zone=limit_analytics:20m : une zone de limite de débit pour l'API des analyses qui peut contenir jusqu'à 10 Mo d'adresses IP de requête.
  • taux=20r/s : Chaque IP reçoit 5 requêtes par seconde.
  • emplacement ~ ^/api/(\d+/)?analytics(.*)$ : les requêtes pour le point d'extrémité de l'API des analyses sont limitées en débit.
  • burst=20 : des rafales contenant jusqu'à 20 requêtes seront mises en file d'attente et traitées ultérieurement ; des demandes supplémentaires conduiront à un 503.

Pour obtenir une explication complète, veuillez consulter la documentation nginx.

Rendre les ressources disponibles avec nginx

Dans certains cas, il est souhaitable de rendre certaines ressources accessibles au public sur le web sans exiger une quelconque authentification. C'est le cas, par exemple, lorsque vous souhaitez rendre les ressources liées à l'analyse des données de l'API Web disponibles dans un portail Web. L'exemple suivant permet d'accéder aux graphiques, aux cartes, aux rapports, aux tableaux de rapports et aux ressources documentaires par le biais d'une authentification de base en insérant un en-tête HTTP d'Autorisation dans la demande. Il supprimera l'en-tête Cookie de la requête et l'en-tête Set-Cookie de la réponse afin d'éviter de modifier l'utilisateur connecté. Il est recommandé de créer un utilisateur à cette fin, en ne lui accordant que les autorisations minimales requises. La valeur d'autorisation peut être construite en codant le nom d'utilisateur avec base64, suivi de deux points et le mot de passe et en lui ajoutant le préfixe "Basic", plus précisément "Basic base64_encode(nom d'utilisateur:mot de passe)". Il vérifiera la méthode HTTP utilisée pour les requêtes et renverra 405 Method Not Allowed s'il détecte autre chose que GET.

En utilisant cette approche, il peut être avantageux de créer un domaine séparé pour les utilisateurs publics. En effet, nous ne voulons pas modifier les informations d'identification des utilisateurs déjà connectés lorsqu'ils accèdent aux ressources publiques. Par exemple, si votre serveur est déployé à l'adresse somedomain.com, vous pouvez créer un sous-domaine dédié à api.somedomain.com et orienter les URL de votre portail vers ce sous-domaine.

http {
  ..

  server {
    listen       80;
    server_name  api.somedomain.com;

    location ~ ^/(api/(charts|chartValues|reports|reportTables|documents|maps|organisationUnits)|dhis-web-commons/javascripts|images|dhis-web-commons-ajax-json|dhis-web-mapping|dhis-web-visualizer) {
    if ($request_method != GET) {
        return 405;
      }

      proxy_pass         http://localhost:8080;
      proxy_redirect     off;
      proxy_set_header   Host               $host;
      proxy_set_header   X-Real-IP          $remote_addr;
      proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;
      proxy_set_header   X-Forwarded-Proto  http;
      proxy_set_header   Authorization      "Basic YWRtaW46ZGlzdHJpY3Q=";
      proxy_set_header   Cookie             "";
      proxy_hide_header  Set-Cookie;
    }
  }
}

Bloquer des versions spécifiques d'applications Android avec nginx

Dans certains cas, l'administrateur du système peut vouloir bloquer certains clients Android sur la base de leur version de l'application DHIS2 ; par exemple, si les utilisateurs sur le terrain n'ont pas mis à jour leur version de l'application Android vers une version spécifique et que l'administrateur du système veut bloquer leur accès pour forcer une mise à jour, ou à l'inverse, si l'administrateur du système veut bloquer les nouvelles versions de l'application car elles n'ont pas encore été testées. Ceci peut être facilement implémenté en utilisant des règles spécifiques User-Agent dans le fichier de configuration nginx.

http {

  server {
    listen       80;
    server_name  api.somedomain.com;

    # Block the latest Android App as it has not been tested
    if ( $http_user_agent ~ 'com\.dhis2/1\.2\.1/2\.2\.1/' ) {
        return 403;
    }

    # Block Android 4.4 (API is 19) as all users should have received new tablets
    if ( $http_user_agent ~ 'com\.dhis2/.*/.*/Android_19' ) {
        return 403;
    }
  }
}

Remarque Pour l'implémentation de la méthode décrite ci-dessus, notez ce qui suit : * Avant la version 1.1.0, la chaîne User-Agent n'était pas envoyée. * De la version 1.1.0 à la version 1.3.2, le User-Agent suivait le modèle Dhis2/AppVersion/AppVersion/Android_XX. * Depuis la version 2.0.0 et plus, le User-Agent suit le modèle com.dhis2/SdkVersion/AppVersion/Android_XX * Android_XX fait référence au niveau de l'API Android, c'est-à-dire à la version d'Android telle que répertoriée [ici] (https://developer.android.com/studio/releases/platforms). * nginx utilise PCRE pour la mise en correspondance des expressions régulières.