linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • Симулятор
  • База знаний
  • Собеседование
Index
Categories
All entries
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
home/linux/kb/Сеть: L4 и выше/tcp-keepalive

kb/network-l4 ── Сеть: L4 и выше ── intermediate

TCP keepalive

Keepalive шлёт пробы по простаивающему TCP-соединению чтобы поймать мёртвый peer (NAT-таймаут, упавший хост). Дефолт Linux: 7200s простоя, 75s между пробами, 9 проб. Включается через setsockopt(SO_KEEPALIVE).

view as markdownaka: keepalive, tcp-keep-alive, so-keepalive

Зачем keepalive

TCP без трафика не знает, жив ли peer. Если клиент молча выдернул шнур или NAT закрыл маппинг - сервер увидит это только при попытке послать данные. На long-lived соединениях (БД-пулы, WebSocket'ы, очереди) это плохо: тред занят «зомби»-соединением.

Keepalive - системный механизм: после N секунд тишины ядро шлёт «пробный» ACK с устаревшим sequence-number. Если peer жив - вернёт ACK; если мёртв - ничего, и после M проб ядро закрывает сокет с ETIMEDOUT.

Три тюнинга на хост

sysctlдефолтчто
net.ipv4.tcp_keepalive_time7200 (2 ч)сколько секунд тишины до первой пробы
net.ipv4.tcp_keepalive_intvl75интервал между пробами
net.ipv4.tcp_keepalive_probes9сколько проб до объявления мёртвым

Дефолт = 2 часа простоя + 9×75с = ~2 часа 11 минут до закрытия. В 99% сценариев это безумно долго.

Включить keepalive в приложении

Параметр сокета SO_KEEPALIVE - по дефолту выключен. Нужно явно:

python
import socket
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
# Per-socket override (Linux):
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60)   # 60s простоя
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 10)  # 10s между пробами
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 3)     # 3 пробы

Получится: 60 + 3×10 = 90 секунд от тишины до закрытия.

Когда нужно тюнить

  • БД-пулы (PostgreSQL/MySQL): дефолт 2 часа значит что после рестарта БД пул держит «мёртвые» сокеты до первого SQL-запроса. Поставить keepalive 30-60 секунд.
  • WebSocket / gRPC с прокси посередине: NAT/LB закрывают idle обычно через 5-10 минут. Keepalive каждые 30-60 сек спасает.
  • VPN / SSH туннели: то же.
  • API behind cloud LB: AWS NLB закрывает idle через 350с по дефолту.

Keepalive vs application ping

ПодходПлюсыМинусы
TCP keepaliveбесплатно, в ядрене проверяет, что приложение живо - только сокет; не работает через прокси, проксирующий L7
Application pingпроверяет всю цепочку до handler'анадо реализовать, лишний traffic

Для [[websocket|WebSocket]] правильно делать обе - keepalive ловит оборванный TCP, application-ping (frame opcode 0x9) ловит зависший сервер.

Что видно в tcpdump

Keepalive-проба = пакет с seq = current_seq - 1, без payload, флаг ACK. В tcpdump смотри пустой ACK через интервал tcp_keepalive_intvl от предыдущего трафика.

IP 10.0.0.1.443 > 10.0.0.5.34521: Flags [.], ack 100, win 1024, length 0

Заметки

  • Keepalive не сохраняет соединение «живым» в смысле NAT - он шлёт пакеты, и NAT ровно поэтому не таймаутится. То есть меньше tcp_keepalive_time, чем NAT-timeout - и NAT не закроет.
  • На современных Linux есть TCP_USER_TIMEOUT - альтернатива: «закрыть соединение если за N миллисекунд нет ACK на отправленные данные». Часто полезнее keepalive'а, потому что работает и под нагрузкой.

Когда что-то пошло не так

  • Соединение «висит» через 5 минут idle и не закрывается - keepalive выключен, либо tcp_keepalive_time > NAT-timeout
  • Слишком частые пробы шумят - tcp_keepalive_intvl слишком мал, либо TCP_KEEPIDLE = 5 секунд (избыточно)
  • Соединение закрылось за 5 минут хотя трафик идёт - не keepalive, смотри NAT/LB конфиг (idle timeout != keepalive)
  • error: ETIMEDOUT на send() - keepalive отработал, peer мёртв

§ команды

bash
sysctl net.ipv4.tcp_keepalive_time net.ipv4.tcp_keepalive_intvl net.ipv4.tcp_keepalive_probes

Текущие глобальные дефолты keepalive

bash
sudo sysctl -w net.ipv4.tcp_keepalive_time=60

Снизить простой до 60с глобально (нужен ребут или sysctl persist)

bash
ss -tnoH state established | head

Колонка timer показывает keepalive: 'keepalive(45sec,...)' если включён

bash
ss -tnoeH | awk '/keepalive/ {print}'

Только сокеты с активным keepalive timer'ом

§ см. также

  • tcp-handshakeTCP three-way handshakeTCP-соединение открывается тремя пакетами: SYN от клиента, SYN-ACK от сервера, ACK от клиента. После - соединение Established, можно слать данные.
  • tcp-statesTCP states (LISTEN, ESTABLISHED, TIME_WAIT)TCP-сессия проходит через 11 состояний от LISTEN до CLOSED. Самые важные на проде: LISTEN, ESTABLISHED, TIME_WAIT, CLOSE_WAIT.
  • conntrackConntrack - память Linux о всех сетевых соединенияхПодсистема ядра Linux, которая помнит каждое активное соединение. Без неё NAT не развернёт ответ на нужный приватный IP, а фаервол не отличит «новый коннект» от «уже установленного». Видна в `/proc/net/nf_conntrack`.
  • portПорт - как несколько сервисов делят один IP16-битное число (0-65535), идентифицирует **процесс-получатель** на хосте. IP говорит куда (хост), порт - кому (процессу). 80 - HTTP, 443 - HTTPS, 22 - SSH.
  • cmd-iperf3iperf3 - измерение bandwidth`iperf3` - стандартный инструмент замера throughput TCP/UDP между двумя точками. Запускается парой server + client. Не для прода, а для теста сети.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки