ฉันมีแอปพลิเคชันที่ใช้คุกกี้ "ปลอดภัย" และต้องการทดสอบการทำงานโดยไม่จำเป็นต้องตั้งค่าเซิร์ฟเวอร์การพัฒนาที่เปิดใช้งาน SSL ที่ซับซ้อน มีวิธีการทำเช่นนี้เป็นเพียงฉันสามารถทดสอบคำขอที่ไม่ใช่การเข้ารหัสโดยใช้ใด ๆ./manage.py runserver
?
ฉันมีแอปพลิเคชันที่ใช้คุกกี้ "ปลอดภัย" และต้องการทดสอบการทำงานโดยไม่จำเป็นต้องตั้งค่าเซิร์ฟเวอร์การพัฒนาที่เปิดใช้งาน SSL ที่ซับซ้อน มีวิธีการทำเช่นนี้เป็นเพียงฉันสามารถทดสอบคำขอที่ไม่ใช่การเข้ารหัสโดยใช้ใด ๆ./manage.py runserver
?
คำตอบ:
มันไม่ได้เป็นง่ายๆเป็นที่สร้างขึ้นในเซิร์ฟเวอร์การพัฒนา แต่ก็ไม่ยากเกินไปที่จะได้รับสิ่งที่ใกล้เคียงกับการใช้ stunnel เป็นคนกลาง SSLifying ระหว่างเบราเซอร์และเซิร์ฟเวอร์การพัฒนาของคุณ Stunnel ช่วยให้คุณสามารถตั้งค่าเซิร์ฟเวอร์ที่มีน้ำหนักเบาบนเครื่องของคุณซึ่งยอมรับการเชื่อมต่อบนพอร์ตที่กำหนดค่าไว้ห่อด้วย SSL และส่งต่อไปยังเซิร์ฟเวอร์อื่น ๆ เราจะใช้สิ่งนี้เพื่อเปิดพอร์ต Stunnel (8443) และส่งต่อการรับส่งข้อมูลใด ๆ ที่ได้รับไปยังอินสแตนซ์ของรันเนอร์เวอร์ Django
ครั้งแรกที่คุณจะต้อง stunnel ซึ่งสามารถดาวน์โหลดได้ที่นี่หรืออาจจะให้โดยระบบแพคเกจแพลตฟอร์มของคุณ (เช่น: apt-get install stunnel
) ฉันจะใช้ Stunnel เวอร์ชัน 4 (เช่น/usr/bin/stunnel4
บน Ubuntu) เวอร์ชัน 3 ก็ใช้ได้เช่นกัน แต่มีตัวเลือกการกำหนดค่าที่แตกต่างกัน
ขั้นแรกให้สร้างไดเร็กทอรีในโปรเจ็กต์ Django ของคุณเพื่อเก็บไฟล์คอนฟิกูเรชันที่จำเป็นและข้อมูล SSLish
mkdir stunnel
cd stunnel
ต่อไปเราจะต้องสร้างใบรับรองในเครื่องและคีย์เพื่อใช้สำหรับการสื่อสาร SSL สำหรับสิ่งนี้เราหันไปใช้ openssl
สร้างคีย์:
openssl genrsa 1024 > stunnel.key
สร้างใบรับรองที่ใช้คีย์นี้ (ซึ่งจะถามข้อมูลจำนวนมากที่จะรวมอยู่ในใบรับรอง - เพียงแค่ตอบสิ่งที่คุณรู้สึกดี):
openssl req -new -x509 -nodes -sha1 -days 365 -key stunnel.key > stunnel.cert
ตอนนี้รวมสิ่งเหล่านี้เป็นไฟล์เดียวที่ Stunnel จะใช้สำหรับการสื่อสาร SSL:
cat stunnel.key stunnel.cert > stunnel.pem
สร้างไฟล์กำหนดค่าสำหรับ Stunnel ชื่อ dev_https โดยมีเนื้อหาต่อไปนี้:
pid=
cert = stunnel/stunnel.pem
sslVersion = SSLv3
foreground = yes
output = stunnel.log
[https]
accept=8443
connect=8001
TIMEOUTclose=1
ไฟล์นี้บอกสิ่งที่จำเป็นต้องรู้ Stunnel โดยเฉพาะอย่างยิ่งคุณกำลังบอกว่าอย่าใช้ไฟล์ pid โดยที่ไฟล์ใบรับรองคือ SSL เวอร์ชันใดที่จะใช้ว่าควรทำงานในเบื้องหน้าที่ซึ่งควรบันทึกเอาต์พุตและควรยอมรับการเชื่อมต่อบนพอร์ต 8443 และส่งไปยังพอร์ต 8001 พารามิเตอร์สุดท้าย (TIMEOUTclose) บอกให้ปิดการเชื่อมต่อโดยอัตโนมัติหลังจากผ่านไป 1 วินาทีโดยไม่มีกิจกรรมใด ๆ
ตอนนี้ป๊อปสำรองไปยังไดเร็กทอรีโครงการ Django ของคุณ (อันที่มี Manage.py อยู่ในนั้น):
cd ..
ที่นี่เราจะสร้างสคริปต์ชื่อรันเนอร์เวอร์ที่จะรัน Stunnel และเซิร์ฟเวอร์การพัฒนา django สองตัว (หนึ่งตัวสำหรับการเชื่อมต่อปกติและอีกอันสำหรับการเชื่อมต่อ SSL):
stunnel4 stunnel/dev_https &
python manage.py runserver&
HTTPS=1 python manage.py runserver 8001
มาทำลายสิ่งนี้ทีละบรรทัด:
สร้างไฟล์ runscript ที่เราเพิ่งสร้างปฏิบัติการด้วย:
chmod a+x runserver
ตอนนี้เมื่อคุณต้องการเรียกใช้เซิร์ฟเวอร์การพัฒนาของคุณเพียงแค่ดำเนินการ./runserver
จากไดเรกทอรีโครงการของคุณ หากต้องการทดลองใช้เพียงแค่ชี้เบราว์เซอร์ของคุณไปที่http: // localhost: 8000สำหรับการรับส่งข้อมูล HTTP ปกติและhttps: // localhost: 8443สำหรับการรับส่งข้อมูล HTTPS โปรดทราบว่าเบราว์เซอร์ของคุณเกือบจะบ่นอย่างแน่นอนเกี่ยวกับใบรับรองที่ใช้และกำหนดให้คุณต้องเพิ่มข้อยกเว้นหรือสั่งให้เบราว์เซอร์เรียกดูต่อไปอย่างชัดเจน นี่เป็นเพราะคุณสร้างใบรับรองของคุณเองและเบราว์เซอร์ไม่ได้รับความไว้วางใจให้บอกความจริงว่าเป็นใคร นี่เป็นสิ่งที่ดีสำหรับการพัฒนา แต่เห็นได้ชัดว่าจะไม่ตัดมันเพื่อการผลิต
น่าเสียดายที่ในเครื่องของฉันสคริปต์ runerver นี้ไม่ได้ออกอย่างดีเมื่อฉันกด Ctrl-C ฉันต้องฆ่ากระบวนการด้วยตนเอง - ใครมีข้อเสนอแนะในการแก้ไขหรือไม่
ขอบคุณโพสต์ของ Michael Gile และรายการวิกิพีเดียของ django -oven สำหรับข้อมูลอ้างอิง
request.is_secure()
True
หากคุณไม่ต้องการสิ่งนั้นแสดงว่าคุณพูดถูก - คุณสามารถชี้ Stunnel ที่อินสแตนซ์เดียว
"sslVersion = SSLv3": SSLv3 not supported
แต่ฉันได้รับ
TLSv1.2
ฉันได้แก้ไขคำตอบไปยังบัญชีสำหรับการเลิกใช้งานของSSLv3
SSLv3
ฉันอยากจะแนะนำให้ใช้แพ็คเกจdjango-sslserver
แพคเกจในปัจจุบันเกี่ยวกับ PyPI สนับสนุนได้ถึง Django รุ่น 1.5.5 แต่แพทช์มีความมุ่งมั่นผ่าน5d4664c ด้วยการแก้ไขนี้ระบบจะทำงานได้ดีและเป็นวิธีที่ค่อนข้างง่ายและตรงไปตรงมาสำหรับการทดสอบการเชื่อมต่อ https
อัปเดต: เนื่องจากฉันโพสต์คำตอบของฉันการกระทำข้างต้นได้รวมเข้ากับสาขาหลักและรุ่นใหม่ได้รับการผลักดันไปยัง PyPI ดังนั้นจึงไม่จำเป็นต้องระบุการกระทำ 5d4664c สำหรับการแก้ไขเฉพาะนั้น
คล้ายกับ django-sslserver คุณสามารถใช้RunServerPlusจากdjango-extensions
มีการพึ่งพา Werkzeug (ดังนั้นคุณจึงสามารถเข้าถึงตัวดีบัก Werkzeug ที่ยอดเยี่ยม) และ pyOpenSSL (จำเป็นสำหรับโหมด ssl เท่านั้น) เพื่อติดตั้งรัน:
pip install django-extensions Werkzeug pyOpenSSL
เพิ่มลงใน INSTALLED_APPS ในไฟล์ settings.py โครงการของคุณ:
INSTALLED_APPS = (
...
'django_extensions',
...
)
จากนั้นคุณสามารถเรียกใช้เซิร์ฟเวอร์ในโหมด ssl ด้วย:
./manage.py runserver_plus --cert /tmp/cert
สิ่งนี้จะสร้างไฟล์ใบรับรองที่/tmp/cert.crt
และไฟล์คีย์ที่/tmp/cert.key
สามารถนำมาใช้ซ้ำสำหรับเซสชันในอนาคตได้
มีสิ่งพิเศษอีกมากมายที่รวมอยู่ในส่วนขยายของ django ที่คุณอาจพบว่าใช้งานได้ดังนั้นจึงควรค่าแก่การอ่านเอกสารอย่างรวดเร็ว
./manage.py runserver_plus --cert /tmp/cert 0.0.0.0:8000
เพียงแค่ติดตั้ง
sudo pip install django-sslserver
รวม sslserver ใน aps ที่ติดตั้ง
INSTALLED_APPS = (...
"sslserver",
...
)
ตอนนี้คุณสามารถเรียกใช้
python manage.py runsslserver 0.0.0.0:8888
สำหรับผู้ที่มองหาตัวเลือก Stunnel เวอร์ชันเบื้องหน้าเพื่อวัตถุประสงค์ในการดีบัก:
stunnel.pem เป็นใบรับรองที่สร้างขึ้นเช่นเดียวกับคำตอบที่ได้รับการโหวตสูงสุดของ Evan Grimm
ฟังบนอินเตอร์เฟสโลคัลทั้งหมดบนพอร์ต 443 และส่งต่อไปยังพอร์ต 80 บน localhost
sudo stunnel -f -p stunnel.pem -P ~/stunnel.pid -r localhost:80 -d 443
sudo จำเป็นสำหรับพอร์ตขาเข้าเท่านั้น (-d [host:] port) ที่ต่ำกว่า 1024
วิธีหนึ่งคือการใช้ ngrok
ติดตั้ง ngrok ลิงค์ดาวน์โหลด: https://ngrok.com/download
ออกคำสั่งต่อไปนี้บนเทอร์มินัล
ngrok http 8000
มันจะเริ่มเซสชัน ngrok มันจะแสดงรายการสอง url หนึ่งแมปกับ http: // localhost: 8000 วินาทีถูกแมปกับ https: // localhost: 8000 โปรดตรวจสอบภาพหน้าจอด้านล่าง ใช้ url อย่างใดอย่างหนึ่ง มันจะแมปกับเซิร์ฟเวอร์ภายในของคุณ
วิธีที่สองเป็นไปตามวิธีการแก้ปัญหาที่จัดทำโดย @EvanGrim ลิงก์ - https://stackoverflow.com/a/8025645/9384511
วิธีแรกเป็นวิธีที่แนะนำหากคุณต้องการทดสอบ https url เพียงสองสามครั้ง แต่ถ้าความต้องการของคุณบอกว่า https เป็นข้อบังคับก็จะดีกว่าถ้าคุณทำตามวิธีที่สอง ฉันประสบปัญหาต่อไปนี้เกี่ยวกับโซลูชัน @EvanGrim
ฉันแก้ไขปัญหาเหล่านี้โดยการเพิ่ม subAltname ลงในใบรับรอง ssl ด้านล่างนี้เป็นขั้นตอนที่ฉันทำตามเพื่อเรียกใช้เซิร์ฟเวอร์ https ภายในโดยไม่มีปัญหาสองประการข้างต้น
ติดตั้ง Stunnel เวอร์ชัน Stunnel ที่ใช้คือ version4 (/ usr / bin / stunnel4) สำหรับ Ubuntu execute
sudo apt-get install stunnel
สร้างไดเร็กทอรี Stunnel ใน Django Project ของคุณ
คัดลอก openssl.cnf จาก /etc/ssl/openssl.cnf หรือ /usr/lib/ssl/openssl.cnf ไปยัง Stunnel หลีกเลี่ยงการแก้ไขโดยตรงเว้นแต่คุณจะรู้ว่าคุณกำลังทำอะไรอยู่
ค้นหาส่วน [req] หรือ [req] ในชุดส่วน req
x509_extensions = v3_ca
req_extensions = v3_req
x509_extensions และ req_extensions ควรมีอยู่ ถ้าไม่มีให้เพิ่ม หากมีความคิดเห็นให้ยกเลิกการแสดงความคิดเห็น
ค้นหาส่วน [v3_req] ในส่วนนี้เพิ่ม
subjectAltName = @alt_names
ค้นหาส่วน [v3_ca] ในส่วนนี้เพิ่ม
subjectAltName = @alt_names
เราจำเป็นต้องเพิ่มส่วนใหม่ alt_names สามารถเพิ่มได้ทุกที่ ฉันเพิ่มหลังส่วน [v3_ca] สำหรับโลคัลโฮสต์และที่อยู่ IP ของคุณให้เพิ่มดังนี้:
[alt_names]
DNS.1 = localhost
IP.1 = x.x.x.x
IP.2 = 127.0.0.1
เพื่อสร้างคีย์ดำเนินการ
openssl genrsa 1024 > stunnel.key
ในการสร้างใบรับรองที่เข้ารหัส DER ให้ดำเนินการคำสั่งแรกหรือที่สอง
หากคุณได้แก้ไขโดยตรง /etc/ssl/openssl.cnf หรือ /usr/lib/ssl/openssl.cnf
openssl req -new -x509 -nodes -sha1 -days 365 -key stunnel.key > stunnel.cert
หากคุณทำสำเนา openssl.cnf ในไดเร็กทอรี Stunnel
openssl req -new -x509 -nodes -sha256 -days 365 -key stunnel.key -config openssl.cnf > stunnel.cert
ในการสร้างใบรับรองที่ถอดรหัส PEM ดำเนินการ
cat stunnel.key stunnel.cert > stunnel.pem
สร้างไฟล์กำหนดค่าสำหรับ Stunnel ชื่อ dev_https.config โดยมีเนื้อหาต่อไปนี้
#not to use pid
pid=
#path of certificate file
cert = stunnel/stunnel.pem
#version of SSL to use
sslVersion = TLSv1.1
foreground = yes
#log output path
output = stunnel.log
[https]
#listen on port 8443
accept=8443
#tunnel the connection to port 8001
connect=8001
# and close connection automatically after one second
TIMEOUTclose=1
โปรดทราบว่า sslVersion ใช้เวอร์ชัน OpenSSL ที่ใช้โดย python interpreter เหมืองคือ OpenSSL 1.1.1 สำหรับเวอร์ชันนี้ให้ใช้ TLSv1.1 ค้นหาเวอร์ชัน openssl ของคุณและเพิ่มเวอร์ชันที่เกี่ยวข้อง คุณสามารถค้นหาเวอร์ชัน OpenSSL ได้โดยดำเนินการ
python -c "import ssl; print(ssl.OPENSSL_VERSION)"
สร้างสคริปต์ที่เรียกว่ารันเนอร์เวอร์และเพิ่มเนื้อหาด้านล่าง สคริปต์นี้ควรอยู่ในไดเร็กทอรีเดียวกับ Manage.py สคริปต์นี้จะรัน Stunnel สองตัวและ django สองสภาพแวดล้อม หนึ่งสำหรับการเชื่อมต่อ http และหนึ่งสำหรับการเชื่อมต่อ https ปัญหาของรันเนอร์เวอร์ที่ไม่ออกอย่างหมดจด (ตามที่ Evan กล่าวถึง) ได้รับการแก้ไขโดยคำสั่งกับดักซึ่งเรียกใช้ฟังก์ชันการล้างข้อมูล
stunnel4 stunnel/dev_https.config &
stunnel_pid=$!
echo "stunnel pid: $stunnel_pid"
python manage.py runserver 0.0.0.0:8000 &
py_server_bg=$!
echo "BG py server pid: $py_server_bg"
HTTPS=1 python manage.py runserver 0.0.0.0:8001
function cleanup()
{
echo "Cleaning up"
kill $stunnel_pid
kill $py_server_bg
echo "Cleaned"
}
trap cleanup EXIT
ดำเนินการ
chmod a+x runserver
จากคุณ django ดำเนินโครงการ
./runserver
ตอนนี้ถ้าคุณรันคำสั่งการร้องขอ python คำเตือนที่หายไป subjectAltNames จะไม่แสดง นอกจากนี้คำขอ https วอลเลย์ Android ของคุณจะดำเนินการได้ดี
data = {'login_id':'someid'}
headers = {'content-type': 'application/json'}
url = "https://localhost:8443/myauth/check-id/"
r=requests.post(url, data=json.dumps(data), headers=headers,verify='stunnel/stunnel.pem')
ฉันขอขอบคุณ @EvanGrim สำหรับการแก้ปัญหา และขอบคุณ @Friek, @Utku และ @dr Sybren จากความคิดเห็นของพวกเขาฉันใช้ฟังก์ชันล้างข้อมูล
allowed_host
สามารถทำได้ในบรรทัดเดียวด้วย socat:
socat openssl-listen:8443,fork,reuseaddr,cert=server.pem,verify=0 tcp:localhost:8000
โดยที่ 8443 เป็นพอร์ตสำหรับรับฟังการเชื่อมต่อ HTTPS ขาเข้า server.pem คือใบรับรองเซิร์ฟเวอร์ที่ลงนามด้วยตนเองและ localhost: 8000 คือเซิร์ฟเวอร์ HTTP ที่ดีบักที่เปิดตัวตามปกติ
รายละเอียดเพิ่มเติม: http://www.dest-unreach.org/socat/doc/socat-openssltunnel.html
จัดการ SSL / TLS ด้วยพร็อกซีเช่น Nginx แทนที่จะเป็น Django Nginx สามารถตั้งค่าให้รับฟังบนพอร์ต 443 จากนั้นส่งต่อคำขอไปยังเซิร์ฟเวอร์ Django dev ของคุณ (โดยทั่วไปhttp://127.0.0.1:8000
) การกำหนดค่า Nginx สำหรับสิ่งนี้อาจมีลักษณะดังต่อไปนี้:
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;
}
}
นอกจากนี้คุณยังจะต้อง map django-dev.localhost
ไป127.0.0.1
และเพิ่มdjango-dev.localhost
การในALLOWED_HOSTS
settings.py
บน Linux คุณจะต้องเพิ่มบรรทัดต่อไปนี้ใน/etc/hosts
:
127.0.0.1 django-dev.localhost
จากนั้นคุณจะสามารถเข้าถึงไซต์ dev ของคุณได้โดยไปที่https://django-dev.localhost
เบราว์เซอร์ของคุณ (คุณจะต้องข้ามคำเตือนความปลอดภัยของเบราว์เซอร์ของคุณ)