Что именно браузер говорит серверу и как убедиться, что сервер настоящий
curlhttps://portal.nevabit.ru:443/course/view.php?idnumber=linux-basics#section-2
└─┬─┘ └───────┬───────┘ └┬┘ └──────┬──────┘ └─────────┬─────────┘ └───┬────┘
схема хост порт путь параметры фрагмент
| Часть | Кто использует |
|---|---|
| Схема | Браузер: какой протокол, порт по умолчанию — 80 для http, 443 для https |
| Хост | DNS — найти адрес; сервер — понять, какой из сайтов на этом адресе нужен (заголовок Host) |
| Путь и параметры | Сервер: что отдать |
Фрагмент #… | Только браузер — на сервер не отправляется |
HTTP — текстовый протокол «запрос — ответ» поверх TCP. Опция -v у curl показывает, что уходит (>) и что приходит (<):
$ curl -v -s -o /dev/null https://nevabit.ru/
...
> GET / HTTP/1.1
> Host: nevabit.ru
> User-Agent: curl/8.14.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx
< Date: Wed, 14 Oct 2026 19:26:42 GMT
< Content-Type: text/html
< Content-Length: 23561
...
Запрос — строка «метод, путь, версия», затем заголовки и пустая строка; у POST после неё идёт тело. Ответ — строка состояния, заголовки, пустая строка и тело (страница, картинка, JSON).
| Метод | Назначение |
|---|---|
GET | Получить ресурс. Не должен ничего менять на сервере |
POST | Отправить данные: форма, создание записи |
PUT, PATCH | Заменить, изменить ресурс (в API) |
DELETE | Удалить (в API) |
HEAD | Как GET, но только заголовки — проверить, есть ли страница |
Первая цифра кода — класс ответа. По коду, ещё не читая страницу, понятно, на чьей стороне проблема.
| Код | Значение | Когда встречается |
|---|---|---|
200 OK | Успех | Страница отдана |
301, 302 | Перенаправление: адрес в заголовке Location | С http на https, сменился адрес страницы |
304 Not Modified | Не изменилось — берите из кэша | Повторная загрузка |
400 | Неверный запрос | Ошибка в данных клиента |
401, 403 | Нужна авторизация / доступ запрещён | Нет входа, нет прав |
404 Not Found | Ресурса нет | Опечатка в адресе, удалённая страница |
500 | Ошибка в приложении на сервере | Смотреть журналы приложения |
502, 504 | Прокси не получил ответ от приложения / не дождался | Приложение за nginx упало или зависло |
503 | Сервис временно недоступен | Перегрузка, обслуживание |
$ curl -sI http://nevabit.ru/ | head -1
HTTP/1.1 301 Moved Permanently
$ curl -sI https://nevabit.ru/no-such-page | head -1
HTTP/1.1 404 Not Found
$ curl -s -o /dev/null -w '%{http_code} %{time_total}s %{remote_ip}\n' https://nevabit.ru/linux-basics/
200 0.550812s 188.120.235.218
Последняя форма — готовая проверка для скриптов мониторинга: код, время ответа и адрес, на который ушёл запрос.
$ curl -sI https://nevabit.ru/
HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html
Content-Length: 23561
Last-Modified: Wed, 14 Oct 2026 18:19:20 GMT
ETag: "6acfc7a8-5c09"
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000
| Заголовок | Смысл |
|---|---|
Host (запрос) | Какой сайт нужен — на одном адресе их может быть сотни |
Content-Type | Тип тела: text/html, application/json, image/png |
Location | Куда перейти при 3xx |
Cache-Control, ETag, Last-Modified | Правила кэширования, версия ресурса |
Set-Cookie / Cookie | Сервер выдаёт метку, браузер возвращает её с каждым запросом — так работает вход на сайт |
Strict-Transport-Security | «Год ходи ко мне только по HTTPS» — защита от подмены на http |
Заголовок Host позволяет проверить сайт напрямую на сервере, минуя DNS, — например, новый сервер до переключения записи:
$ curl -s --resolve nevabit.ru:443:188.120.235.218 -o /dev/null -w '%{http_code}\n' https://nevabit.ru/
200
HTTP передаёт всё открытым текстом: пароль из формы виден любому на пути — в общем Wi-Fi, у провайдера. HTTPS — тот же HTTP внутри шифрованного канала TLS. TLS решает три задачи: конфиденциальность (шифрование), целостность (данные нельзя незаметно изменить) и подлинность (вы говорите именно с nevabit.ru, а не с подменой).
$ curl -v -s -o /dev/null https://nevabit.ru/ 2>&1 | grep '^\*'
* Trying 188.120.235.218:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519MLKEM768 / id-ecPublicKey
* Server certificate:
* subject: CN=nevabit.ru
* start date: Oct 12 08:11:24 2026 GMT
* expire date: Jan 10 08:11:23 2027 GMT
* subjectAltName: host "nevabit.ru" matched cert's "nevabit.ru"
* issuer: C=US; O=Let's Encrypt; CN=YE1
* SSL certificate verify ok.
Клиент и сервер договариваются о версии TLS и шифре, сервер предъявляет сертификат, клиент проверяет его и вместе с сервером вычисляет общий ключ сеанса. Дальше — обычный HTTP, но зашифрованный.
Сертификат связывает имя сайта с открытым ключом сервера и подписан удостоверяющим центром (УЦ). Браузер проверяет: имя совпадает с адресом, срок не истёк, подпись ведёт к корневому сертификату, которому доверяет система.
$ openssl s_client -connect nevabit.ru:443 -servername nevabit.ru -showcerts </dev/null 2>/dev/null | grep -E '^ *[0-9] s:|^ *i:'
0 s:CN=nevabit.ru
i:C=US, O=Let's Encrypt, CN=YE1
1 s:C=US, O=Let's Encrypt, CN=YE1
i:C=US, O=ISRG, CN=Root YE
2 s:C=US, O=ISRG, CN=Root YE
i:C=US, O=Internet Security Research Group, CN=ISRG Root X2
3 s:C=US, O=Internet Security Research Group, CN=ISRG Root X2
i:C=US, O=Internet Security Research Group, CN=ISRG Root X1
s: — кому выдан, i: — кто подписал. Сертификат сайта подписан промежуточным центром Let's Encrypt, тот — корневым. Корневые сертификаты поставляются с ОС и браузером: в Debian — пакет ca-certificates, каталог /etc/ssl/certs. Let's Encrypt выдаёт сертификаты бесплатно на 90 дней с автоматическим продлением — так работает и этот сайт.
| Ошибка | Причина |
|---|---|
| certificate has expired | Сертификат просрочен — не продлили. Или неверное время на клиенте |
| certificate subject name does not match | Сертификат выдан на другое имя: зашли по IP или на поддомен, которого нет в сертификате |
| unable to get local issuer certificate | Сервер не отдал промежуточный сертификат, или корень неизвестен клиенту |
| self-signed certificate in certificate chain | Корень цепочки не входит в доверенные у клиента |
С 2022 года часть иностранных УЦ отзывает и не выдаёт сертификаты российским организациям. Минцифры создало Национальный удостоверяющий центр, корневой сертификат «Russian Trusted Root CA». Им подписаны сайты ряда банков и госсервисов. В стандартные хранилища Debian, Windows и большинства браузеров этот корень не входит:
$ curl -sS -I https://online.sberbank.ru/
curl: (60) SSL certificate problem: self-signed certificate in certificate chain
$ openssl s_client -connect online.sberbank.ru:443 -servername online.sberbank.ru </dev/null 2>/dev/null | openssl x509 -noout -issuer
issuer=C=RU, O=The Ministry of Digital Development and Communications, CN=Russian Trusted Sub CA
Чтобы такие сайты открывались, корневой сертификат устанавливают в систему: скачивают с Госуслуг (раздел о сертификатах безопасности), кладут в /usr/local/share/ca-certificates/ с расширением .crt и выполняют sudo update-ca-certificates. Яндекс Браузер и браузеры на основе отечественных сборок доверяют ему сразу. Это решение организации: добавленный корень позволяет его владельцу выпускать сертификаты на любые сайты, поэтому в корпоративной сети его ставят по политике безопасности, а не по просьбе пользователя.
curl -k, verify=False) в рабочих скриптах. Проверка — единственное, что отличает настоящий сервер от подменённого. Отключать её можно только на минуту, чтобы посмотреть, что сервер отдаёт.curl -sI — заголовки, -v — весь обмен, -w '%{http_code}' — для скриптов, --resolve — в обход DNSupdate-ca-certificates; проверку сертификатов не отключают