Порт 80 закрыт: что делать
Что означает «порт 80 закрыт»
Порт 80 — стандартный TCP-порт протокола HTTP, за ним закреплён весь незашифрованный веб-трафик. Когда вы видите в адресной строке http://example.com, браузер по умолчанию идёт именно на 80-й порт. Поэтому формулировка «порт 80 закрыт» на практике описывает три разных ситуации, и лечатся они по-разному:
| Что происходит | Что на самом деле | Как отличить |
|---|---|---|
| Никто не слушает порт 80 | Веб-сервер не имеет секции listen 80 — порт формально свободен, ядро отвечает RST |
ss -lntp не показывает строку с :80 |
| Слушает, но трафик режется | nginx/Apache запущены, но фаервол хоста или security group облака отбрасывает пакеты | Локально curl работает, снаружи — таймаут |
| Слушает и отвечает, но не тем | Порт открыт, однако отдаёт ошибку или чужой сайт (например, дефолтный vhost) | Снаружи приходит код 4xx/5xx или не тот сертификат |
Путать эти случаи дорого: вы можете полдня править конфиг nginx, тогда как пакеты дропает внешний фаервол, — или наоборот, открывать порт в облаке, когда процесс вообще не запущен.
Важно и другое: «закрыт» — не всегда авария. Часть администраторов сознательно закрывают 80, оставляя только HTTPS, считая HTTP лишним. Ниже разберём, почему это решение почти всегда создаёт проблемы — даже если сайт продолжает открываться по https://.
Почему закрытый 80 ломает редирект HTTP → HTTPS
Редирект с HTTP на HTTPS — это обычный HTTP-ответ. Чтобы браузер получил 301 Moved Permanently и адрес Location: https://…, должен существовать кто-то, кто этот ответ отдаст. Отдаёт его веб-сервер по 80-му порту. Если порта нет, ответить некому.
Получается логический тупик:
- Пользователь открывает
http://example.com(старая закладка, ссылка из письма, бэклинк, QR-код на визитке, документация интеграции). - Браузер пытается установить TCP-соединение на порт 80.
- Соединение не устанавливается — если порт закрыт «в отказ», мгновенно приходит
ERR_CONNECTION_REFUSED; если пакеты дропаются, браузер висит и через десятки секунд показываетERR_CONNECTION_TIMED_OUT. - Никакого 301 не приходит, на HTTPS браузер не переходит. Пользователь видит «Не удаётся получить доступ к сайту».
То есть закрытый 80 не «отключает лишний протокол», а отключает точку входа, через которую браузер узнавал бы, что нужно идти на HTTPS. Зашифрованный порт 443 при этом полностью работоспособен — и это сбивает с толку: сайт жив, SSL-сертификат валиден, а половина старых ссылок и часть посетителей упираются в ошибку. Получается парадоксальная ситуация: сайт доступен по HTTPS, но недоступен по HTTP, и никакого промежуточного состояния не остаётся.
Кто страдает от этого в первую очередь:
- Ссылки в письмах и рассылках. Письма живут годами; шаблоны часто содержат
http://без редиректа на стороне отправителя. - Бэклинки и чужой контент. Вы не контролируете, как вас процитировали.
- Платёжные и партнёрские сервисы. Часть интеграций проверяет
http://-адрес «на живость» до отправки пользователя. - Внутренние сети и старые клиенты. Корпоративные прокси, тонкие клиенты, скрипты на Python/curl без явного
https://. - Мониторинг и внешние проверки. Проверка доступности, настроенная на
http://, начинает показывать падение, хотя с сайтом всё в порядке.
Проверить, как сейчас ведёт себя связка «HTTP → HTTPS», можно двумя способами: глазами через проверку редиректов и вручную из терминала — команды ниже.

Почему закрытый 80 ломает продление Let's Encrypt
Второе последствие — отложенное и поэтому более болезненное. Большинство сертификатов Let's Encrypt выдаются и продлеваются через ACME-проверку типа HTTP-01.
Механика HTTP-01:
- Клиент (certbot и его аналоги) запрашивает у центра сертификации задачу.
- ЦС генерирует случайный токен и сохраняет его у себя.
- Клиент кладёт файл с этим токеном на сервер — обычно в
/.well-known/acme-challenge/<token>. - ЦС снаружи обращается по адресу
http://<ваш-домен>/.well-known/acme-challenge/<token>— то есть строго на порт 80. - Если ЦС получила корректное содержимое файла, владение доменом подтверждено и сертификат выдаётся.
Порт 80 здесь не «рекомендация», а жёсткое требование протокола: HTTP-01 выполняется только по HTTP на порту 80. Если порт закрыт, шаг 4 не проходит, и в логе появляется характерная ошибка:
Challenge failed for domain example.com
http-01 challenge for example.com
Fetching http://example.com/.well-known/acme-challenge/xxxxxxxx: Connection refused
Some challenges have failed.
Сертификат не продлевается. Срок жизни сертификата Let's Encrypt — 90 дней, а продление запускается за 30 дней до истечения. Если порт 80 был закрыт «в рамках оптимизации», сайт продолжит работать примерно два месяца — а потом пользователи получат предупреждение браузера о недействительном сертификате. Это типичный сценарий «всё было хорошо, а сегодня внезапно упало».
Отдельно стоит проверить, не близок ли ваш сертификат к истечению прямо сейчас: проверка срока действия SSL и проверка SSL-сертификата. Развёрнутый разбор причин неудачного продления — в статье Let's Encrypt не продлился.
Что делать, если держать 80 открытым принципиально не хочется:
- DNS-01 — подтверждение через TXT-запись в DNS. Порт 80 не нужен вообще, но требуется API-доступ к DNS-провайдеру или ручное добавление записи.
- TLS-ALPN-01 — подтверждение на порту 443 по специальному расширению ALPN. Требует настроенного веб-сервера и не работает через reverse-proxy, который сам терминирует TLS.
Оба варианта — компромисс: они усложняют автоматизацию и требуют, чтобы её кто-то поддерживал. Универсально дешёвое решение — оставить порт 80 открытым и отдавать с него только редирект и ACME-файлы.

Как проверить, закрыт ли порт 80: пошагово
Начинайте с внешней проверки — именно её видит ЦС и посетитель. Полезно иметь две-три разных точки обзора: локальный терминал, внешний сервис, машина в другой сети.
Шаг 1. Проверка снаружи через curl
curl -I -m 10 http://example.com
Ключ -I запрашивает только заголовки, -m 10 ограничивает ожидание 10 секундами, чтобы не ждать таймаут по умолчанию.
Три возможных сценария и что они означают:
curl: (7) Failed to connect to example.com port 80: Connection refused
Connection refused — на порт прилетел TCP-RST. Значит, до сервера достучались, но слушателя на 80 нет, либо правило фаервола намеренно отвечает отказом (REJECT, а не DROP). Ищите причину в конфиге веб-сервера.
curl: (28) Operation timed out after 10001 milliseconds with 0 bytes received
Таймаут — пакеты уходят в никуда. Так ведёт себя правило DROP в фаерволе или deny в security group облака. То есть на сервере порт может быть открыт и процесс запущен, но снаружи его не видно. Локально такая проверка обычно проходит успешно — это и есть ловушка.
HTTP/1.1 301 Moved Permanently
Location: https://example.com/
Server: nginx
Это корректный рабочий сценарий: порт 80 отвечает, редирект стоит.
Шаг 2. Проверка порта без HTTP
nc -vz example.com 80
Утилита nc (netcat) открывает TCP-соединение и сразу закрывает его — без отправки HTTP-запроса. Полезно, когда нужно понять, работает ли порт как таковой, независимо от конфигурации vhost.
Connection to example.com 80 port [tcp/http] succeeded!
Порт открыт. Если после этого curl отдаёт 404 или чужую страницу — проблема в конфигурации сайта, а не в сети.
nc: connect to example.com port 80 (tcp) failed: Connection refused
Порт закрыт — переходите к разделу «Как открыть порт 80».
Шаг 3. Проверка изнутри сервера
sudo ss -lntp | grep ':80 '
Показывает, есть ли вообще слушающий процесс. Разбираем вывод:
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1337,fd=6))
LISTEN 0 511 [::]:80 [::]:* users:(("nginx",pid=1337,fd=7))
LISTEN— сокет слушает входящие соединения.0.0.0.0:80— приём на всех IPv4-интерфейсах. Это то, что нам нужно.[::]:80— то же для IPv6. Без этой строки IPv6-клиенты и часть внешних проверок получат отказ.users:(("nginx",…))— какой процесс держит порт.
Если вместо 0.0.0.0:80 вы видите 127.0.0.1:80, сервис слушает только loopback. Снаружи порт закрыт, даже если сам процесс работает: так часто ломается конфиг за reverse-proxy или в контейнере без публикации порта. Если строк с :80 нет вообще — веб-сервер не слушает порт, правьте его конфигурацию.
Шаг 4. Проверка ACME-пути
curl -I -m 10 http://example.com/.well-known/acme-challenge/test-token
Перед реальным продлением полезно убедиться, что путь /.well-known/acme-challenge/ отвечает снаружи. Правильный результат — HTTP/1.1 404 Not Found от вашего веб-сервера: файла нет, но порт открыт, редирект его не перехватывает и запрос доходит до нужного места. Если приходит 301 на HTTPS — редирект ловит ACME раньше обработчика, и продление через HTTP-01 упадёт. Если Connection refused — порт 80 закрыт.

Быстрая альтернатива без терминала — проверка порта UptimeChecker: она делает ту же проверку с внешней стороны и показывает, доступен ли порт извне.
Таблица: симптом → причина → решение
| Симптом | Причина | Решение |
|---|---|---|
curl: (7) Connection refused |
Нет слушателя на порту 80, либо правило REJECT |
Добавить listen 80 в конфиг веб-сервера, перезапустить его |
curl: (28) timed out |
Правило DROP в фаерволе или deny в security group |
Разрешить входящий TCP 80 на уровне хоста и облака |
| Локально работает, снаружи — нет | Разница в фаерволе хоста и security group, слушатель только на 127.0.0.1 |
Проверить оба уровня, привязать сервис к 0.0.0.0/[::] |
Из браузера ошибка, nc — «succeeded» |
Слушает дефолтный vhost или другой сервис | Сверить server_name и порядок виртуальных хостов |
| Порт открыт, но редиректа нет | Нет секции return 301, или она перекрыта другим location |
Добавить редирект, проверить порядок правил |
| Редирект есть, но продление падает | ACME-путь перехватывается редиректом на HTTPS | Исключить /.well-known/acme-challenge/ из редиректа |
| Всё работало, через два месяца «сертификат истёк» | Порт 80 закрыли после последнего успешного продления | Открыть 80 либо перейти на DNS-01 |
| Ошибка появляется периодически | Балансировка между серверами, где 80 открыт не везде | Привести конфигурацию всех узлов к общему виду |
ERR_CONNECTION_REFUSED только у части пользователей |
IPv6-клиенты, а [::]:80 не слушает |
Добавить директиву для IPv6 |
Как открыть порт 80
Действовать нужно последовательно: сначала процесс, потом фаервол хоста, потом облако. Открывать всё сразу — верный способ запутаться, что именно помогло.
1. Веб-сервер должен слушать порт
Для nginx добавьте серверный блок, который отвечает на 80-й порт:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location /.well-known/acme-challenge/ {
root /var/www/html;
allow all;
}
location / {
return 301 https://$host$request_uri;
}
}
Проверить конфигурацию и применить без разрыва соединений:
sudo nginx -t && sudo systemctl reload nginx
Для Apache аналог выглядит так:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
</VirtualHost>
Условие RewriteCond исключает ACME-путь из редиректа — это то, что спасает автоматическое продление.
2. Фаервол хоста
Debian/Ubuntu с ufw:
sudo ufw status verbose
sudo ufw allow 80/tcp
Первая команда показывает текущие правила и политику по умолчанию, вторая добавляет разрешение. Если в выводе есть правило deny 80/tcp выше разрешающего, правила применяются сверху вниз — уберите или переставьте.
iptables напрямую:
sudo iptables -L INPUT -n --line-numbers | grep -E 'Chain INPUT|dpt:80'
sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT
Первая команда показывает цепочку INPUT с номерами строк: правило, оказавшееся выше принимающего и имеющее цель DROP/REJECT, и блокирует порт. Вторая вставляет разрешение в начало цепочки. Помните, что правила iptables без iptables-persistent не переживут перезагрузку.
CentOS/RHEL/AlmaLinux с firewalld:
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
--list-all покажет, входит ли http в список разрешённых сервисов зоны; --permanent сохраняет правило после перезагрузки.
3. Security group облака
Если сервер в облаке, помимо фаервола хоста есть внешний уровень: security groups, сетевые ACL, «файрволы» облачного провайдера. Правило проверки простое — убедитесь, что во входящих (ingress) разрешён TCP-порт 80 с источника 0.0.0.0/0 и, если используете IPv6, ::/0. Exact набор интерфейсов отличается у каждого провайдера, но принцип одинаков: два независимых уровня защиты должны пропускать трафик, и блокировать может любой из них.
После правок обязательно повторите шаги проверки из предыдущего раздела снаружи: успешный локальный curl ничего не доказывает.
Особые случаи
Сайт за CDN или обратным прокси
Когда трафик терминируется на стороне CDN, порт 80 на вашем сервере вообще может быть закрыт — это допустимо, если CDN сам отвечает на 80 и делает редирект на HTTPS, а ACME-валидацию вы проходите через DNS-01 или через сам CDN. Ключевое условие: внешняя точка входа на 80 должна существовать и корректно редиректить.
HSTS и «мы всё равно переходим на HTTPS»
Заголовок Strict-Transport-Security заставляет браузер обращаться к домену сразу по HTTPS, и после первого визита HTTP-ссылки действительно будут переписаны на https://. Но HSTS не отменяет необходимость порта 80:
- первый визит всё равно идёт по
http://, пока браузер не увидел заголовок; - предзагрузка (preload) покрывает браузеры, но не скрипты, не
curl, не серверные интеграции; - ACME-проверка HTTP-01 не подчиняется HSTS — сервер сертификации идёт строго на 80-й порт.
Поэтому «у нас HSTS» — не аргумент в пользу закрытия 80-го порта.
Порт 80 отвечает не тем сайтом
Иногда порт открыт, но на запрос приходит дефолтная страница веб-сервера или другой домен: server_name не покрывает нужное имя, либо блок с listen 80 default_server перехватывает запрос раньше. Проверяется командой:
curl -sI -m 10 http://example.com | grep -iE 'server|location|http/'
Если в поле Server или в содержимом виден чужой сайт — правьте порядок виртуальных хостов и наличие default_server у служебного блока.
Что держать под наблюдением
Закрытый 80-й порт — из тех сбоев, которые не дают мгновенной обратной связи. Сайт открывается по HTTPS, посетители приходят по новым ссылкам, поэтому день тишины не значит, что всё в порядке. Ошибка проявляется двумя волнами: сначала часть старых ссылок и проверок перестаёт работать, а через полтора-два месяца истекает сертификат, и проблема становится массовой.
Разумный минимум для профилактики — держать под регулярной внешней проверкой три вещи одновременно: доступность самого сайта (чекер доступности), состояние SSL-сертификата и его срок, и корректность редиректов HTTP → HTTPS. Дополнительно можно смотреть на конфигурацию соседнего порта — в статье Порт 443 закрыт разобраны похожие сценарии для HTTPS, и вместе эти две статьи закрывают весь входной периметр сайта.
Если нужен только разовый ответ на вопрос «доступен ли порт 80 извне и куда он ведёт» — это решается за пару секунд через проверку порта, без захода на сервер и без установки утилит.