18-bo‘lim
TLS va HTTPS
Sertifikat nima isbotlaydi, Let's Encrypt bilan avtomatlashtirish, Nginx da TLS sozlash va muddat tugashining oldini olish.
Ushbu bo‘lim mundarijasi
HTTPS ikki narsani beradi: shifrlash (yo'ldagi hech kim o'qiy olmaydi) va shaxsni tasdiqlash (siz haqiqatan ham o'sha serverga ulanganingiz). Ikkinchisi ko'pincha unutiladi, lekin u muhimroq.
Sertifikat nima isbotlaydi #
| Sertifikat turi | Nima tekshiriladi | Narxi |
|---|---|---|
| DV (Domain Validation) | Domenni boshqarasizmi | Bepul (Let's Encrypt) |
| OV (Organization) | Tashkilot mavjudmi | Pullik |
| EV (Extended) | Tashkilot batafsil tekshiriladi | Qimmat |
Ilgari brauzerlar EV sertifikat uchun manzil satrida tashkilot nomini yashil rangda ko'rsatardi. 2019-yildan boshlab Chrome va Firefox bundan voz kechdi - tadqiqotlar foydalanuvchilar bu farqni sezmasligini ko'rsatdi.
Bugun amaliy farq deyarli yo'q: DV ham, EV ham bir xil shifrlash beradi va brauzerda bir xil ko'rinadi.
Veb-sayt uchun Let's Encrypt (DV) yetarli va u bepul. OV/EV faqat ba'zi tartibga solinadigan sohalarda talab qilinadi.
Sinov sertifikati #
Haqiqiy sertifikat olish uchun domen va ochiq server kerak. Mexanizmni tushunish uchun esa o'zimiz imzolagan sertifikat ham yetarli.
[ -f logs/nginx.pid ] && kill -QUIT "$(cat logs/nginx.pid)" 2>/dev/null
sleep 0.3
mkdir -p conf/tls logs html temp
echo "<h1>HTTPS ishlayapti</h1>" > html/index.html
openssl req -x509 -newkey rsa:2048 \
-keyout conf/tls/kalit.pem -out conf/tls/sert.pem \
-days 365 -nodes -subj "/CN=sinov.local" >/dev/null 2>&1
chmod 600 conf/tls/kalit.pem
cat > conf/nginx.conf <<'EOF'
worker_processes 1;
error_log logs/error.log warn;
pid logs/nginx.pid;
events { worker_connections 64; }
http {
access_log logs/access.log;
client_body_temp_path temp;
proxy_temp_path temp/proxy;
fastcgi_temp_path temp/fastcgi;
uwsgi_temp_path temp/uwsgi;
scgi_temp_path temp/scgi;
default_type text/html;
server {
listen 127.0.0.1:8080;
server_name sinov.local;
return 301 https://$host:8443$request_uri;
}
server {
listen 127.0.0.1:8443 ssl;
server_name sinov.local;
ssl_certificate tls/sert.pem;
ssl_certificate_key tls/kalit.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
add_header Strict-Transport-Security "max-age=31536000" always;
root html;
}
}
EOF
Yuqoridagi sozlamada ssl_certificate tls/sert.pem - nisbiy
yo'l, va u sozlama fayli joylashgan katalogga nisbatan
hisoblanadi.
Haqiqiy serverda esa doim mutlaq yo'l yoziladi:
ssl_certificate /etc/letsencrypt/live/softromeda.uz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/softromeda.uz/privkey.pem;
Bu 2-bo'limdagi qoidaning davomi: interaktiv ishda nisbiy yo'l qulay, sozlama fayllarida esa faqat mutlaq yo'l.
Sertifikat ichida nima bor #
openssl x509 -in conf/tls/sert.pem -noout -subject -issuer
subject=CN=sinov.local
issuer=CN=sinov.local
subject va issuer bir xil - demak sertifikatni o'zi
imzolagan (self-signed). Haqiqiy sertifikatda issuer
sertifikat markazi bo'ladi.
openssl x509 -in conf/tls/sert.pem -noout -checkend 86400 \
&& echo "kamida bir kun amal qiladi"
Certificate will not expire
kamida bir kun amal qiladi
| Buyruq | Vazifa |
|---|---|
openssl x509 -in f -noout -text | To'liq mazmun |
-subject -issuer | Kim uchun, kim imzolagan |
-dates | Amal qilish muddati |
-checkend N | N soniyadan keyin tugaydimi |
-fingerprint -sha256 | Barmoq izi |
openssl s_client -connect ... | Ishlab turgan serverdan olish |
Kalit sertifikatga mos kelishini tekshirish:
a=$(openssl x509 -noout -modulus -in conf/tls/sert.pem | openssl sha256)
b=$(openssl rsa -noout -modulus -in conf/tls/kalit.pem 2>/dev/null | openssl sha256)
[ "$a" = "$b" ] && echo "kalit sertifikatga mos"
kalit sertifikatga mos
ssl_certificate_key xatosini tez topadiNginx key values mismatch degan xato bersa, sabab odatda
shu: sertifikat yangilangan, kalit esa eski qolgan (yoki
teskarisi).
Yuqoridagi ikki qatorli tekshiruv aynan shuni aniqlaydi - va u serverni qayta ishga tushirmasdan ishlaydi.
Kalit fayl ruxsati ham muhim: 600 va egasi root.
Yopiq kalit oshkor bo'lsa, sertifikat butunlay ma'nosini
yo'qotadi.
HTTPS ni ishga tushiramiz #
nginx -p "$PWD" -c conf/nginx.conf
sleep 1
curl -sk https://127.0.0.1:8443/
nginx -p "$PWD" -c conf/nginx.conf -s quit 2>/dev/null
<h1>HTTPS ishlayapti</h1>
-k bayrog'i - "sertifikatni tekshirma". Usiz nima bo'ladi:
nginx -p "$PWD" -c conf/nginx.conf
sleep 1
curl -s -o /dev/null -w '%{http_code}' --max-time 3 https://127.0.0.1:8443/
echo " kod=$?"
nginx -p "$PWD" -c conf/nginx.conf -s quit 2>/dev/null
000 kod=60
curl kodi 60 - "sertifikatga ishonib bo'lmadi"15-bo'limdagi jadvalni to'ldiramiz:
| Kod | Ma'no | Sabab |
|---|---|---|
6 | DNS yechilmadi | Domen yo'q |
7 | Ulanib bo'lmadi | Port yopiq |
28 | Taymaut | Paket yutilmoqda |
35 | TLS qo'l siqishi buzildi | Protokol yoki shifr mos kelmadi |
51 | Sertifikatdagi nom mos kelmadi | CN/SAN boshqa domen |
60 | Sertifikatga ishonib bo'lmadi | O'zi imzolagan yoki zanjir to'liq emas |
60 ni ko'rganda birinchi shubha - oraliq sertifikat
yetishmayapti.
Let's Encrypt ikkita fayl beradi:
| Fayl | Ichida nima |
|---|---|
cert.pem | Faqat sizning sertifikatingiz |
fullchain.pem | Sizniki + oraliq sertifikat |
Nginx da doim fullchain.pem ni ko'rsating. cert.pem
ni yozsangiz, brauzerlarning bir qismida ishlaydi (ular
oraliqni keshdan topadi), boshqalarida esa yo'q - va bu
"menda ishlayapti" turidagi eng chalkash xatolardan biri.
HTTP dan HTTPS ga yo'naltirish #
nginx -p "$PWD" -c conf/nginx.conf
sleep 1
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' http://127.0.0.1:8080/sahifa
nginx -p "$PWD" -c conf/nginx.conf -s quit 2>/dev/null
301 https://127.0.0.1:8443/sahifa
$request_uri tufayli yo'l saqlanib qoldi - foydalanuvchi
bosh sahifaga emas, o'zi so'ragan sahifaga tushadi.
rewrite emas, return 301 ishlatingKo'p eski qo'llanmalarda shunday yoziladi:
rewrite ^(.*)$ https://$host$1 permanent;
Bu ishlaydi, lekin return tezroq va aniqroq:
return 301 https://$host$request_uri;
rewrite muntazam ifodani har so'rovda hisoblaydi, return
esa shunchaki javob beradi.
Yana bir xato - yo'naltirishni location ichida yozish
va .well-known yo'lini unutish. Let's Encrypt sertifikatni
yangilash uchun http://sayt.uz/.well-known/acme-challenge/
ga murojaat qiladi. Agar u ham HTTPS ga yo'naltirilsa,
yangilash buzilishi mumkin.
To'g'ri shakl:
server {
listen 80;
server_name softromeda.uz;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
HSTS #
nginx -p "$PWD" -c conf/nginx.conf
sleep 1
curl -skI https://127.0.0.1:8443/ | grep -i 'strict-transport'
nginx -p "$PWD" -c conf/nginx.conf -s quit 2>/dev/null
Strict-Transport-Security: max-age=31536000
Bu sarlavha brauzerga aytadi: "keyingi bir yil davomida bu domenga faqat HTTPS orqali murojaat qil".
max-age=31536000 - bir yil. Brauzer buni eslab qoladi
va sizning saytingizga HTTP orqali umuman ulanmaydi.
Agar sertifikatingiz muddati tugasa yoki HTTPS buzilsa, foydalanuvchilar saytga umuman kira olmaydi - HTTP ga qaytish imkoni yo'q.
Xavfsiz tartib:
| Qadam | max-age |
|---|---|
| 1. Sinov | 300 (5 daqiqa) |
| 2. Ishonch hosil qilgach | 86400 (1 kun) |
| 3. Barqaror ishlagach | 31536000 (1 yil) |
includeSubDomains va preload ni esa juda ehtiyotkorlik
bilan qo'shing: preload ro'yxatiga tushgan domenni
qaytarib olish oylar oladi va u brauzerlarga o'rnatilgan
holda keladi.
Barcha subdomenlar HTTPS da ishlashiga to'liq ishonchingiz
bo'lmasa, includeSubDomains yozmang.
TLS versiyalari #
nginx -p "$PWD" -c conf/nginx.conf
sleep 1
curl -sk --tls-max 1.1 -o /dev/null -w '%{http_code}' --max-time 3 https://127.0.0.1:8443/
echo " kod=$?"
nginx -p "$PWD" -c conf/nginx.conf -s quit 2>/dev/null
000 kod=35
ssl_protocols TLSv1.2 TLSv1.3; tufayli eski protokol
rad etildi - curl kodi 35, ya'ni qo'l siqishi
buzildi.
Server qaysi versiyani tanlaganini ko'ramiz:
nginx -p "$PWD" -c conf/nginx.conf
sleep 1
echo | openssl s_client -connect 127.0.0.1:8443 -brief 2>&1 \
| grep -E '^Protocol version|^Ciphersuite'
nginx -p "$PWD" -c conf/nginx.conf -s quit 2>/dev/null
Protocol version: TLSv1.3
Ciphersuite: TLS_AES_256_GCM_SHA384
| Versiya | Holati |
|---|---|
| SSLv2, SSLv3 | Buzilgan - hech qachon |
| TLS 1.0, 1.1 | Eskirgan, 2021-yildan rasman bekor qilingan |
| TLS 1.2 | Hozircha kerak - eski mijozlar uchun |
| TLS 1.3 | Tavsiya etiladi - tezroq va soddaroq |
TLS shifrlar ro'yxatini qo'lda tanlash - xato qilishning oson yo'li. Mozilla buning uchun generator yuritadi:
| Profil | Kimga |
|---|---|
| Modern | Faqat TLS 1.3, eng qat'iy |
| Intermediate | TLS 1.2 + 1.3 - ko'pchilik uchun to'g'ri tanlov |
| Old | Juda eski mijozlar kerak bo'lsa |
ssl_ciphers ni internetdan ko'chirib olishdan ko'ra,
generatordan olingan Intermediate profilini ishlating
va uni yiliga bir marta yangilang.
Natijani tekshirish uchun ssllabs.com/ssltest yoki
testssl.sh vositasidan foydalaning.
Let's Encrypt #
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d softromeda.uz -d www.softromeda.uz
certbot uch ishni bajaradi: domen sizniki ekanini isbotlaydi,
sertifikat oladi va Nginx sozlamasini o'zi tahrirlaydi.
| Fayl | Nima |
|---|---|
/etc/letsencrypt/live/domen/fullchain.pem | Sertifikat + oraliq |
/etc/letsencrypt/live/domen/privkey.pem | Yopiq kalit |
/etc/letsencrypt/live/domen/cert.pem | Faqat sertifikat - ishlatmang |
Let's Encrypt sertifikatlari atigi 90 kun yashaydi. Bu ataylab: qisqa muddat avtomatlashtirishni majburiy qiladi.
certbot o'rnatilganda systemd taymerini ham qo'shadi:
systemctl list-timers certbot.timer
Uni tekshiring. Eng ko'p uchraydigan nosozlik ssenariysi:
- Sertifikat qo'lda olingan;
- Taymer o'chirilgan yoki
--nginxo'rniga--standaloneishlatilgan; - 90 kundan keyin sayt to'satdan ishlamay qoladi;
- HSTS tufayli foydalanuvchilar HTTP ga ham tusha olmaydi.
Yangilanishni sinash:
sudo certbot renew --dry-run
Bu haqiqiy yangilashni bajarmaydi, lekin butun jarayonni sinab ko'radi. Uni o'rnatgandan keyin darhol bajaring.
Muddat tugashini kuzatish #
openssl x509 -in conf/tls/sert.pem -noout -checkend 2592000 \
&& echo "30 kundan ortiq qoldi" || echo "30 kundan kam qoldi"
Certificate will not expire
30 kundan ortiq qoldi
Bu tekshiruvni skriptga aylantirish oson:
if ! openssl x509 -in /etc/letsencrypt/live/softromeda.uz/fullchain.pem \
-noout -checkend 1209600 >/dev/null; then
logger -t tls-nazorat -p user.warning \
"sertifikat 14 kundan kam qoldi"
fi
19-bo'limda buni systemd taymeri bilan har kuni ishga
tushiramiz.
Fayl emas, haqiqiy ulanish orqali tekshirish ishonchliroq - u Nginx qaysi sertifikatni haqiqatan ham berayotganini ko'rsatadi:
echo | openssl s_client -connect softromeda.uz:443 \
-servername softromeda.uz 2>/dev/null \
| openssl x509 -noout -dates -subject
-servername muhim: bitta IP da bir necha sayt bo'lsa,
usiz siz noto'g'ri sertifikatni olasiz (SNI).
Bu Nginx sozlamasidagi eski yo'l qolib ketgan holatni ham aniqlaydi: faylda yangi sertifikat, serverda esa eski.
Xavfsizlik sarlavhalari #
| Sarlavha | Nimadan himoya qiladi |
|---|---|
Strict-Transport-Security | HTTP ga tushib qolish |
X-Content-Type-Options: nosniff | Brauzer fayl turini taxmin qilishi |
X-Frame-Options: DENY | Saytni iframe ga solish (clickjacking) |
Content-Security-Policy | XSS - eng kuchli, lekin murakkab |
Referrer-Policy | Manzilning boshqa saytga oshkor bo'lishi |
add_header va alwaysadd_header X-Frame-Options DENY always;
always bo'lmasa, sarlavha faqat muvaffaqiyatli javoblarga
qo'shiladi. Xato sahifalarida (404, 500) u yo'qoladi.
Yana bir tuzoq: location blokida bitta add_header yozsangiz,
server darajasidagi barcha add_header lar o'sha blokda
bekor bo'ladi.
Shuning uchun sarlavhalarni bitta joyda - odatda server
blokida - saqlang va location ichida add_header yozishdan
qoching.
openssl req -x509bilan o'zi imzolagan sertifikat yarating.subjectvaissuerni ko'ring - nega bir xil?- Kalit sertifikatga mosligini
modulusorqali tekshiring. - Nginx da HTTPS ni yoqing va
curl -kbilan sinang. -ksiz sinab,60kodini oling.return 301bilan HTTP dan HTTPS ga yo'naltiring.- HSTS sarlavhasini qo'shing va
curl -Ibilan tasdiqlang. --tls-max 1.1bilan eski protokolni sinang -35kodi.s_client -briefbilan tanlangan protokolni ko'ring.-checkendbilan muddat tekshiruvini yozing.
Xulosa #
- Sertifikat domen egaligini isbotlaydi, saytning halolligini emas.
- Veb-sayt uchun bepul DV (Let's Encrypt) yetarli.
- Nginx da doim
fullchain.pem,cert.pememas. curlkodi35- TLS qo'l siqishi,51- nom mos emas,60- ishonch zanjiri.rewriteemas,return 301 https://$host$request_uri..well-known/acme-challenge/ni yo'naltirishdan chiqarib qoldiring.- HSTS ni qisqa
max-agebilan boshlang - uni orqaga qaytarib bo'lmaydi. ssl_protocols TLSv1.2 TLSv1.3- eskilari rad etilsin.- Shifrlarni qo'lda tanlamang - Mozilla Intermediate profilini oling.
- Let's Encrypt 90 kun -
certbot renew --dry-runni darhol sinang.
Keyingi bo'limda zaxira nusxa, rejalashtirilgan vazifalar va
fail2ban ni ko'ramiz.
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.