Bagaimana saya dapat menguji koneksi https dengan Django semudah saya dapat koneksi non-https menggunakan 'runserver'?

109

Saya memiliki aplikasi yang menggunakan cookie "aman" dan ingin menguji fungsionalitasnya tanpa perlu menyiapkan server pengembangan berkemampuan SSL yang rumit. Apakah ada cara untuk melakukan ini semudah saya menguji permintaan yang tidak dienkripsi menggunakan ./manage.py runserver?

Evan Grim
sumber
Tidak bisakah Anda menentukan runserver 443 agar server berjalan pada port 443?
Furbeenator
@Furbeenator: Sayangnya tidak - ini hanya akan membuat server HTTP di 443, yang saya butuhkan adalah server SSL yang sebenarnya berjalan.
Evan Grim

Jawaban:

109

Ini tidak seperti sederhana seperti dibangun di server pengembangan, tapi itu tidak terlalu sulit untuk mendapatkan sesuatu yang dekat menggunakan stunnel sebagai perantara SSLifying antara browser dan server pembangunan. Stunnel memungkinkan Anda untuk menyiapkan server ringan di mesin Anda yang menerima koneksi pada port yang dikonfigurasi, membungkusnya dengan SSL, dan meneruskannya ke beberapa server lain. Kita akan menggunakan ini untuk membuka port stunnel (8443) dan meneruskan semua lalu lintas yang diterimanya ke instance runserver Django.

Pertama, Anda memerlukan stunnel yang dapat diunduh di sini atau mungkin disediakan oleh sistem paket platform Anda (misalnya:) apt-get install stunnel. Saya akan menggunakan stunnel versi 4 (misalnya: /usr/bin/stunnel4di Ubuntu), versi 3 juga akan berfungsi, tetapi memiliki opsi konfigurasi yang berbeda.

Pertama buat direktori dalam proyek Django Anda untuk menyimpan berkas konfigurasi yang diperlukan dan barang SSLish.

mkdir stunnel
cd stunnel

Selanjutnya kita perlu membuat sertifikat dan kunci lokal yang akan digunakan untuk komunikasi SSL. Untuk ini kita beralih ke openssl.

Buat kunci:

openssl genrsa 1024 > stunnel.key

Buat sertifikat yang menggunakan kunci ini (ini akan menanyakan Anda banyak informasi yang akan disertakan dalam sertifikat - jawab saja dengan apa pun yang Anda rasa nyaman):

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

Sekarang gabungkan ini menjadi satu file yang akan digunakan stunnel untuk komunikasi SSL-nya:

cat stunnel.key stunnel.cert > stunnel.pem

Buat file konfigurasi untuk stunnel bernama dev_https dengan konten berikut:

pid=

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

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

File ini memberi tahu stunnel apa yang perlu diketahui. Secara khusus, Anda memberi tahu untuk tidak menggunakan file pid, di mana file sertifikatnya, versi SSL apa yang akan digunakan, yang harus dijalankan di latar depan, di mana harus mencatat keluarannya, dan bahwa itu harus menerima koneksi pada port 8443 dan memindahkannya ke port 8001. Parameter terakhir (TIMEOUTclose) memberitahu untuk menutup koneksi secara otomatis setelah 1 detik telah berlalu tanpa aktivitas.

Sekarang munculan kembali ke direktori proyek Django Anda (yang dengan manage.py di dalamnya):

cd ..

Di sini kita akan membuat skrip bernama runserver yang akan menjalankan stunnel dan dua server pengembangan django (satu untuk koneksi normal, dan satu untuk koneksi SSL):

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

Mari kita uraikan ini, baris demi baris:

  • Baris 1: Memulai stunnel dan mengarahkannya ke file konfigurasi yang baru kita buat. Ini memiliki stunnel mendengarkan pada port 8443, membungkus koneksi apa pun yang diterimanya dalam SSL, dan meneruskannya ke port 8001
  • Baris 2: Memulai instance runserver Django normal (pada port 8000)
  • Baris 3: Memulai instance runserver Django lainnya (pada port 8001) dan mengkonfigurasinya untuk memperlakukan semua koneksi masuk seolah-olah mereka sedang dilakukan menggunakan HTTPS.

Jadikan file runscript yang baru saja kita buat dapat dieksekusi dengan:

chmod a+x runserver

Sekarang ketika Anda ingin menjalankan server pengembangan Anda, cukup jalankan ./runserverdari direktori proyek Anda. Untuk mencobanya, arahkan browser Anda ke http: // localhost: 8000 untuk lalu lintas HTTP normal, dan https: // localhost: 8443 untuk lalu lintas HTTPS. Perhatikan bahwa browser Anda hampir pasti akan mengeluh tentang sertifikat yang digunakan dan mengharuskan Anda menambahkan pengecualian atau secara eksplisit menginstruksikan browser untuk melanjutkan penelusuran. Ini karena Anda membuat sertifikat sendiri dan tidak dipercaya oleh browser untuk mengatakan yang sebenarnya tentang siapa itu. Ini bagus untuk pengembangan, tetapi jelas tidak akan dipotong untuk produksi.

Sayangnya, di komputer saya, skrip runserver ini tidak keluar dengan baik ketika saya menekan Ctrl-C. Saya harus mematikan proses secara manual - ada yang punya saran untuk memperbaikinya?

Terima kasih kepada posting Michael Gile dan entri wiki django-weave untuk bahan referensi.

Evan Grim
sumber
4
Saya baru saja menemukan jawaban ini. Beberapa komentar: Anda tidak perlu menjalankan instance pengembangan terpisah pada 8001, Anda juga dapat membiarkannya terhubung ke port 8000. Jika Anda ingin stunnel dimatikan secara otomatis, tambahkan fungsi dan exit trap: kill_stunnel () { kill $ stunnel_pid} trap kill_stunnel keluar stunnel4 stunnel / dev https & stunnel_pid = $ 1
Jumat
2
Instance kedua dipanggil dengan HTTPS = 1 yang berarti request.is_secure()akan melaporkan True. Jika Anda tidak membutuhkannya maka Anda benar - Anda bisa mengarahkan stunnel ke satu instance.
Evan Grim
Jika Anda mengalami mode stunnel fips tidak didukung .... tambahkan fips = no ke file dev_https untuk mematikannya
yeahdixon
2
Saya baru saja mencoba ini karena saya mencoba menyiapkan salinan pengembangan dari pekerjaan situs pada proyek yang dikembangkan oleh orang lain tetapi saya mendapatkannya "sslVersion = SSLv3": SSLv3 not supported.
HenryM
@Friek stunnel_pid=$1tidak bekerja untuk saya tetapi stunnel_pid=$!berhasil. Bagaimana stunnel_pid=$1Anda berhasil?
Utku
86

Saya akan merekomendasikan menggunakan paket django-sslserver .

Paket saat ini pada PyPI hanya mendukung hingga Django versi 1.5.5 tetapi tambalan telah dilakukan melalui 5d4664c . Dengan perbaikan ini, sistem berjalan dengan baik dan merupakan solusi yang cukup sederhana dan mudah untuk menguji koneksi https.

PEMBARUAN: Sejak saya memposting jawaban saya, komit di atas telah digabungkan ke dalam cabang master dan rilis baru telah didorong ke PyPI. Jadi tidak perlu menentukan commit 5d4664c untuk perbaikan khusus tersebut.

devonbleibtrey
sumber
5
Ini terlihat menjanjikan - Saya mungkin harus memperbarui jawaban yang diterima untuk yang satu ini. Adakah yang ingin menimbang?
Evan Grim
3
ini harus menjadi jawaban yang diterima, digunakan untuk sementara waktu dalam proyek yang cukup kompleks yang tidak dapat bekerja tanpa menjalankan https dan tidak pernah mengalami masalah.
simone cittadini
2
Bekerja dengan baik ... Terima kasih! :)
nidHi
5
Bekerja pada Python 3.6.2 dan Django 1.11.3.
phoenix
2
Bekerja pada Python 3.5 dan Django 1.11
Hansel
64

Mirip dengan django-sslserver Anda bisa menggunakan RunServerPlus dari django-extensions

Ini memiliki ketergantungan pada Werkzeug (sehingga Anda mendapatkan akses ke debugger Werkzeug yang sangat baik) dan pyOpenSSL (hanya diperlukan untuk mode ssl) jadi untuk menginstal jalankan:

pip install django-extensions Werkzeug pyOpenSSL

Tambahkan ke INSTALLED_APPS di file settings.py proyek Anda:

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

Kemudian Anda dapat menjalankan server dalam mode ssl dengan:

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

Ini akan membuat file sertifikat di /tmp/cert.crtdan file kunci /tmp/cert.keyyang kemudian dapat digunakan kembali untuk sesi mendatang.

Ada banyak hal tambahan yang termasuk dalam django-extensions yang mungkin berguna bagi Anda sehingga ada baiknya melihat-lihat dokumen dengan cepat.

djsutho.dll
sumber
2
Sebenarnya jawaban terbaik untuk Django 1.6+ karena django-sslserver tidak mendukung muat ulang otomatis untuk versi baru
Zat42
Jawaban terbaik untuk debugging + aktifkan SSL.
Yuda Prawira
Saya bertanya-tanya mengapa itu tidak berfungsi di aplikasi peti kemas buruh pelabuhan
Roel
@Roel mencobanya dengan cepat dan tampaknya berfungsi untuk aplikasi hello world. bisa jadi gambar dasar Anda tidak memiliki dependensi yang diperlukan (misalnya jika Anda menggunakan -alpine) atau Anda mungkin perlu membuka rentang IP Anda misalnya./manage.py runserver_plus --cert /tmp/cert 0.0.0.0:8000
djsutho
FileNotFoundError: [Errno 2] Tidak ada file atau direktori seperti itu: '/tmp\\cert.crt'
Mark Anthony Libres
38

instal saja

sudo pip install django-sslserver

sertakan sslserver di aps yang diinstal

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

sekarang kamu bisa lari

 python manage.py runsslserver 0.0.0.0:8888
Ryabchenko Alexander
sumber
2
Solusi terbersih!
SexyBeast
memang solusi yang bersih, tetapi untuk beberapa alasan, ini sangat lambat
Bhanu Tez
Hmm, Chrome memberi peringatan bahwa sertifikat tidak valid.
zerohedge
@zerohedge hanya untuk pengembangan, jadi tidak masalah.
Sharpless512
ini sangat elegan - tetapi adakah solusi untuk menggunakan ini untuk menguji koneksi aman? misalnya, apakah Anda ingin menguji dengan API Grafik Facebook? developer.facebook.com/docs/graph-api/webhooks#setup
frednikgohar
14

Daftar ke https://ngrok.com/ . Anda dapat menggunakan https untuk menguji. Ini dapat membantu orang yang hanya ingin menguji https dengan cepat.

Neil
sumber
6
Untuk pengujian cepat, ini adalah solusi yang bagus. Dan saya tidak perlu mendaftar untuk apa pun, cukup unduh dan jalankan ./ngrok http 8000, 8000 adalah port localhost saya.
GavKilbride
4

Bagi mereka yang mencari versi latar depan dari opsi stunnel untuk keperluan debugging:

stunnel.pem adalah sertifikat yang dihasilkan seperti dalam jawaban pilihan teratas Evan Grimm.

Dengarkan semua antarmuka lokal di port 443 dan teruskan ke port 80 di localhost

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

sudo hanya diperlukan untuk port masuk (-d [host:] port) di bawah 1024

Micheal Lunny
sumber
4
  1. Instal ngrok. tautan unduhan: https://ngrok.com/download
  2. Terbitkan mengikuti perintah di terminal

    ngrok http 8000

Ini akan memulai sesi ngrok. Ini akan mencantumkan dua url. Satu dipetakan ke http: // localhost: 8000 . Kedua dipetakan ke https: // localhost: 8000 . Silakan periksa gambar di bawah. Gunakan salah satu url. Ini akan memetakan ke server lokal Anda.

contoh tangkapan layar sesi ngrok

ABN
sumber
Cara termudah untuk melakukannya tetapi ingat untuk meletakkan url https baru keallowed_host
Roel
2

Itu bisa dilakukan dalam satu baris dengan socat:

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

, di mana 8443 adalah port untuk mendengarkan koneksi HTTPS yang masuk, server.pem adalah sertifikat server yang ditandatangani sendiri dan localhost: 8000 adalah server HTTP debug yang diluncurkan seperti biasa.

Rincian lebih lanjut: http://www.dest-unreach.org/socat/doc/socat-openssltunnel.html

uri.z
sumber
0

Tangani SSL / TLS dengan proxy seperti Nginx daripada Django. Nginx dapat disetel untuk mendengarkan pada port 443 dan kemudian meneruskan permintaan ke server Django dev Anda (biasanya http://127.0.0.1:8000). Konfigurasi Nginx untuk ini mungkin terlihat seperti berikut:

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

Anda juga akan perlu untuk memetakan django-dev.localhostke 127.0.0.1dan menambahkan django-dev.localhostke ALLOWED_HOSTSdalam settings.py. Di Linux, Anda perlu menambahkan baris berikut ke /etc/hosts:

127.0.0.1   django-dev.localhost

Kemudian Anda akan dapat mencapai situs dev Anda dengan masuk ke https://django-dev.localhostbrowser Anda (Anda harus melewati peringatan keamanan browser Anda).

lima puluh dua kartu
sumber