Wie kann ich https-Verbindungen mit Django so einfach testen wie Nicht-https-Verbindungen mit 'runserver'?

108

Ich habe eine Anwendung, die "sichere" Cookies verwendet und deren Funktionalität testen möchte, ohne einen komplizierten SSL-fähigen Entwicklungsserver einrichten zu müssen. Gibt es eine Möglichkeit, dies so einfach zu tun, wie ich unverschlüsselte Anforderungen mit testen kann ./manage.py runserver?

Evan Grim
quelle
Können Sie nicht einfach den Runserver 443 angeben, damit der Server auf Port 443 ausgeführt wird?
Furbeenator
@ Furbeenator: Leider nicht - dies wird nur den Server HTTP auf 443 machen, was ich brauche, ist ein tatsächlicher SSL-Server, der ausgeführt wird.
Evan Grim

Antworten:

108

Es ist nicht so einfach wie der eingebaute Entwicklungsserver, aber es ist nicht allzu schwierig, mit stunnel als SSLifying-Vermittler zwischen Ihrem Browser und dem Entwicklungsserver etwas in die Nähe zu bringen. Mit Stunnel können Sie einen kompakten Server auf Ihrem Computer einrichten, der Verbindungen an einem konfigurierten Port akzeptiert, sie mit SSL umschließt und an einen anderen Server weiterleitet. Wir werden dies verwenden, um einen Stunnel-Port (8443) zu öffnen und den empfangenen Datenverkehr an eine Django-Runserver-Instanz weiterzuleiten.

Zuerst benötigen Sie einen Stunnel, der hier heruntergeladen oder vom Paketsystem Ihrer Plattform bereitgestellt werden kann (z apt-get install stunnel. B. :) . Ich werde Version 4 von stunnel verwenden (zB: /usr/bin/stunnel4unter Ubuntu), Version 3 wird ebenfalls funktionieren, hat aber verschiedene Konfigurationsoptionen.

Erstellen Sie zunächst ein Verzeichnis in Ihrem Django-Projekt, in dem die erforderlichen Konfigurationsdateien und SSLish-Inhalte gespeichert sind.

mkdir stunnel
cd stunnel

Als Nächstes müssen wir ein lokales Zertifikat und einen Schlüssel erstellen, die für die SSL-Kommunikation verwendet werden sollen. Dazu wenden wir uns an openssl.

Erstellen Sie den Schlüssel:

openssl genrsa 1024 > stunnel.key

Erstellen Sie das Zertifikat, das diesen Schlüssel verwendet (hier werden Sie nach einer Reihe von Informationen gefragt, die im Zertifikat enthalten sind - antworten Sie einfach mit dem, was sich für Sie gut anfühlt):

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

Kombinieren Sie diese nun zu einer einzigen Datei, die stunnel für die SSL-Kommunikation verwendet:

cat stunnel.key stunnel.cert > stunnel.pem

Erstellen Sie eine Konfigurationsdatei für stunnel mit dem Namen dev_https mit den folgenden Inhalten:

pid=

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

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

Diese Datei sagt stunnel, was es wissen muss. Insbesondere weisen Sie es an, keine PID-Datei zu verwenden, in der sich die Zertifikatdatei befindet, welche SSL-Version verwendet werden soll, die im Vordergrund ausgeführt werden soll, in der die Ausgabe protokolliert werden soll und die Verbindung am Port akzeptiert werden soll 8443 und bringen Sie sie zu Port 8001. Der letzte Parameter (TIMEOUTclose) weist ihn an, die Verbindung automatisch zu schließen, nachdem 1 Sekunde ohne Aktivität vergangen ist.

Kehren Sie nun zu Ihrem Django-Projektverzeichnis zurück (das mit der Datei "manage.py"):

cd ..

Hier erstellen wir ein Skript namens runserver, auf dem stunnel und zwei Django-Entwicklungsserver ausgeführt werden (einer für normale Verbindungen und einer für SSL-Verbindungen):

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

Lassen Sie uns dies Zeile für Zeile aufschlüsseln:

  • Zeile 1: Startet den Stunnel und zeigt auf die gerade erstellte Konfigurationsdatei. Dies hat Stunnel Listen auf Port 8443, umschließt alle Verbindungen, die es empfängt, in SSL und leitet sie an Port 8001 weiter
  • Zeile 2: Startet eine normale Django-Runserver-Instanz (auf Port 8000).
  • Zeile 3: Startet eine andere Django-Runserver-Instanz (auf Port 8001) und konfiguriert sie so, dass alle eingehenden Verbindungen so behandelt werden, als würden sie mit HTTPS ausgeführt.

Machen Sie die gerade erstellte Runscript-Datei ausführbar mit:

chmod a+x runserver

Wenn Sie jetzt Ihren Entwicklungsserver ausführen möchten, führen Sie ihn einfach ./runserveraus Ihrem Projektverzeichnis aus. Zeigen Sie zum Ausprobieren einfach Ihren Browser auf http: // localhost: 8000 für normalen HTTP-Verkehr und https: // localhost: 8443 für HTTPS-Verkehr. Beachten Sie, dass sich Ihr Browser mit ziemlicher Sicherheit über das verwendete Zertifikat beschwert und Sie dazu auffordert, eine Ausnahme hinzuzufügen oder den Browser anderweitig ausdrücklich anzuweisen, mit dem Surfen fortzufahren. Dies liegt daran, dass Sie Ihr eigenes Zertifikat erstellt haben und der Browser nicht darauf vertraut, dass er die Wahrheit darüber sagt, wer es ist. Dies ist gut für die Entwicklung, wird es aber offensichtlich nicht für die Produktion schneiden.

Leider wird dieses Runserver-Skript auf meinem Computer nicht gut beendet, wenn ich Strg-C drücke. Ich muss die Prozesse manuell beenden - hat jemand einen Vorschlag, um das zu beheben?

Vielen Dank an Michael Giles Beitrag und den Wiki-Eintrag von Django-Weave für das Referenzmaterial.

Evan Grim
quelle
3
Ich bin gerade auf diese Antwort gestoßen. Einige Anmerkungen: Sie müssen nicht unbedingt eine separate Entwicklungsinstanz auf 8001 ausführen, sondern können diese auch mit Port 8000 verbinden. Wenn Sie möchten, dass der Stunnel automatisch beendet wird, fügen Sie eine Funktion und einen Exit-Trap hinzu: kill_stunnel () { kill $ stunnel_pid} trap kill_stunnel exit stunnel4 stunnel / dev https & stunnel_pid = $ 1
Friek
2
Die zweite Instanz wird mit HTTPS = 1 aufgerufen, was bedeutet, dass request.is_secure()gemeldet wird True. Wenn Sie das nicht brauchen, haben Sie Recht - Sie können den Tunnel einfach auf die einzelne Instanz richten.
Evan Grim
Wenn Sie in den nicht unterstützten Stunnel-Fips-Modus geraten ... fügen Sie der dev_https-Datei fips = no hinzu, um sie auszuschalten
yeahdixon
2
Ich habe es gerade versucht, als ich versuche, eine Entwicklungskopie einer Site-Arbeit an einem Projekt zu erstellen, das von jemand anderem entwickelt wurde, aber ich bekomme "sslVersion = SSLv3": SSLv3 not supported.
HenryM
@Friek stunnel_pid=$1hat bei mir nicht funktioniert, aber stunnel_pid=$!funktioniert. Wie hat stunnel_pid=$1bei dir gearbeitet?
Utku
86

Ich würde empfehlen, das Paket django-sslserver zu verwenden .

Das aktuelle Paket auf PyPI unterstützt nur bis zu Django Version 1.5.5, aber ein Patch wurde über 5d4664c festgeschrieben . Mit diesem Fix läuft das System gut und ist eine ziemlich einfache und unkomplizierte Lösung zum Testen von https-Verbindungen.

UPDATE: Da ich meine Antwort gepostet commit oben wurde verschmolzen in den Hauptzweig und ein neues Release hat PyPI geschoben worden. Es sollte also nicht erforderlich sein, das 5d4664c-Commit für diesen bestimmten Fix anzugeben.

devonbleibtrey
quelle
5
Das sieht vielversprechend aus - ich muss möglicherweise die akzeptierte Antwort auf diese Frage aktualisieren. Möchte noch jemand wiegen?
Evan Grim
3
Dies sollte die akzeptierte Antwort werden, die für eine Weile in einem recht komplexen Projekt verwendet wird, das einfach nicht funktionieren kann, ohne auf https zu laufen, und nie Probleme hatte.
Simone Cittadini
2
Funktioniert gut ... Danke! :)
nidHi
5
Funktioniert ab Python 3.6.2 und Django 1.11.3.
Phoenix
2
Funktioniert ab Python 3.5 und Django 1.11
Hansel
64

Ähnlich wie bei django-sslserver können Sie RunServerPlus von django-extensions verwenden

Es hat Abhängigkeiten von Werkzeug (damit Sie Zugriff auf den hervorragenden Werkzeug-Debugger erhalten) und pyOpenSSL (nur für den SSL-Modus erforderlich), um Folgendes zu installieren:

pip install django-extensions Werkzeug pyOpenSSL

Fügen Sie es INSTALLED_APPS in der Datei settings.py Ihres Projekts hinzu:

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

Dann können Sie den Server im SSL-Modus ausführen mit:

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

Dadurch werden eine Zertifizierungsdatei /tmp/cert.crtund eine Schlüsseldatei erstellt, /tmp/cert.keydie dann für zukünftige Sitzungen wiederverwendet werden können.

In Django-Erweiterungen sind einige zusätzliche Dinge enthalten, die Sie möglicherweise verwenden können. Es lohnt sich also, einen kurzen Blick durch die Dokumente zu werfen.

djsutho
quelle
2
Eigentlich die beste Antwort für Django 1.6+, da django-sslserver das automatische Neuladen für die neue Version nicht unterstützt
Zat42
Die beste Antwort zum Debuggen + Aktivieren von SSL.
Yuda Prawira
Ich frage mich, warum es in der Docker-Container-App nicht funktioniert
Roel
@Roel hat es kurz ausprobiert und es scheint für eine Hallo-Welt-App zu funktionieren. Möglicherweise sind für Ihr Basis-Image keine Abhängigkeiten erforderlich (z. B. wenn Sie -alpine verwenden), oder Sie müssen Ihren IP-Bereich öffnen, z. B../manage.py runserver_plus --cert /tmp/cert 0.0.0.0:8000
djsutho,
FileNotFoundError: [Errno 2] Keine solche Datei oder kein solches Verzeichnis: '/tmp\\cert.crt'
Mark Anthony Libres
38

einfach installieren

sudo pip install django-sslserver

sslserver in installierte aps einbinden

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

Jetzt kannst du rennen

 python manage.py runsslserver 0.0.0.0:8888
Ryabchenko Alexander
quelle
2
Die sauberste Lösung!
SexyBeast
in der Tat eine saubere Lösung, aber aus irgendeinem Grund ist es sehr langsam
Bhanu Tez
Hmm, Chrome warnt, dass das Zertifikat ungültig ist.
Zerohedge
@zerohedge ist nur für die Entwicklung, also spielt es keine Rolle.
Sharpless512
Das ist sehr elegant - aber gibt es eine Lösung, um damit sichere Verbindungen zu testen? Zum Beispiel, wenn Sie gegen Facebook Graph API testen möchten? developer.facebook.com/docs/graph-api/webhooks#setup
frednikgohar
14

Melden Sie sich bei https://ngrok.com/ an . Sie können https zum Testen verwenden. Dies kann Menschen helfen, die nur schnell https testen möchten.

Neil
quelle
6
Für einen schnellen Test ist dies eine großartige Lösung. Und ich musste mich für nichts anmelden, nur herunterladen und ausführen ./ngrok http 8000, 8000 ist mein localhost-Port.
GavKilbride
4

Für diejenigen, die nach einer Vordergrundversion der Stunnel-Option für Debugging-Zwecke suchen:

stunnel.pem ist ein Zertifikat, das wie in Evan Grimms bestbewerteter Antwort generiert wurde.

Lauschen Sie allen lokalen Schnittstellen an Port 443 und leiten Sie sie an Port 80 von localhost weiter

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

sudo ist nur für eingehende Ports (-d [host:] port) unter 1024 erforderlich

Micheal Lunny
quelle
4
  1. Installieren Sie ngrok. Download-Link: https://ngrok.com/download
  2. Geben Sie den folgenden Befehl am Terminal aus

    ngrok http 8000

Es wird die ngrok-Sitzung gestartet. Es werden zwei URLs aufgelistet. Einer ist http: // localhost: 8000 zugeordnet . Der zweite ist https: // localhost: 8000 zugeordnet . Bitte überprüfen Sie den Screenshot unten. Verwenden Sie eine der beiden URLs. Es wird Ihrem lokalen Server zugeordnet.

Beispiel-Screenshot einer ngrok-Sitzung

ABN
quelle
Der einfachste Weg, dies zu tun, aber denken Sie daran, die neue https-URL an denallowed_host
Roel
2

Dies kann in einer Zeile mit socat erfolgen:

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

server.pem ist ein selbstsigniertes Serverzertifikat und localhost: 8000 ist ein Debug-HTTP-Server, der wie gewohnt gestartet wird.

Weitere Details: http://www.dest-unreach.org/socat/doc/socat-openssltunnel.html

uri.z
quelle
0

Behandeln Sie SSL / TLS mit einem Proxy wie Nginx anstelle von Django. Nginx kann so eingerichtet werden, dass es Port 443 überwacht und Anforderungen (normalerweise http://127.0.0.1:8000) an Ihren Django-Entwicklungsserver weiterleitet . Eine Nginx-Konfiguration hierfür könnte folgendermaßen aussehen:

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;
    }
}

Sie werden auch eine Karte brauchen , django-dev.localhostum 127.0.0.1hinzuzufügen , django-dev.localhostum ALLOWED_HOSTSin settings.py. Unter Linux müssen Sie die folgende Zeile hinzufügen /etc/hosts:

127.0.0.1   django-dev.localhost

Sie können dann Ihre Entwickler-Site erreichen, indem Sie https://django-dev.localhostin Ihrem Browser aufrufen (Sie müssen die Sicherheitswarnung Ihres Browsers umgehen).

fünfzig Karten
quelle