Configuration SSL de l’hôte virtuel Docker Container

J’ai la configuration suivante et fonctionne correctement (je suis sur Docker 1.6):

entrer la description de l'image ici

Un conteneur Docker fait office de proxy d’hôte virtuel pour les autres applications Web exécutées dans des conteneurs Docker individuels. (Je devrais append que je ne suis pas un as de la configuration des serveurs ou des réseaux).

J’ai essayé d’append SSL à la configuration, mais avec peu de succès. Chaque conteneur monte le répertoire de fichiers sur l’hôte pour les certificates. Par exemple, pour exécuter un conteneur une fois que j’utilise les éléments suivants:

docker run -d -P --name build \ -v /home/applications/src/ssl-cert:/etc/ssl/certs \ -e "DBL=mysql:dbname=build;host=192.168.0.1;port=3306" \ -e "DB_USER=foo" -e "DB_PASS=bar" \ --link mysql56:mysql \ --add-host dockerhost:`/sbin/ip addr | grep 'eth0' | grep 'inet' | cut -d'/' -f1 | awk '{print $2}'` \ -p 8001:80 -p 4431:443 \ repos/build:latest 

Si je tente de me connecter à https://build.example.com j’obtiens des erreurs de certificate et je ne peux pas me connecter. La configuration Apache du conteneur a la configuration appropriée dans default-ssl.conf pour les fichiers de certificate (qui fonctionne s’il s’agit d’une instance autonome):

  ServerAdmin webmaster@localhost DocumentRoot /var/www/html/ # Enable/Disable SSL for this virtual host. SSLEngine on SSLProtocol all -SSLv2 -SSLv3 SSLHonorCipherOrder On SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS SSLCertificateFile /etc/ssl/certs/build.crt SSLCertificateKeyFile /etc/ssl/certs/build.key SSLCACertificateFile /etc/ssl/certs/digicert/digicertca.crt #SSLOptions +FakeBasicAuth +ExportCertData +SsortingctRequire  SSLOptions +StdEnvVars   SSLOptions +StdEnvVars  BrowserMatch "MSIE [2-6]" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 # MSIE 7 and newer should be able to use keepalive BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown  

Ensuite, j’essaie d’exécuter ce qui suit pour le conteneur proxy:

 docker run -it -d -P --name apache_proxy \ -v /home/applications/src/ssl-cert:/etc/ssl/certs \ -p 8000:80 -p 443:443 \ repos/apache-proxy:latest 

Ce conteneur contient également le même default-ssl.conf.

J’ai essayé de faire fonctionner ceci dans plusieurs configurations différentes:

  • exécuter la configuration SSL dans le conteneur proxy Apache uniquement
  • exécuter la configuration SSL dans le conteneur d’application de génération uniquement
  • exécuter la configuration SSL dans les deux conteneurs

Si vous vous sentez comme si je manque quelque chose d’évident, mais ne peut pas mettre le doigt sur ce que ce serait. Y a-t-il quelque chose qui me manque quand il s’agit d’exécuter SSL dans une configuration comme celle-ci?

Lorsque nous voulons append SSL aux hôtes derrière un proxy inverse, nous pouvons configurer les hôtes de trois manières:

  • Edge: le proxy inverse décrypte le trafic HTTPS entrant et communique avec les serveurs principaux via HTTP en texte brut.
  • Pass-through: les serveurs principaux décryptent tout le trafic et le proxy inverse leur transmet simplement les requêtes HTTPS.
  • Hybride: le proxy inverse décrypte le trafic HTTPS, puis rechiffre le trafic lié aux serveurs principaux.

La première option est la plus facile à configurer: il suffit d’installer des certificates et de configurer SSL sur le proxy inverse. La seconde approche “pass-through” permet aux serveurs backend de gérer indépendamment leurs configurations SSL, mais le proxy inverse est désormais “aveugle” car il ne peut pas lire le trafic chiffré, ce que nous souhaitons peut-être pour la journalisation (exemple). Nous utiliserions la troisième configuration hybride lorsque le proxy doit lire le trafic, mais nous ne faisons pas confiance au réseau entre le proxy et les serveurs principaux.

Sur la base des informations contenues dans la question, la première option semble la plus appropriée car nous faisons confiance au réseau Docker interne entre le proxy inverse et les serveurs principaux. Nous pouvons supprimer la configuration SSL des serveurs principaux et transférer les demandes du proxy inverse vers leurs ports HTTP standard.

Cette configuration nécessite deux composants supplémentaires:

  • Hôtes virtuels basés sur des noms configurés sur le proxy pour transférer les demandes pour chaque service backend.
  • Un certificate unique qui sécurise tous les noms de domaine backend (en tant que sujets multiples ou en tant que caractère générique tel que * .example.com ).

Voici un exemple de section de configuration d’hôte virtuel sur laquelle nous pouvons construire:

  ServerName build.example.com ProxyRequests Off ProxyPreserveHost On ProxyPass / http://build:8001/ ProxyPassReverse / http://build:8001/   ServerName cicd.example.com ProxyRequests Off ProxyPreserveHost On ProxyPass / http://cicd:8002/ ProxyPassReverse / http://cicd:8002/  

… et n’oubliez pas de configurer les directives SSL dans le bloc d’hôte virtuel par défaut . Si nous lions les conteneurs ou les exécutons sur le même réseau Docker, nous pouvons utiliser leurs noms de conteneur comme noms d’hôtes dans notre fichier httpd.conf, comme indiqué ci-dessus.


En ce qui concerne la mise en réseau, la question semble indiquer que nous devons examiner de plus près la mise en réseau Docker car je ne vois aucun indice indiquant que les conteneurs ont été configurés pour communiquer (le statut de réponse 503 prend en charge cette hypothèse). Le conteneur de proxy inverse doit transmettre les demandes à chacun des conteneurs backend, mais il ne peut pas le faire à moins de lier les conteneurs ( obsolète ) ou de créer un réseau interne défini par l’utilisateur entre les conteneurs:

 $ docker network create build_network $ docker run --network build_network --name apache_proxy ... $ docker run --network build_network --name build ... $ docker run --network build_network --name cicd ... 

Lorsque nous exécutons des conteneurs sur le même réseau défini par l’utilisateur, ils peuvent résoudre les adresses IP d’autres conteneurs par nom de conteneur via le résolveur DNS interne de Docker (ou par un autre nom d’hôte si nous --hostname argument --hostname pour docker run ). Notez également que, chaque conteneur représentant un hôte discret, il n’est pas nécessaire d’incrémenter ses numéros de port ( 8001 , 8002 , etc.). Nous pouvons utiliser le port 80 pour desservir le trafic HTTP de chaque conteneur sur le réseau interne.

  +────────────────── Docker Host ─────────────────+ │ +────────────── build_network ─────────────+ │ │ │ │ │ Client ────────────── apache_proxy (:443 → :443) │ │ │ │ ├── build (:80) │ │ │ │ └── cicd (:80) │ │ │ +──────────────────────────────────────────+ │ +────────────────────────────────────────────────+ 

Normalement, si vos serveurs s’exécutent derrière un serveur Apache, il vous suffit de configurer Apache pour qu’il fonctionne avec des certificates SSL. Ceci si Apache est le seul serveur “extérieur” exposé et que les autres serveurs ne sont pas directement accessibles du monde extérieur

Vous auriez besoin d’Apache pour proxy vers les autres serveurs en raison de l’URL ou du port, par exemple:

  ServerName SERVERNAME_HERE SSLProtocol all -SSLv2 -SSLv3 SSLHonorCipherOrder On SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS SSLCertificateFile /etc/ssl/certs/build.crt SSLCertificateKeyFile /etc/ssl/certs/build.key SSLCACertificateFile /etc/ssl/certs/digicert/digicertca.crt # Proxy pass to other server ProxyRequests Off ProxyPreserveHost On ProxyPass / http://OTHER_SERVER_IP_WITHIN_DOCKER_NETWORK:8081/ ProxyPassReverse / http://OTHER_SERVER_IP_WITHIN_DOCKER_NETWORK:8081/   

J’espère que ça vous aide le long …