ERR_TIMED_OUT: чем отличается от ERR_CONNECTION_TIMED_OUT и где искать причину
«Сайт слишком долго не отвечает» — Chrome показывает одну фразу для двух разных кодов: ERR_TIMED_OUT и ERR_CONNECTION_TIMED_OUT. Второй означает, что TCP-соединение не установилось, первый — что запрос застрял на любой другой стадии, от DNS до ожидания ответа бэкенда. Разбираем, где Chromium выставляет код -7, сколько он ждёт на каждой стадии, как одной командой curl увидеть застрявший этап и какие таймауты в nginx, PHP и Cloudflare за это отвечают.
ERR_TIMED_OUT (код -7 в Chromium) — общий таймаут сетевой операции: браузер ждал завершения какого-то этапа запроса дольше отведённого времени и прекратил попытку. В отличие от ERR_CONNECTION_TIMED_OUT (-118), который операционная система возвращает строго на этапе установления TCP-соединения, код -7 возникает на любой стадии: при резолве имени, TLS-рукопожатии, ожидании первого байта ответа или приёме тела. По данным файла net_error_list.h на сентябрь 2026, комментарий к -7 — «операция превысила время ожидания», к -118 — «попытка соединения превысила время ожидания».
Чем ERR_TIMED_OUT отличается от ERR_CONNECTION_TIMED_OUT и других «молчаливых» ошибок
Разница зашита в исходниках Chromium: функция MapConnectError переводит системную ошибку ETIMEDOUT от вызова connect() в ERR_CONNECTION_TIMED_OUT, а общая MapSystemError ту же ETIMEDOUT на установленном сокете — в ERR_TIMED_OUT. Плюс код -7 выставляют собственные таймеры Chromium (класс ConnectJob), ограничивающие резолв, TLS-рукопожатие и подключение через прокси.
| Ошибка | Стадия | Кто чаще виноват | Аналог в curl | След в логах nginx |
|---|---|---|---|---|
| ERR_TIMED_OUT (-7) | Любая: DNS, TLS, ожидание ответа, тело | Бэкенд, дроп пакетов в сети, MTU | exit 28: «Operation timed out … 0 bytes received» после connect, «Connection timed out» на TLS | Ничего (запрос не дошёл) или 499 — клиент не дождался |
| ERR_CONNECTION_TIMED_OUT (-118) | Только TCP connect: SYN без ответа | Файрвол с DROP, маршрут, выключенный сервер | exit 28 «Connection timed out after N ms» или exit 7 | Ничего: nginx SYN не увидел |
| ERR_EMPTY_RESPONSE (-324) | Сервер закрыл соединение, не прислав ни байта | Упавший воркер, return 444 | exit 52 «Empty reply from server» | 444 в access.log, «worker process exited» в error.log |
| ERR_CONNECTION_RESET (-101) | Любая после connect: пришёл TCP RST | Клиент, сеть или сервер поровну | exit 56 «Connection reset by peer», на TLS — 35 | «recv() failed (104)» в error.log или 499 |
| HTTP 504 | Прокси не дождался бэкенда | Бэкенд за nginx, Apache, балансировщиком | exit 0, http_code 504 (с -f — exit 22) | 504, «upstream timed out (110)», upstream_response_time 60.0 |
| Cloudflare 524 | Cloudflare подключился к origin, но не дождался ответа | Бэкенд за Cloudflare | exit 0, http_code 524 | 499 или 200 с request_time больше 125 с |
Правило: -118 означает «пакеты до сервера не доходят или он не слушает», искать надо в файрволе, маршруте и статусе сервиса — это разобрано в статье про ERR_CONNECTION_TIMED_OUT. Код -7 говорит, что соединение чаще всего было, и вопрос в том, на какой стадии оно замолчало.
На какой стадии запрос мог застрять и какая ошибка получится
HTTPS-запрос проходит шесть стадий, и на каждой таймаут выглядит по-разному. Таблица показывает, что увидит Chrome и что покажет curl -w, если запрос замолчал именно здесь (по исходникам Chromium на сентябрь 2026).
| Стадия | Кто ограничивает время | Ошибка в Chrome | Как выглядит в curl -w |
|---|---|---|---|
| 1. DNS-резолв | Резолвер (внутренний код -803); резолв + connect вместе накрыты таймером в 4 минуты | Обычно ERR_NAME_NOT_RESOLVED (-105); ERR_TIMED_OUT — если резолвер завис на 4 минуты | Растёт только time_namelookup; exit 6 или 28 |
| 2. TCP connect | ОС: Linux 127 с (tcp_syn_retries = 6), Windows порядка 20 с; Chromium — 4 минуты на все адреса | ERR_CONNECTION_TIMED_OUT (-118); ERR_TIMED_OUT, если таймер Chromium сработал раньше ОС | time_connect = 0; «Connection timed out after N ms», exit 28 или 7 |
| 3. TLS-рукопожатие | Chromium: kSSLHandshakeTimeout = 30 с | ERR_TIMED_OUT (-7) | time_appconnect = 0; -v обрывается после «Client hello» |
| 4. Отправка запроса | ОС: пакеты не подтверждаются, tcp_retries2 = 15 | ERR_TIMED_OUT (-7), иногда ERR_CONNECTION_RESET | time_pretransfer есть, time_starttransfer = 0 |
| 5. Ожидание первого байта | У Chromium таймера нет; первыми сдаются прокси: nginx 60 с, Cloudflare 125 с | Чаще 504 или 524; ERR_TIMED_OUT — если прокси нет и сервер перестал подтверждать пакеты | time_starttransfer ≈ таймауту прокси, http_code 504/524 |
| 6. Приём тела | Сервер: send_timeout 60 с; ОС на клиенте | CLOSED / RESET, если закрыл сервер; ERR_TIMED_OUT, если канал «умер» | time_total упирается в --max-time; «N out of M bytes received» |
Ключевая цифра — 30 секунд на стадии 3: если ERR_TIMED_OUT стабильно приходит через полминуты, соединение установилось, а TLS-рукопожатие не завершилось. Так выглядят потеря больших пакетов (MTU) и фильтрация, отбрасывающая пакеты после ClientHello.
Что проверить на своём компьютере, если ошибку видите только вы
Если сайт открывается с телефона через мобильный интернет, а на компьютере даёт ERR_TIMED_OUT, источник — между браузером и роутером. Три самых частых: антивирус или VPN, проксирующие HTTPS, слабый Wi-Fi с потерями и неверный MTU, из-за которого мелкие пакеты рукопожатия проходят, а крупные — нет.
# Chrome: полный лог сетевого стека в файл. После воспроизведения # ищите событие CONNECT_JOB_TIMED_OUT и стадию, на которой оно случилось chrome://net-export # Тест MTU: 1472 байта данных + 28 байт заголовков = 1500 ping -f -l 1472 example.com # Windows ping -M do -s 1472 example.com # Linux (macOS: ping -D -s 1472) # Потери на Wi-Fi: 20 пакетов до шлюза (Linux/macOS: ping -c 20) ping -n 20 192.168.1.1 # Windows, от администратора: сброс DNS-кэша и сетевого стека ipconfig /flushdns netsh winsock reset
Ответ «Packet needs to be fragmented» на ping с 1472 байтами означает MTU меньше 1500 на пути: для PPPoE ставят 1492, для туннелей — 1420 и ниже, либо включают MSS clamping на роутере. Если таймаут повторяется на многих сайтах и приходит примерно через 30 секунд, первым отключайте VPN и проверку HTTPS в антивирусе. Тяжёлая страница, которая на мобильной сети получает заголовки и потом «крутится» до таймаута, — вопрос к владельцу сайта: сжатие, разбиение ответа, CDN.
Когда таймаут создаёт сеть: отброшенные пакеты вместо RST
Промежуточный узел может не сбрасывать соединение, а молча отбрасывать пакеты — тогда обе стороны ждут, повторяют отправку и сдаются по таймауту. Так ведут себя файрволы с политикой DROP, NAT, потерявший запись о соединении, и системы фильтрации трафика: по техническим разборам 2026 года, в России ограничение доступа всё чаще реализуется отбрасыванием пакетов на этапе TLS, а не инъекцией RST — пользователь видит ERR_TIMED_OUT через 30 секунд вместо ERR_CONNECTION_RESET.
Симптом для владельца: из одних сетей сайт открывается, из других зависает на рукопожатии, сервер здоров, в логах пусто. Проверка блокировки РКН сверяет домен и IP с реестром по расписанию, а сравнение HTTP-проверок из разных регионов показывает, где трафик перестал проходить.
Что на сервере заставляет запрос молчать
На сервере таймаут рождается там, где запрос принят, но обработчик молчит: кончились воркеры PHP-FPM, запрос к базе ждёт блокировку, бэкенд синхронно ждёт внешний API. Если перед приложением стоит nginx или Cloudflare, пользователь чаще увидит не ERR_TIMED_OUT, а 504 Gateway Timeout или 524 — прокси сдаётся первым. ERR_TIMED_OUT напрямую получают там, где прокси нет или он сам застрял.
| Причина на сервере | Где видно | Что получит клиент |
|---|---|---|
| Кончились воркеры PHP-FPM | php-fpm.log: «server reached pm.max_children setting» | 504 через 60 с; без nginx — долгий TTFB и ERR_TIMED_OUT |
| Блокировка в базе | SHOW PROCESSLIST: «Waiting for … lock»; innodb_lock_wait_timeout = 50 с | TTFB 50+ с, затем 500 или 504 |
| Синхронный вызов внешнего API без таймаута | FPM slowlog: воркер висит в recv(); на Linux I/O не входит в max_execution_time | Ждёт до таймаута прокси: 60 с nginx, 125 с Cloudflare |
| Антибот, fail2ban или rate-limit с DROP | iptables -S / nft list ruleset: DROP по IP; адрес пропал из access.log | Таймаут на connect (-118) или на первом запросе (-7) |
| Мёртвое keep-alive соединение | Сервер или NAT молча закрыл простаивающее соединение, браузер отправил в него запрос | Ошибка «через раз», F5 помогает |
Признак серверной причины — растущее время до первого байта при нормальных connect и TLS. Как его измерять и снижать — в статье про TTFB.
Диагностика: curl -w, логи nginx и tcpdump
Команда curl с форматом -w раскладывает запрос по стадиям. Запускайте её и с проблемного клиента, и с самого сервера: совпадение результатов указывает на сервер, расхождение — на сеть между ними.
curl -o /dev/null -s --max-time 70 \
-w 'dns %{time_namelookup}\ntcp %{time_connect}\n'\
'tls %{time_appconnect}\nttfb %{time_starttransfer}\n'\
'total %{time_total}\nhttp %{http_code}\n' https://example.com/
# пример вывода: медленный бэкенд, nginx отдал 504 ровно через 60 с
dns 0.012
tcp 0.041
tls 0.098
ttfb 60.104
total 60.105
http 504
# пример вывода: TLS не завершился, curl сдался по --max-time
dns 0.011
tcp 0.040
tls 0.000
ttfb 0.000
total 70.001
http 000
curl: (28) Connection timed out after 70001 milliseconds
Ключ --max-time ограничивает всю операцию, --connect-timeout — только соединение (по умолчанию 300 секунд); оба дают код выхода 28, но текст разный: пока соединение не готово (для curl это включая TLS) — «Connection timed out», после отправки запроса — «Operation timed out … bytes received». Ключ --trace-time с -v показывает момент, когда обмен замер.
# Только connect: аналог ERR_CONNECTION_TIMED_OUT $ curl --connect-timeout 5 https://example.com/ curl: (28) Connection timed out after 5001 milliseconds # Где именно замерло: метки времени на каждом шаге $ curl -v --trace-time --max-time 30 https://example.com/ -o /dev/null # пример вывода: после Client Hello тишина 30 секунд 14:02:11.318 * Connected to example.com (203.0.113.10) port 443 14:02:11.320 * TLSv1.3 (OUT), TLS handshake, Client hello (1): 14:02:41.321 * Connection timed out after 30001 milliseconds 14:02:41.321 * closing connection #0 curl: (28) Connection timed out after 30001 milliseconds
На сервере смотрите два поля лога nginx: $request_time (сколько запрос жил в nginx) и $upstream_response_time (сколько ждали бэкенд). Второе упёрлось в 60.0 при статусе 504 — виноват бэкенд. Статус 499 при большом времени — клиент или Cloudflare ушли раньше, чем бэкенд ответил.
# nginx.conf: формат лога с временами
log_format timing '$remote_addr "$request" $status '
'$request_time $upstream_response_time';
access_log /var/log/nginx/access.log timing;
# пример вывода: бэкенд не ответил за fastcgi_read_timeout
198.51.100.7 "GET /export HTTP/1.1" 504 60.002 60.001
# пример вывода: клиент ушёл на 125-й секунде (Cloudflare 524)
198.51.100.7 "GET /report HTTP/1.1" 499 125.318 125.317
# error.log при таймауте бэкенда
grep 'timed out' /var/log/nginx/error.log | tail -5
# пример вывода (одна строка, перенесена)
2026/09/25 14:02:11 [error] 1234#1234: *5678 upstream timed out
(110: Connection timed out) while reading response header from
upstream, client: 198.51.100.7, request: "GET /export HTTP/1.1",
upstream: "fastcgi://unix:/run/php/php8.3-fpm.sock"
# Медленные запросы: request_time больше 10 с
awk '$(NF-1) > 10' /var/log/nginx/access.log | tail -20
Если в логах nginx запросов нет, а клиент видит таймаут, пакеты теряются по пути. Это доказывает tcpdump: повторы одного сегмента без подтверждений. Теряются только сегменты по 1448 байт, мелкие проходят — это MTU.
# Весь обмен с проблемным клиентом на 443-м порту sudo tcpdump -ni eth0 'host 198.51.100.7 and tcp port 443' # пример вывода (сокращён): сервер трижды шлёт один сегмент # 1448 байт, ACK от клиента нет — большие пакеты не доходят 14:05:40.112 203.0.113.10.443 > 198.51.100.7.51301: [P.] seq 1:1449 14:05:40.318 203.0.113.10.443 > 198.51.100.7.51301: [P.] seq 1:1449 14:05:40.730 203.0.113.10.443 > 198.51.100.7.51301: [P.] seq 1:1449 14:05:41.554 203.0.113.10.443 > 198.51.100.7.51301: [P.] seq 1:1449 # Счётчики повторов по живым соединениям без дампа ss -ti dst 198.51.100.7 # пример вывода: retrans:1/4 — четыре повтора, один сегмент в полёте cubic rto:1648 rtt:103/12 unacked:1 retrans:1/4 lost:1 # Одни SYN без SYN-ACK — это уже история про -118, не про -7 sudo tcpdump -ni eth0 'tcp[tcpflags] & tcp-syn != 0 and \ tcp[tcpflags] & tcp-ack == 0'
Симптом → причина → проверка → исправление
| Симптом | Вероятная причина | Как проверить | Как исправить |
|---|---|---|---|
| Ошибка через ~30 с, только из части сетей | Дроп пакетов после ClientHello: фильтрация или файрвол | curl -v --trace-time из разных сетей: обрыв после «Client hello» | Проверить домен и IP в реестре, сменить IP, мониторинг из регионов |
| Мелкие страницы открываются, тяжёлые зависают | MTU меньше 1500 на пути, PMTUD заблокирован | ping -f -l 1472; в tcpdump повторы только сегментов 1448 байт | MSS clamping, пропустить ICMP type 3 code 4 |
| TTFB 60 с и 504 у всех | Бэкенд не успевает: FPM, база, внешний API | $upstream_response_time ≈ 60.0; php-fpm.log; SHOW PROCESSLIST | Больше воркеров, таймауты на вызовы API, индексы, долгие задачи — в очередь |
| Ошибка через раз, F5 помогает | Мёртвое keep-alive соединение через NAT или балансировщик | net-export: запрос ушёл в переиспользованный сокет и завис | keepalive_timeout сервера больше, чем у балансировщика и NAT |
| Таймаут у одного IP на всех страницах, в логах его нет | Бан с DROP: fail2ban, антибот, rate-limit | iptables -S / nft list ruleset, fail2ban-client status | Разбанить, allowlist, для наглядности DROP заменить на REJECT |
Сколько ждёт каждый слой: таймауты по стеку
Пользователю ошибку показывает слой, сдавшийся первым, поэтому цифры стоит знать. Значения по умолчанию на сентябрь 2026 — из документации nginx, PHP, Apache, Cloudflare, ядра Linux и исходников Chromium.
| Слой | Параметр | По умолчанию | Что получит клиент |
|---|---|---|---|
| Chrome | Резолв + TCP connect / TLS-рукопожатие / туннель через прокси | 4 мин / 30 с / 30 с (Android и iOS — 10 с) | ERR_TIMED_OUT |
| Chrome | Ожидание заголовков ответа HTTP/1.1 | Своего таймера нет | 504/524 от прокси, ERR_TIMED_OUT от ОС, ERR_EMPTY_RESPONSE, если сервер закрыл |
| Linux | tcp_syn_retries / tcp_retries2 | 6 (≈127 с) / 15 (не менее 924 с) | ERR_CONNECTION_TIMED_OUT / ERR_TIMED_OUT |
| nginx | proxy_connect_timeout / proxy_read_timeout / proxy_send_timeout / fastcgi_read_timeout | 60s (connect — не более 75) / 60s / 60s / 60s | 504 |
| nginx | send_timeout / client_header_timeout / keepalive_timeout | 60s / 60s / 75s | Обрыв тела; 408; закрытие простаивающего соединения |
| PHP | max_execution_time; request_terminate_timeout (FPM) | 30 (CLI — 0); 0 = выключен | Fatal error → 500; на Linux ожидание I/O в лимит не входит |
| MySQL | innodb_lock_wait_timeout | 50 с | «Lock wait timeout exceeded» → 500 или 504 |
| Apache | Timeout / ProxyTimeout | 60 / равен Timeout | Обрыв соединения / 504 |
| Cloudflare | TCP connect / ACK запроса / Proxy Read Timeout | 19 с / 90 с / 125 с (Enterprise — до 6000 с) | 522 / 522 / 524 |
Как поймать таймаут, который случается раз в час
Плавающие таймауты — пик нагрузки, мёртвое keep-alive, региональный дроп пакетов — разовым curl не ловятся: в момент проверки всё работает. Нужны регулярные запросы из нескольких сетей с историей по каждой точке.
Пруфен выполняет HTTP-проверки с интервалом от 2 минут из 20 точек мониторинга — 17 в России, а также Минск, Астана и Испания. Запрос, не уложившийся в порог ответа, фиксируется как недоступность в конкретной локации; инцидент открывается, когда её подтверждает заданная доля точек. Вкладка «По локациям» и есть диагноз: таймаут из всех точек сразу — медленный бэкенд или упавший сервис, таймаут только из части регионов — сетевой дроп или фильтрация на пути.
Пруфен присылает уведомление в Email, Telegram или Макс, как только проверка перестала проходить, и второе — когда сайт снова ответил. Если ресурс так и не поднялся, подключается голосовой звонок. Время обнаружения равно интервалу проверки. Бесплатный план включает 5 проверок — хватит на главную, тяжёлый отчёт и API.
Частые вопросы
Почему Chrome показывает одинаковый текст для ERR_TIMED_OUT и ERR_CONNECTION_TIMED_OUT?
Страница ошибки строится по группе кодов: оба относятся к «сайт слишком долго не отвечает». Различить их можно по коду мелким шрифтом под текстом или в DevTools на вкладке Network. Для диагностики это важно: -118 ведёт к файрволу и маршруту, -7 — к TLS, бэкенду и потерям на открытом соединении.
Сколько именно ждёт Chrome до ERR_TIMED_OUT?
Зависит от стадии. По исходникам Chromium на сентябрь 2026: 30 секунд на TLS-рукопожатие, 30 секунд на туннель через прокси (10 на Android и iOS), 4 минуты на резолв плюс перебор адресов при TCP-подключении. На ожидание HTTP-ответа собственного таймера нет — раньше сработает ОС или прокси. Поэтому «ровно 30 секунд» — почти всегда TLS, «около минуты и 504» — nginx, «две с лишним минуты» — Cloudflare.
Может ли ERR_TIMED_OUT быть признаком блокировки сайта?
Может: когда фильтрующее оборудование отбрасывает пакеты после ClientHello, браузер видит таймаут на TLS через 30 секунд, а не сброс. Но сам код ничего не доказывает — ту же картину даёт неверный MTU или файрвол хостера. Подтверждение — воспроизводимость из сетей конкретных операторов, чистые логи сервера, проверка домена и IP в реестре.
Поможет ли увеличить max_execution_time в PHP, если страница падает в таймаут?
Обычно нет. В обычных (NTS) сборках PHP на Linux этот лимит считает процессорное время скрипта, а ожидание базы или внешнего API в него не входит — запрос упрётся в fastcgi_read_timeout nginx (60 с) раньше, чем в PHP. Если долгий запрос нужен, поднимать придётся таймаут прокси для конкретного location, а лучше вынести работу в фоновую очередь.