15-bo‘lim
TLS va HTTPS
TLS nimani va'da qiladi, qo'l berish bosqichlari, sertifikatlar va ishonch zanjiri, nima shifrlanadi va nima ochiq qoladi.
Ushbu bo‘lim mundarijasi
12-bo'limda HTTP so'rovini ochiq matnda yubordik. Bu shuni anglatadiki, yo'ldagi har bir qurilma uni o'qiy oladi - Wi-Fi nuqtasi, provayder, oradagi marshrutizatorlar.
HTTPS - bu HTTP ning ustiga TLS qatlami qo'shilgani.
TLS uchta narsani va'da qiladi #
| Va'da | Ma'nosi | Usiz nima bo'ladi |
|---|---|---|
| Maxfiylik | Yo'ldagi hech kim o'qiy olmaydi | Parolingiz ochiq ketadi |
| Butunlik | Yo'lda o'zgartirib bo'lmaydi | Sahifaga reklama qo'shiladi |
| Haqiqiylik | Server aynan o'zi ekani tasdiqlanadi | Soxta saytga tushasiz |
Uchinchisi eng ko'p e'tibordan chetda qoladi, lekin u eng muhimi. Shifrlash kim bilan gaplashayotganingizni bilmasangiz, foydasiz: hujumchi bilan xotirjam shifrlangan aloqa qurgan bo'lasiz.
Qo'l berish bosqichlari #
Eng muhim nuqta: shifrlash kaliti tarmoqdan o'tmaydi. Ikkala tomon ochiq ma'lumot almashadi, lekin undan kelib chiqadigan umumiy sirni faqat o'zlari hisoblay oladi. Bu kalit almashuvi "Amaliy kriptografiya" darsligida batafsil ko'rilgan.
TLS serveri va mijozi #
Quyidagi misolda sinov sertifikati yasaladi va u bilan haqiqiy TLS ulanish quriladi:
import os
import ssl
import socket
import subprocess
import tempfile
import threading
ish = tempfile.mkdtemp()
kalit = os.path.join(ish, "kalit.pem")
sert = os.path.join(ish, "sert.pem")
# O'zi imzolagan sertifikat yasaymiz (faqat sinov uchun!)
subprocess.run([
"openssl", "req", "-x509", "-newkey", "rsa:2048",
"-keyout", kalit, "-out", sert, "-days", "1", "-nodes",
"-subj", "/CN=localhost",
], check=True, capture_output=True)
print("sertifikat yasaldi:", os.path.exists(sert))
print("kalit yasaldi :", os.path.exists(kalit))
PORT = 9900
tinglovchi = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tinglovchi.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tinglovchi.bind(("127.0.0.1", PORT))
tinglovchi.listen(1)
server_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
server_ctx.load_cert_chain(sert, kalit)
def server():
xom, _ = tinglovchi.accept()
with server_ctx.wrap_socket(xom, server_side=True) as himoyalangan:
himoyalangan.recv(1024)
himoyalangan.sendall(b"shifrlangan javob")
oqim = threading.Thread(target=server, daemon=True)
oqim.start()
# Mijoz: o'zi imzolagan sertifikatga ishonishi uchun uni beramiz
mijoz_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
mijoz_ctx.load_verify_locations(sert)
xom = socket.create_connection(("127.0.0.1", PORT))
s = mijoz_ctx.wrap_socket(xom, server_hostname="localhost")
s.sendall(b"shifrlangan so'rov")
javob = s.recv(1024)
print()
print("TLS 1.3 ishlatildimi:", s.version() == "TLSv1.3")
print("shifr tanlandimi :", s.cipher() is not None)
sertifikat = s.getpeercert()
nom = dict(x[0] for x in sertifikat["subject"])
print("sertifikat egasi :", nom["commonName"])
print("javob :", javob.decode())
s.close()
oqim.join()
tinglovchi.close()
sertifikat yasaldi: True
kalit yasaldi : True
TLS 1.3 ishlatildimi: True
shifr tanlandimi : True
sertifikat egasi : localhost
javob : shifrlangan javob
E'tibor bering: soket bilan ishlash o'zgarmadi. sendall
va recv xuddi oldingidek. Farqi shundaki, soket
wrap_socket bilan o'ralgan - bu 9-bo'limdagi Dekorator
naqshining aynan o'zi.
-nodes va o'zi imzolagan sertifikat - faqat sinov uchunYuqoridagi buyruqda ikkita narsa bor, ular ishlab chiqarishga mos emas:
| Nima | Nima uchun sinov uchun |
|---|---|
-nodes | Maxfiy kalit parolsiz saqlanadi |
-x509 o'zi imzolagan | Hech kim unga ishonmaydi |
Haqiqiy sayt uchun sertifikatni sertifikat markazi (CA) beradi. Bugun bu bepul va avtomatik: Let's Encrypt kabi xizmatlar buni bir buyruq bilan bajaradi.
Ishonch zanjiri #
Mijoz sertifikatni qanday tekshiradi? U uchta savolga javob izlaydi:
- Sertifikatni ishonchli markaz imzolaganmi?
- Undagi nom men so'ragan nom bilan mos keladimi?
- Muddati tugamaganmi?
Uchalasini ham sinab ko'ramiz:
import os
import ssl
import socket
import subprocess
import tempfile
import threading
ish = tempfile.mkdtemp()
kalit = os.path.join(ish, "k.pem")
sert = os.path.join(ish, "s.pem")
subprocess.run([
"openssl", "req", "-x509", "-newkey", "rsa:2048",
"-keyout", kalit, "-out", sert, "-days", "1", "-nodes",
"-subj", "/CN=localhost",
], check=True, capture_output=True)
PORT = 9901
tinglovchi = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tinglovchi.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tinglovchi.bind(("127.0.0.1", PORT))
tinglovchi.listen(4)
server_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
server_ctx.load_cert_chain(sert, kalit)
def server(nechta):
for _ in range(nechta):
xom, _ = tinglovchi.accept()
try:
with server_ctx.wrap_socket(xom, server_side=True) as h:
h.recv(64)
h.sendall(b"ok")
except ssl.SSLError:
pass # mijoz qo'l berishni rad etdi
except OSError:
pass
oqim = threading.Thread(target=server, args=(3,), daemon=True)
oqim.start()
def sinab_kor(nom, ctx, xost="localhost"):
try:
xom = socket.create_connection(("127.0.0.1", PORT), timeout=5)
s = ctx.wrap_socket(xom, server_hostname=xost)
s.sendall(b"salom")
s.recv(64)
s.close()
print(f" {nom:<34} ULANDI")
except ssl.SSLCertVerificationError as x:
sabab = x.verify_message.split(",")[0]
print(f" {nom:<34} RAD ETILDI")
print(f" {'':<34} sabab: {sabab}")
except ssl.SSLError:
print(f" {nom:<34} RAD ETILDI: TLS xatosi")
print("uchta mijoz, uchta sozlama:")
# 1 - tizimning ishonchli markazlari (bizning sertifikat yo'q)
sinab_kor("tizim ishonchi bilan", ssl.create_default_context())
# 2 - sertifikatimizni ishonchli deb ko'rsatamiz
ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx2.load_verify_locations(sert)
sinab_kor("sertifikat ishonchli deb berildi", ctx2)
# 3 - to'g'ri sertifikat, lekin NOM mos kelmaydi
ctx3 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx3.load_verify_locations(sert)
sinab_kor("nom mos kelmaydi", ctx3, "boshqa-sayt.uz")
oqim.join()
tinglovchi.close()
uchta mijoz, uchta sozlama:
tizim ishonchi bilan RAD ETILDI
sabab: self-signed certificate
sertifikat ishonchli deb berildi ULANDI
nom mos kelmaydi RAD ETILDI
sabab: Hostname mismatch
Uchinchi holat ayniqsa muhim: sertifikat haqiqiy va
ishonchli, lekin u localhost uchun berilgan. Boshqa nom
so'ralganda ulanish rad etildi.
Aynan shu tekshiruv soxta saytlardan himoya qiladi.
Internetda "TLS xatosini qanday tuzatish" degan savolga eng ko'p beriladigan "yechim" - tekshiruvni o'chirish:
| Til | O'chirish usuli |
|---|---|
| Python | ctx.verify_mode = ssl.CERT_NONE |
curl | -k yoki --insecure |
| Node.js | rejectUnauthorized: false |
Buni qilsangiz, TLS ning uchinchi va'dasi butunlay yo'qoladi: shifrlash qoladi, lekin kim bilan shifrlayotganingiz noma'lum.
To'g'ri yechimlar:
| Muammo | To'g'ri yechim |
|---|---|
| Ichki sertifikat | Uni ishonchlilar ro'yxatiga qo'shing |
| Muddati tugagan | Yangilang |
| Nom mos emas | To'g'ri nom bilan qayta bering |
| Zanjir to'liq emas | Serverga oraliq sertifikatni qo'shing |
Oxirgisi juda ko'p uchraydi: brauzerda ishlaydi, lekin
curl yoki mobil ilova xato beradi. Sabab - brauzerda
oraliq sertifikat keshda qolgan bo'ladi.
Nima shifrlanadi, nima yo'q? #
Bu savolga aniq javob berish muhim - ko'pchilik HTTPS ni "hech kim hech narsani ko'rmaydi" deb tushunadi.
MALUMOTLAR = [
("Qaysi IP manzilga ulandingiz", False),
("Qaysi portga ulandingiz", False),
("Ulanish vaqti va davomiyligi", False),
("Uzatilgan ma'lumot HAJMI", False),
("Sayt nomi (SNI, qo'l berishda)", False),
("DNS so'rovi (oddiy DNS da)", False),
("So'ralgan yo'l (/hisobim)", True),
("Sarlavhalar va cookie lar", True),
("Forma va parol", True),
("Javob tanasi", True),
("Holat kodi", True),
]
print(f"{'Ma\'lumot':<34} {'Yo\'lda ko\'rinadimi'}")
print("-" * 56)
for nom, shifrlangan in MALUMOTLAR:
holat = "yo'q - shifrlangan" if shifrlangan else "HA - ochiq"
print(f"{nom:<34} {holat}")
ochiq = sum(1 for _, s in MALUMOTLAR if not s)
print()
print("ochiq qoladigan bandlar:", ochiq)
print("shifrlanadiganlari :", len(MALUMOTLAR) - ochiq)
print()
print("TLS mazmunni yashiradi, ALOQA FAKTINI emas")
Ma'lumot Yo'lda ko'rinadimi
--------------------------------------------------------
Qaysi IP manzilga ulandingiz HA - ochiq
Qaysi portga ulandingiz HA - ochiq
Ulanish vaqti va davomiyligi HA - ochiq
Uzatilgan ma'lumot HAJMI HA - ochiq
Sayt nomi (SNI, qo'l berishda) HA - ochiq
DNS so'rovi (oddiy DNS da) HA - ochiq
So'ralgan yo'l (/hisobim) yo'q - shifrlangan
Sarlavhalar va cookie lar yo'q - shifrlangan
Forma va parol yo'q - shifrlangan
Javob tanasi yo'q - shifrlangan
Holat kodi yo'q - shifrlangan
ochiq qoladigan bandlar: 6
shifrlanadiganlari : 5
TLS mazmunni yashiradi, ALOQA FAKTINI emas
2-bo'limda ko'rgandik: bitta IP da yuzlab sayt turishi mumkin.
Server qaysi sertifikatni yuborishni bilishi kerak. Lekin bu qaror qo'l berishning eng boshida, shifrlash hali yoqilmasdan qabul qilinadi.
Shuning uchun sayt nomi (Server Name Indication) ochiq ketadi.
Buni yopish uchun Encrypted Client Hello ishlab chiqilgan, lekin u hali hamma joyda ishlatilmaydi.
Amaliy xulosa: HTTPS qaysi saytga kirganingizni yashirmaydi - faqat o'sha saytda nima qilganingizni yashiradi.
- TLS server misolini ishga tushiring.
s.cipher()natijasini to'liq chop eting va o'qing.- Sertifikat muddatini (
notAfter) chop eting. - Tekshiruv misolini ishga tushiring.
- To'rtinchi holat qo'shing: muddati o'tgan sertifikat (
-days 0). openssl s_client -connect edu.softromeda.com:443ni ishga tushiring.- Chiqishdan sertifikat zanjirini toping.
- Brauzerda qulf belgisini bosib, sertifikatni ko'ring.
- TLS yashiradigan va yashirmaydigan uchtadan narsani sanang.
- Sertifikat tekshiruvini o'chirish nima uchun xavfli ekanini yozing.
Xulosa #
- TLS uchta narsani beradi: maxfiylik, butunlik va haqiqiylik.
- Haqiqiylik eng muhimi: kim bilan gaplashayotganingizni bilmasangiz, shifrlash foydasiz.
- Shifrlash kaliti tarmoqdan o'tmaydi - u ikkala tomonda alohida hisoblanadi.
- TLS 1.3 qo'l berish bir marta borib-kelishga sig'adi.
- Soket API si o'zgarmaydi - soket shunchaki
wrap_socketbilan o'raladi. - Sertifikat tekshiruvi uch savoldan iborat: kim imzolagan, nom mos keladimi, muddati.
- Nom mos kelmasa ulanish rad etiladi - bu soxta saytlardan asosiy himoya.
- Tekshiruvni hech qachon o'chirmang - bu TLS ning uchinchi va'dasini yo'q qiladi.
- TLS mazmunni yashiradi, aloqa faktini emas: IP, vaqt, hajm va SNI ochiq qoladi.
- HTTPS qaysi saytga kirganingizni emas, o'sha saytda nima qilganingizni yashiradi.
Keyingi bo'limda tarmoq tezligi haqida gaplashamiz: kechikish, o'tkazuvchanlik va tiqilinch nazorati.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.