14-bo‘lim

TLS qanday ishlaydi

Oldingi o'n uch bo'lim TLS da birlashadi - qo'l siqish, versiyalar va sozlashdagi xatolar.

🕑 17 daqiqa o‘qish 📄 1 113 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. TLS nimalardan yig'ilgan
  2. Sinov serverini ishga tushiramiz
  3. Tekshiruvsiz ulanish
  4. Protokol versiyalari
  5. Eski versiyalarni rad etish
  6. SNI - bitta IP, ko'p domen
  7. PHP dan TLS bilan ishlash
  8. HTTPS ga majburlash
  9. Sozlashdagi eng ko'p uchraydigan xatolar
  10. Xulosa

TLS (Transport Layer Security) - internetdagi eng ko'p ishlatiladigan kriptografik protokol. https:// ning s harfi aynan shu.

Uning qiziq tomoni shundaki, u yangi hech narsa o'ylab topmaydi. U oldingi bo'limlarda ko'rgan qismlarni birlashtiradi.

TLS nimalardan yig'ilgan #

QismQaysi bo'limda ko'rdik
Kalit almashinuvi (ECDHE)12
Server autentifikatsiyasi (sertifikat + imzo)11, 13
Kalit ajratish (HKDF)6
Ma'lumot shifrlash (AES-GCM / ChaCha20)8
Nonce boshqaruvi9
Butunlik (AEAD tegi)8

TLS - bu yig'ma protokol. Shuning uchun uni tushunish uchun oldingi bo'limlarni bilish yetarli.

Sinov serverini ishga tushiramiz #

Terminal
export LC_ALL=C TZ=UTC

# 13-bo'limdagidek sinov sertifikat markazi va server sertifikati
openssl ecparam -name prime256v1 -genkey -noout -out ca.key 2>/dev/null
openssl req -x509 -new -key ca.key -sha256 -days 3650 \
  -subj "/C=UZ/O=Namuna Lab CA/CN=Namuna Ildiz CA" -out ca.crt 2>/dev/null

openssl ecparam -name prime256v1 -genkey -noout -out srv.key 2>/dev/null
openssl req -new -key srv.key \
  -subj "/C=UZ/O=Namuna/CN=xizmat.namuna.uz" -out srv.csr 2>/dev/null

cat > srv.ext <<'EXT'
subjectAltName=DNS:xizmat.namuna.uz
basicConstraints=critical,CA:FALSE
keyUsage=critical,digitalSignature
extendedKeyUsage=serverAuth
EXT

openssl x509 -req -in srv.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
  -days 90 -sha256 -extfile srv.ext -out srv.crt 2>/dev/null

# Mahalliy TLS serverini ishga tushiruvchi yordamchi
server() {
    openssl s_server -accept "$1" -cert srv.crt -key srv.key \
        ${2:-} -quiet -naccept 1 >/dev/null 2>&1 &
    sleep 0.7
}
Terminal
server 14501

echo | openssl s_client -connect 127.0.0.1:14501 \
    -CAfile ca.crt -servername xizmat.namuna.uz \
    -verify_hostname xizmat.namuna.uz 2>/dev/null \
  | grep -E "^(Protocol|Verify return code)"

wait 2>/dev/null; true
Natija
Protocol: TLSv1.3
Verify return code: 0 (ok)
Nima sodir bo'ldi

Bir necha millisekundda quyidagilar bajarildi:

QadamMa'nosi
1. ClientHelloMijoz qo'llab-quvvatlaydigan versiya, shifrlar va o'z ECDHE ochiq kaliti
2. ServerHelloServer tanlagan shifr va o'z ECDHE ochiq kaliti
3. SertifikatServer o'z sertifikatini yuboradi
4. CertificateVerifyServer maxfiy kaliti bilan imzolaydi
5. FinishedIkkala tomon kalitlarni hisoblaydi va tasdiqlaydi

Diqqat qiling: 4-qadam hal qiluvchi. Server nafaqat sertifikat ko'rsatadi, balki o'sha sertifikatdagi ochiq kalitga mos maxfiy kalitga egaligini isbotlaydi.

Bu bo'lmasa, hujumchi boshqa saytning sertifikatini nusxa qilib ko'rsatishi mumkin bo'lardi (sertifikat ochiq ma'lumot).

TLS 1.3 qo'l siqish - bitta borib-kelish Mijoz Server ClientHello versiyalar · shifrlar · ECDHE ochiq kalit · SNI ServerHello + Certificate + CertificateVerify tanlangan shifr · ECDHE ochiq kalit · sertifikat · imzo Ikkala tomon MUSTAQIL hisoblaydi ECDHE → umumiy sir → HKDF → sessiya kalitlari Finished Finished Shifrlangan ma'lumot (AES-GCM yoki ChaCha20-Poly1305) TLS 1.2 da bu ikki borib-kelish edi. TLS 1.3 da bitta - shuning uchun ulanish sezilarli tezroq.
Kalit almashinuvi va autentifikatsiya bitta qo'l siqishda birlashadi

Tekshiruvsiz ulanish #

Terminal
server 14502

# CAfile ko'rsatilmagan - mijoz zanjirni qura olmaydi
echo | openssl s_client -connect 127.0.0.1:14502 2>/dev/null \
  | grep -E "^Verify return code"

wait 2>/dev/null; true
Natija
Verify return code: 21 (unable to verify the first certificate)
Terminal
server 14503

# Sertifikat boshqa domen uchun
echo | openssl s_client -connect 127.0.0.1:14503 \
    -CAfile ca.crt -verify_hostname boshqa.namuna.uz 2>/dev/null \
  | grep -E "^Verify return code"

wait 2>/dev/null; true
Natija
Verify return code: 62 (hostname mismatch)
Ulanish baribir amalga oshdi

Ikkala holatda ham openssl s_client xatoni ko'rsatdi, lekin ulanishni uzmadi.

Bu juda muhim nuqta: TLS qo'l siqish muvaffaqiyatli bo'lishi mumkin, sertifikat esa yaroqsiz bo'lishi mumkin.

Tekshiruv - mijozning vazifasi:

MijozStandart xulq
BrauzerTekshiradi, xato bo'lsa to'xtatadi
curlTekshiradi, xato bo'lsa to'xtatadi
openssl s_clientTekshiradi, lekin davom etadi (bu vosita)
PHP file_get_contentsTekshiradi (PHP 5.6+)
Ba'zi eski kutubxonalarTekshirmaydi

Oxirgi qatorga ehtiyot bo'ling. Kodingizda ishlatayotgan HTTP mijozi sertifikatni tekshirayotganiga ishonch hosil qiling.

verify_peer va verify_peer_name ni false qilish - shifrlashni saqlab, autentifikatsiyani o'chirish demakdir. Bu esa 12-bo'limdagi o'rtadagi odam hujumiga to'liq ochiq qoldiradi.

Protokol versiyalari #

Terminal
server 14504

echo "--- standart (eng yangi):"
echo | openssl s_client -connect 127.0.0.1:14504 -CAfile ca.crt 2>/dev/null \
  | grep -E "^(Protocol|Cipher)"

wait 2>/dev/null; true
Natija
--- standart (eng yangi):
Protocol: TLSv1.3
Terminal
server 14505

echo "--- TLS 1.2 majburiy:"
echo | openssl s_client -connect 127.0.0.1:14505 -CAfile ca.crt -tls1_2 \
    2>/dev/null | grep -E "    (Protocol|Cipher)  *:"

wait 2>/dev/null; true
Natija
--- TLS 1.2 majburiy:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-ECDSA-AES256-GCM-SHA384
Shifr to'plami nomlarini o'qish

TLS 1.2 dagi nom to'rt qismdan iborat:

KOD
ECDHE-ECDSA-AES256-GCM-SHA384
  |     |      |    |    |
  |     |      |    |    +-- xesh
  |     |      |    +------- rejim (AEAD)
  |     |      +------------ shifr
  |     +------------------- imzo turi
  +------------------------- kalit almashinuvi

TLS 1.3 da esa nom qisqargan:

KOD
TLS_AES_256_GCM_SHA384

Kalit almashinuvi va imzo turi nomda yo'q, chunki TLS 1.3 da ular alohida kelishiladi va tanlov cheklangan:

TLS 1.2TLS 1.3
300 dan ortiq to'plam5 ta
RSA kalit almashinuvi mumkinFaqat ECDHE/DHE
CBC rejimi mumkinFaqat AEAD
Oldinga maxfiylik ixtiyoriyMajburiy
Qayta kelishuv (renegotiation)Olib tashlangan

Tanlovni qisqartirish - TLS 1.3 ning asosiy g'oyasi. Xavfli variantlar shunchaki olib tashlangan.

Eski versiyalarni rad etish #

Terminal
# Server 1.2 dan past versiyani qabul qilmaydi
openssl s_server -accept 14506 -cert srv.crt -key srv.key \
    -min_protocol TLSv1.2 -quiet -naccept 2 >/dev/null 2>&1 &
sleep 0.7

echo "--- TLS 1.0 bilan urinish:"
echo | openssl s_client -connect 127.0.0.1:14506 -CAfile ca.crt -tls1 2>&1 \
  | grep -oE "alert protocol version" | head -1

echo "--- standart bilan urinish:"
echo | openssl s_client -connect 127.0.0.1:14506 -CAfile ca.crt 2>/dev/null \
  | grep -E "^Protocol"

wait 2>/dev/null; true
Natija
--- TLS 1.0 bilan urinish:
alert protocol version
--- standart bilan urinish:
Protocol: TLSv1.3
Qaysi versiyalarni yoqish kerak
VersiyaChiqqan yiliHolati
SSL 2.0, 3.01995, 1996Buzilgan, o'chirilsin
TLS 1.01999Eskirgan (2021 da rasman)
TLS 1.12006Eskirgan
TLS 1.22008Ishonchli, minimal daraja
TLS 1.32018Tavsiya etiladi

nginx uchun:

KOD
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;

Ikkinchi qator qarama-qarshi tuyulishi mumkin, lekin TLS 1.3 da mijozning tanlovi afzal: u o'z uskunasi uchun qaysi shifr tezroq ekanini yaxshiroq biladi (masalan mobil qurilmada ChaCha20).

TLS 1.0 va 1.1 ni o'chirishda ehtiyot bo'ling: juda eski mijozlar (Android 4.x, Windows XP) ulana olmay qoladi. Amalda bu deyarli muammo emas.

SNI - bitta IP, ko'p domen #

Terminal
server 14507

echo "--- SNI bilan:"
echo | openssl s_client -connect 127.0.0.1:14507 -CAfile ca.crt \
    -servername xizmat.namuna.uz 2>/dev/null \
  | grep -E "^(Protocol|Verify return code)"

wait 2>/dev/null; true
Natija
--- SNI bilan:
Protocol: TLSv1.3
Verify return code: 0 (ok)
SNI maxfiy emas

SNI (Server Name Indication) - mijoz qaysi domenga ulanmoqchi ekanini qo'l siqishning eng boshida aytadi.

Bu zarur: bitta IP manzilda yuzlab sayt bo'lishi mumkin va server qaysi sertifikatni yuborishni bilishi kerak.

Muammo shundaki, SNI ochiq matnda ketadi:

Nima yashiringanNima ochiq
So'ralgan sahifa (/hisob/1234)Domen nomi
So'rov va javob tanasiIP manzil
Kukilar, sarlavhalarUlanish vaqti va hajmi

Ya'ni tarmoqni kuzatayotgan tomon qaysi saytga kirganingizni ko'radi, lekin nima qilganingizni ko'rmaydi.

Buni yashirish uchun ECH (Encrypted Client Hello) ishlab chiqilmoqda, lekin u hali hamma joyda qo'llab-quvvatlanmaydi.

PHP dan TLS bilan ishlash #

Terminal
cat > mijoz.php <<'PHP'
<?php
declare(strict_types=1);

// TO'G'RI sozlama - ikkala tekshiruv ham yoqilgan
$togri = [
    'ssl' => [
        'verify_peer' => true,
        'verify_peer_name' => true,
        'cafile' => 'ca.crt',
        'peer_name' => 'xizmat.namuna.uz',
        'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
                         | STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT,
    ],
];

// XATO sozlama - hech qachon shunday yozmang
$xato = [
    'ssl' => ['verify_peer' => false, 'verify_peer_name' => false],
];

foreach (['togri' => $togri, 'xato' => $xato] as $nom => $sozlama) {
    $s = $sozlama['ssl'];
    printf("%-6s verify_peer=%-5s verify_peer_name=%-5s cafile=%s\n",
        $nom,
        var_export($s['verify_peer'], true),
        var_export($s['verify_peer_name'], true),
        $s['cafile'] ?? '(yoq)');
}

echo "\nPHP 5.6 dan boshlab verify_peer standart holda TRUE\n";
echo "Uni false qilish - autentifikatsiyani butunlay ochirish\n";
PHP

php mijoz.php
Natija
togri  verify_peer=true  verify_peer_name=true  cafile=ca.crt
xato   verify_peer=false verify_peer_name=false cafile=(yoq)

PHP 5.6 dan boshlab verify_peer standart holda TRUE
Uni false qilish - autentifikatsiyani butunlay ochirish

HTTPS ga majburlash #

Terminal
cat <<'CONF'
# nginx: barcha HTTP so'rovlarni HTTPS ga yo'naltirish
server {
    listen 80;
    server_name xizmat.namuna.uz;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    http2 on;
    server_name xizmat.namuna.uz;

    ssl_certificate     /etc/ssl/fullchain.pem;
    ssl_certificate_key /etc/ssl/srv.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;

    # HSTS - brauzerga "bu saytga faqat HTTPS bilan kel" deydi
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
CONF
Natija
# nginx: barcha HTTP so'rovlarni HTTPS ga yo'naltirish
server {
    listen 80;
    server_name xizmat.namuna.uz;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    http2 on;
    server_name xizmat.namuna.uz;

    ssl_certificate     /etc/ssl/fullchain.pem;
    ssl_certificate_key /etc/ssl/srv.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;

    # HSTS - brauzerga "bu saytga faqat HTTPS bilan kel" deydi
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
Yo'naltirish yolg'iz o'zi yetarli emas

Foydalanuvchi manzil qatoriga xizmat.namuna.uz deb yozsa, brauzer avval HTTP ga boradi. Aynan o'sha birinchi so'rov himoyasiz.

Yo'lda turgan hujumchi shu paytda yo'naltirishni to'sib, foydalanuvchini o'z soxta saytiga olib ketishi mumkin (SSL stripping).

HSTS shu bo'shliqni yopadi: brauzer sarlavhani bir marta ko'rgach, keyingi safar HTTP ga umuman bormaydi - u to'g'ridan-to'g'ri HTTPS ga o'tadi.

ParametrMa'nosi
max-age=31536000Bir yil davomida eslab qol
includeSubDomainsBarcha subdomenlar uchun ham
preloadBrauzerlar ro'yxatiga kiritish uchun

Birinchi tashrif muammosi preload bilan hal qilinadi: domen brauzerlarga oldindan o'rnatilgan ro'yxatga kiritiladi.

Ehtiyot bo'ling: HSTS ni bekor qilish qiyin. max-age tugagunicha brauzer HTTPS talab qiladi. Sertifikat muddati o'tib qolsa, sayt umuman ochilmaydi.

Shuning uchun kichik max-age (masalan 300) bilan boshlang, hammasi barqaror ishlagach oshiring.

Sozlashdagi eng ko'p uchraydigan xatolar #

Terminal
printf "%-32s %s\n" "XATO" "OQIBATI"
printf "%-32s %s\n" "--------------------------------" "------------------------"
printf "%-32s %s\n" "fullchain emas, faqat sayt serti" "ba'zi mijozlarda xato"
printf "%-32s %s\n" "TLS 1.0/1.1 yoqilgan" "eskirgan shifrlar"
printf "%-32s %s\n" "HSTS yo'q" "SSL stripping mumkin"
printf "%-32s %s\n" "sertifikat qo'lda yangilanadi" "kutilmaganda muddati otadi"
printf "%-32s %s\n" "maxfiy kalit git da" "kalit sizib chiqadi"
printf "%-32s %s\n" "verify_peer => false" "MITM ga toliq ochiq"
printf "%-32s %s\n" "kalit huquqlari 644" "har kim oqiy oladi"
Natija
XATO                             OQIBATI
-------------------------------- ------------------------
fullchain emas, faqat sayt serti ba'zi mijozlarda xato
TLS 1.0/1.1 yoqilgan             eskirgan shifrlar
HSTS yo'q                        SSL stripping mumkin
sertifikat qo'lda yangilanadi    kutilmaganda muddati otadi
maxfiy kalit git da              kalit sizib chiqadi
verify_peer => false             MITM ga toliq ochiq
kalit huquqlari 644              har kim oqiy oladi
Amaliy topshiriq
  1. Sinov sertifikati bilan mahalliy TLS serverini ishga tushiring.
  2. openssl s_client bilan ulaning va protokol hamda tekshiruv kodini yozing.
  3. -CAfile siz ulaning - tekshiruv kodi qanday o'zgardi?
  4. Noto'g'ri domen ko'rsatib ulaning.
  5. -tls1_2 bilan ulanib, shifr to'plami nomini qismlarga ajrating.
  6. Serverga -min_protocol TLSv1.2 qo'shing va TLS 1.0 bilan ulanishga urinib ko'ring.
  7. TLS 1.2 va 1.3 dagi shifr to'plami nomlarini solishtiring.
  8. SNI nima uchun ochiq ketishini tushuntiring.
  9. PHP da verify_peer va verify_peer_name farqini yozing.
  10. HSTS ni kichik max-age bilan boshlash nima uchun tavsiya etilishini yozing.

Xulosa #

  • TLS yangi kriptografiya o'ylab topmaydi - u oldingi bo'limlardagi qismlarni birlashtiradi.
  • TLS 1.3 qo'l siqishi bitta borib-kelishda tugaydi.
  • Server sertifikat ko'rsatibgina qolmay, maxfiy kalitga egaligini imzo bilan isbotlaydi.
  • Qo'l siqish muvaffaqiyatli bo'lishi, sertifikat esa yaroqsiz bo'lishi mumkin.
  • Sertifikatni tekshirish - mijozning vazifasi; verify_peer ni o'chirmang.
  • TLS 1.3 da shifr to'plamlari 300 dan 5 taga qisqargan va oldinga maxfiylik majburiy.
  • Minimal versiya sifatida TLS 1.2 ni qo'ying, 1.0 va 1.1 ni o'chiring.
  • SNI ochiq matnda ketadi: kuzatuvchi qaysi domenga kirganingizni ko'radi.
  • Server to'liq zanjirni (fullchain) yuborishi shart.
  • HSTS birinchi HTTP so'rovidagi bo'shliqni yopadi, lekin uni bekor qilish qiyin.

Keyingi bo'limda kriptografiyaning poydevori - xavfsiz tasodifiylik haqida gaplashamiz.

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.