Comment puis-je tester les connexions https avec Django aussi facilement que les connexions non-https en utilisant 'runserver'?

109

J'ai une application qui utilise des cookies «sécurisés» et je souhaite tester ses fonctionnalités sans avoir à configurer un serveur de développement SSL complexe. Existe-t-il un moyen de le faire aussi simplement que je peux tester les demandes non chiffrées en utilisant ./manage.py runserver?

Evan Grim
la source
Ne pouvez-vous pas simplement spécifier runserver 443 pour que le serveur s'exécute sur le port 443?
Furbeenator
@Furbeenator: Malheureusement non - cela ne fera que rendre le serveur HTTP sur 443, ce dont j'ai besoin est un serveur SSL réel en cours d'exécution.
Evan Grim

Réponses:

109

Ce n'est pas aussi simple que le serveur de développement intégré, mais il n'est pas trop difficile d'obtenir quelque chose de proche en utilisant stunnel comme intermédiaire SSLifying entre votre navigateur et le serveur de développement. Stunnel vous permet de configurer un serveur léger sur votre machine qui accepte les connexions sur un port configuré, les enveloppe avec SSL et les transmet à un autre serveur. Nous allons l'utiliser pour ouvrir un port stunnel (8443) et transmettre tout trafic qu'il reçoit à une instance de Django runserver.

Vous aurez d'abord besoin de stunnel qui peut être téléchargé ici ou peut être fourni par le système de paquets de votre plate-forme (par exemple :) apt-get install stunnel. J'utiliserai la version 4 de stunnel (par exemple: /usr/bin/stunnel4sur Ubuntu), la version 3 fonctionnera également, mais a différentes options de configuration.

Créez d'abord un répertoire dans votre projet Django pour contenir les fichiers de configuration nécessaires et les éléments SSLish.

mkdir stunnel
cd stunnel

Ensuite, nous devrons créer un certificat local et une clé à utiliser pour la communication SSL. Pour cela, nous nous tournons vers openssl.

Créez la clé:

openssl genrsa 1024 > stunnel.key

Créez le certificat qui utilise cette clé (cela vous demandera un tas d'informations qui seront incluses dans le certificat - répondez simplement avec ce qui vous convient):

openssl req -new -x509 -nodes -sha1 -days 365 -key stunnel.key > stunnel.cert

Maintenant, combinez-les en un seul fichier que stunnel utilisera pour sa communication SSL:

cat stunnel.key stunnel.cert > stunnel.pem

Créez un fichier de configuration pour stunnel appelé dev_https avec le contenu suivant:

pid=

cert = stunnel/stunnel.pem
sslVersion = SSLv3
foreground = yes
output = stunnel.log

[https]
accept=8443
connect=8001
TIMEOUTclose=1

Ce fichier indique à Stunnel ce qu'il doit savoir. Plus précisément, vous lui dites de ne pas utiliser de fichier pid, où se trouve le fichier de certificat, quelle version de SSL utiliser, qu'il doit s'exécuter au premier plan, où il doit enregistrer sa sortie et qu'il doit accepter la connexion sur le port 8443 et les acheminer vers le port 8001. Le dernier paramètre (TIMEOUTclose) lui dit de fermer automatiquement la connexion après 1 seconde sans activité.

Maintenant, revenez dans le répertoire de votre projet Django (celui avec manage.py):

cd ..

Ici, nous allons créer un script nommé runserver qui exécutera stunnel et deux serveurs de développement django (un pour les connexions normales et un pour les connexions SSL):

stunnel4 stunnel/dev_https &
python manage.py runserver&
HTTPS=1 python manage.py runserver 8001

Décomposons ceci, ligne par ligne:

  • Ligne 1: Démarre stunnel et pointez-le vers le fichier de configuration que nous venons de créer. Cela a stunnel écouter sur le port 8443, envelopper toutes les connexions qu'il reçoit en SSL et les transmettre au port 8001
  • Ligne 2: Démarre une instance Django runserver normale (sur le port 8000)
  • Ligne 3: Démarre une autre instance de Django runserver (sur le port 8001) et la configure pour traiter toutes les connexions entrantes comme si elles étaient effectuées en HTTPS.

Rendez le fichier runscript que nous venons de créer exécutable avec:

chmod a+x runserver

Maintenant, lorsque vous souhaitez exécuter votre serveur de développement, exécutez simplement à ./runserverpartir du répertoire de votre projet. Pour l'essayer, pointez simplement votre navigateur sur http: // localhost: 8000 pour le trafic HTTP normal et https: // localhost: 8443 pour le trafic HTTPS. Notez que votre navigateur se plaindra presque certainement du certificat utilisé et vous demandera d'ajouter une exception ou de demander explicitement au navigateur de continuer à naviguer. En effet, vous avez créé votre propre certificat et le navigateur ne lui fait pas confiance pour dire la vérité sur qui il s'agit. C'est bien pour le développement, mais évidemment pas pour la production.

Malheureusement, sur ma machine, ce script runserver ne se termine pas correctement lorsque j'appuie sur Ctrl-C. Je dois tuer manuellement les processus - quelqu'un a-t-il une suggestion pour résoudre ce problème?

Merci au post de Michael Gile et à l' entrée wiki de django-weave pour le matériel de référence.

Evan Grim
la source
4
Je viens de tomber sur cette réponse. Quelques remarques: vous n'avez pas forcément besoin d'exécuter une instance de développement séparée sur 8001, vous pouvez aussi bien la laisser se connecter au port 8000. Si vous voulez que stunnel soit tué automatiquement, ajoutez une fonction et un exit trap: kill_stunnel () { kill $ stunnel_pid} piège kill_stunnel exit stunnel4 stunnel / dev https & stunnel_pid = $ 1
vendredi
2
La deuxième instance est appelée avec HTTPS = 1, ce qui signifie que request.is_secure()le rapport sera signalé True. Si vous n'en avez pas besoin, vous avez raison - vous pouvez simplement pointer Stunnel sur l'instance unique.
Evan Grim
Si vous utilisez le mode fips stunnel non pris en charge .... ajoutez fips = no au fichier dev_https pour le désactiver
yeahdixon le
2
Je viens d'essayer cela en essayant de mettre en place une copie de développement d'un travail de site sur un projet développé par quelqu'un d'autre, mais j'obtiens "sslVersion = SSLv3": SSLv3 not supported.
HenryM
@Friek stunnel_pid=$1n'a pas fonctionné pour moi mais l'a stunnel_pid=$!fait. Comment ça a stunnel_pid=$1marché pour vous?
Utku
86

Je recommanderais d'utiliser le package django-sslserver .

Le package actuel sur PyPI ne prend en charge que la version 1.5.5 de Django mais un correctif a été commis via 5d4664c . Avec ce correctif, le système fonctionne bien et constitue une solution assez simple et directe pour tester les connexions https.

MISE À JOUR: Depuis que j'ai publié ma réponse, le commit ci-dessus a été fusionné dans la branche principale et une nouvelle version a été envoyée à PyPI. Il ne devrait donc pas être nécessaire de spécifier le commit 5d4664c pour ce correctif spécifique.

devonbleibtrey
la source
5
Cela semble prometteur - je devrai peut-être mettre à jour la réponse acceptée sur celle-ci. Quelqu'un d'autre veut-il intervenir?
Evan Grim le
3
cela devrait devenir la réponse acceptée, utilisée pendant un certain temps dans un projet assez complexe qui ne peut tout simplement pas fonctionner sans fonctionner sur https et n'a jamais eu de problèmes.
simone cittadini
2
Fonctionne bien ... Merci! :)
nidHi
5
Fonctionne à partir de Python 3.6.2 et Django 1.11.3.
phoenix
2
Fonctionne à partir de Python 3.5 et Django 1.11
Hansel
64

Similaire à django-sslserver, vous pouvez utiliser RunServerPlus à partir de django-extensions

Il a des dépendances sur Werkzeug (vous avez donc accès à l'excellent débogueur Werkzeug) et pyOpenSSL (requis uniquement pour le mode ssl), donc pour installer, exécutez:

pip install django-extensions Werkzeug pyOpenSSL

Ajoutez-le à INSTALLED_APPS dans le fichier settings.py de votre projet:

INSTALLED_APPS = (
    ...
    'django_extensions',
    ...
)

Ensuite, vous pouvez exécuter le serveur en mode ssl avec:

./manage.py runserver_plus --cert /tmp/cert

Cela créera un fichier de certificat sur /tmp/cert.crtet un fichier de clé sur /tmp/cert.keylequel pourra être réutilisé pour de futures sessions.

Il y a un tas de trucs supplémentaires inclus dans les extensions django que vous pouvez trouver utiles, il vaut donc la peine de parcourir rapidement la documentation.

djsutho
la source
2
En fait, la meilleure réponse pour Django 1.6+ puisque django-sslserver ne prend pas en charge le rechargement automatique pour la nouvelle version
Zat42
La meilleure réponse pour le débogage + activer SSL.
Yuda Prawira
Je me demande pourquoi cela ne fonctionne pas dans l'application conteneurisée docker
Roel
@Roel a essayé rapidement et cela semble fonctionner pour une application Hello World. peut être que votre image de base n'a pas de dépendances requises (par exemple si vous utilisez -alpine) ou vous devrez peut-être ouvrir votre plage IP, par exemple./manage.py runserver_plus --cert /tmp/cert 0.0.0.0:8000
djsutho
FileNotFoundError: [Errno 2] Aucun fichier ou répertoire de ce type: '/tmp\\cert.crt'
Mark Anthony Libres
38

installe juste

sudo pip install django-sslserver

inclure sslserver dans les aps installés

INSTALLED_APPS = (...
"sslserver",
...
)

maintenant tu peux courir

 python manage.py runsslserver 0.0.0.0:8888
Ryabchenko Alexander
la source
2
La solution la plus propre!
SexyBeast
en effet une solution propre, mais pour une raison quelconque, elle est très lente
Bhanu Tez
Hmm, Chrome vous avertit que le certificat n'est pas valide.
zerohedge
@zerohedge c'est juste pour le développement, donc peu importe.
Sharpless512
c'est très élégant - mais y a-t-il une solution pour l'utiliser pour tester des connexions sécurisées? par exemple, si vous souhaitez tester contre l'API Facebook Graph? developer.facebook.com/docs/graph-api/webhooks#setup
frednikgohar
14

Inscrivez-vous sur https://ngrok.com/ . Vous pouvez utiliser https pour tester. Cela peut aider les personnes qui souhaitent simplement tester rapidement https.

Neil
la source
6
Pour un test rapide, c'est une excellente solution. Et je n'ai pas eu à m'inscrire pour quoi que ce soit, il suffit de télécharger et d'exécuter ./ngrok http 8000, 8000 est mon port localhost.
GavKilbride
4

Pour ceux qui recherchent une version au premier plan de l'option stunnel à des fins de débogage:

stunnel.pem est un certificat généré comme dans la réponse la plus votée d'Evan Grimm.

Écouter sur toutes les interfaces locales sur le port 443 et transférer vers le port 80 sur localhost

sudo stunnel -f -p stunnel.pem -P ~/stunnel.pid -r localhost:80 -d 443

sudo n'est nécessaire que pour les ports entrants (-d [hôte:] port) sous 1024

Micheal Lunny
la source
4
  1. Installez ngrok. lien de téléchargement: https://ngrok.com/download
  2. Émettre la commande suivante sur le terminal

    ngrok http 8000

Il démarrera la session ngrok. Il listera deux URL. L'un est mappé sur http: // localhost: 8000 . Le second est mappé sur https: // localhost: 8000 . Veuillez vérifier la capture d'écran ci-dessous. Utilisez l'une ou l'autre des URL. Il sera mappé à votre serveur local.

exemple de capture d'écran de session ngrok

ABN
la source
Le moyen le plus simple de le faire, mais n'oubliez pas de mettre la nouvelle URL https dans leallowed_host
Roel
2

Cela peut être fait en une seule ligne avec socat:

socat openssl-listen:8443,fork,reuseaddr,cert=server.pem,verify=0 tcp:localhost:8000

, où 8443 est un port pour écouter les connexions HTTPS entrantes, server.pem est un certificat de serveur auto-signé et localhost: 8000 est un serveur HTTP de débogage lancé comme d'habitude.

Plus de détails: http://www.dest-unreach.org/socat/doc/socat-openssltunnel.html

uri.z
la source
0

Gérez SSL / TLS avec un proxy tel que Nginx plutôt que Django. Nginx peut être configuré pour écouter sur le port 443, puis transférer les requêtes vers votre serveur de développement Django (généralement http://127.0.0.1:8000). Une configuration Nginx pour cela pourrait ressembler à ce qui suit:

server {
    listen 443 ssl;
    server_name django-dev.localhost;

    ssl_certificate /etc/ssl/certs/nginx_chain.pem;
    ssl_certificate_key /etc/ssl/private/nginx.pem;    

    location / {
        proxy_pass http://127.0.0.1:8000/;
        proxy_set_header Host $host;
    }
}

Vous aurez également besoin de carte django-dev.localhostpour 127.0.0.1et ajouter django-dev.localhostà ALLOWED_HOSTSdans settings.py. Sous Linux, vous devrez ajouter la ligne suivante à /etc/hosts:

127.0.0.1   django-dev.localhost

Vous pourrez ensuite accéder à votre site de développement en accédant à https://django-dev.localhostvotre navigateur (vous devrez contourner l'avertissement de sécurité de votre navigateur).

cinquante cartes
la source