Сокеты и соединения: ss и netstat

Рейтинг: 64.6% · 12 голосов
Подробный курс по диагностике и производительности Linux для админов и DevOps: с чего начать, методология USE, логи (journalctl, dmesg), процессы, CPU, память и OOM, диск и IO (iostat), сеть (ss, tcpdump), системные вызовы и strace, ltrace, perf, флеймграфы, ftrace, eBPF и bpftrace, lsof, мониторинг. Разбор каждого инструмента с чтением вывода.
Ответить
Аватара пользователя
Dmitry_SRE
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Сокеты и соединения: ss и netstat

Сообщение Dmitry_SRE »

Оглавление курса (47)
  1. С чего начать диагностику Linux: методология вместо паники
  2. Первые 60 секунд: экспресс-диагностика нагруженного сервера
  3. Методологии диагностики: USE, RED и здравый смысл
  4. Логи systemd через journalctl: где искать причину
  5. Где лежат логи Linux: /var/log, dmesg и rsyslog
  6. Источники правды: load average, /proc и /sys
  7. Процессы Linux: ps, pstree и состояния процессов
  8. Интерактивный мониторинг: top и htop
  9. Метрики процессов во времени: pidstat
  10. Приоритеты и ограничения: nice, ionice, cgroups
  11. Сигналы и зависшие процессы: kill, и что делать с D-state
  12. Загрузка CPU: user, system, iowait, steal и контекст-свитчи
  13. Диагностика CPU по ядрам: vmstat и mpstat
  14. Профилирование CPU: perf top и поиск пожирателя
  15. Частоты, троттлинг и NUMA: turbostat и numastat
  16. Память Linux: RSS, VSZ, page cache и миф о нехватке памяти
  17. Сколько памяти занято: free, /proc/meminfo и vmstat
  18. Поиск утечек и пожирателей памяти: smem, pmap, smaps
  19. Swap и подкачка: swapon, swappiness, когда своп - это боль
  20. OOM killer: кто и за что убил процесс
  21. Память ядра и slab: slabtop и куда уходит RAM
  22. Подсистема ввода-вывода: путь запроса от приложения до диска
  23. Диагностика диска: iostat и чтение await, %util
  24. Кто грузит диск: iotop и атрибуция io процессам
  25. Файловые системы: df, du, иноды и куда делось место
  26. Глубокая диагностика блочного слоя: blktrace и biolatency
  27. Кеш страниц и грязные данные: dirty pages, fsync, drop_caches
  28. Сетевой стек Linux: путь пакета и где возникают задержки
  29. Сокеты и соединения: ss и netstat (вы здесь)
  30. Захват трафика: tcpdump для диагностики сети
  31. Задержки и потери в сети: ping, mtr, диагностика латентности
  32. Сеть как источник проблем: nftables, conntrack, дропы
  33. Что такое системный вызов и зачем его трассировать
  34. strace: трассировка системных вызовов на практике
  35. strace в бою: почему программа висит, падает или тормозит
  36. ltrace: трассировка вызовов библиотек
  37. Накладные расходы трассировки и безопасные альтернативы
  38. perf: универсальный профайлер Linux
  39. Флеймграфы: визуализация профиля производительности
  40. Трассировка ядра: ftrace и trace-cmd
  41. eBPF: революция в наблюдаемости Linux
  42. Инструменты eBPF на практике: BCC и bpftrace
  43. lsof: открытые файлы, дескрипторы, кто держит файл и порт
  44. Разбор кейса: приложение тормозит - пошаговая диагностика
  45. Непрерывный мониторинг: sar, node_exporter, Grafana, Zabbix
  46. Диагностика в контейнерах: cgroups, лимиты, Docker и Kubernetes
  47. Карта инструментов и сквозной разбор инцидента производительности
Сервис лёг, в логах тишина, а наружу торчит загадочное "address already in use". Или наоборот: приложение медленно жрёт память и файловые дескрипторы, а в коде вроде всё чисто. Очень часто корень такой беды не в самом процессе, а в его сетевых сокетах - кто слушает порт, кто к кому подключён, и сколько соединений зависло в странных состояниях. В этом уроке разберёмся, как за пару секунд увидеть всю сетевую картину машины. Главный герой - команда ss (это буквально "socket statistics"), современная и очень быстрая. Заодно вспомним старичка netstat, которого ты ещё встретишь на чужих и старых серверах. Всё актуально на 2026 год: ss из пакета iproute2 - это стандарт де-факто на любом Linux с systemd.

Почему ss linux вытеснил netstat

Раньше все админы жили на netstat. Проблема в том, что netstat читает сетевое состояние из текстовых файлов в /proc (вроде /proc/net/tcp), парсит их построчно, и на нагруженном сервере с десятками тысяч соединений это работает медленно, подтормаживает и даёт неполную картину. Команда ss обращается к ядру напрямую через специальный сокет-интерфейс netlink (семейство NETLINK_SOCK_DIAG) и выдаёт ту же информацию в разы быстрее, плюс умеет фильтровать на стороне ядра. Поэтому правило простое: на современном Linux используй ss, а netstat держи в голове как запасной вариант для старых систем, где iproute2 может оказаться без свежих фич, или где вообще стоит только net-tools.

Чтобы понимать вывод, нужно знать про сокеты linux одну базовую вещь. Сокет - это конечная точка сетевого соединения, "розетка", в которую воткнут процесс. Слушающий (LISTEN) сокет сидит на каком-то порту и ждёт входящих. Установленное (ESTABLISHED) соединение - это уже воткнутый кабель между двумя розетками: твоим адресом-портом и адресом-портом на той стороне. Вся диагностика крутится вокруг двух вопросов: кто слушает порт и кто куда подключён. Третий, более тонкий вопрос - в каком состоянии соединения и не копится ли что-то нездоровое.

Изображение

Базовые команды ss: кто слушает порт

Самая частая задача - узнать, кто слушает порт. Команда ss linux решает её так:

Код: Выделить всё

sudo ss -tlnp
Флаги читаются по буквам: t - только TCP, l - только слушающие (listening) сокеты, n - не резолвить порты и адреса в имена (показывать числа, так быстрее и не блокируешься на DNS), p - показать процесс (имя, PID и номер файлового дескриптора). Sudo нужен, чтобы увидеть чужие процессы; без него колонка с процессом для не своих сокетов будет пустой. Вывод:

Код: Выделить всё

State   Recv-Q  Send-Q  Local Address:Port   Peer Address:Port  Process
LISTEN  0       4096    0.0.0.0:80           0.0.0.0:*          users:(("nginx",pid=812,fd=6))
LISTEN  0       4096    [::]:80              [::]:*            users:(("nginx",pid=812,fd=8))
LISTEN  0       128     127.0.0.1:5432       0.0.0.0:*          users:(("postgres",pid=940,fd=5))
Читаем по колонкам. Local Address:Port - где висит сокет. 0.0.0.0:80 значит "на всех IPv4-интерфейсах, порт 80" (доступен извне), [::]:80 - то же самое для IPv6, а 127.0.0.1:5432 - только на локалхосте (снаружи не достучаться, и это правильно для базы данных). Peer Address:Port у слушающего всегда вида 0.0.0.0:* или [::]:* - партнёра пока нет. Process - тот самый ответ "кто занял порт": nginx с pid 812 и дескриптором fd=6. Если порт занят, а ты не знаешь кем - это и есть та команда. Подсказка: чтобы быстро спросить про один порт, добавь фильтр - sudo ss -tlnp sport = :80 покажет только тех, кто слушает 80-й.

Теперь все TCP-соединения с разбивкой по состояниям:
Флаг a - all (и слушающие, и установленные). В первой колонке State увидишь LISTEN, ESTAB, TIME-WAIT, CLOSE-WAIT и прочие. А чтобы не считать строки глазами, есть сводка:

Код: Выделить всё

Total: 1843
TCP:   1722 (estab 210, closed 1450, orphaned 0, timewait 1448)

Transport Total     IP        IPv6
RAW       0         0         0
UDP       12        8         4
TCP       272       250       22
INET      284       258       26
Здесь estab - живые установленные соединения, timewait - сколько штук в состоянии TIME-WAIT, orphaned - соединения без привязанного процесса (часто признак того, что приложение упало, а ядро ещё доживает сокеты). Если timewait огромный, а estab маленький - это сигнал, к нему вернёмся ниже.

Состояния TCP linux: что норма, а что тревога

Соединение TCP проходит через несколько состояний, как через шлагбаумы. Знать tcp состояния linux важно: по ним диагностируют половину сетевых проблем. Полный список ss такой: established, syn-sent, syn-recv, fin-wait-1, fin-wait-2, time-wait, closed, close-wait, last-ack, listening, closing. На практике чаще всего смотришь на эти:
  • LISTEN - сокет ждёт входящих. Норма для серверного процесса.
  • ESTAB (ESTABLISHED) - соединение установлено, данные ходят. Норма, рабочее состояние.
  • SYN-SENT / SYN-RECV - идёт рукопожатие. Если их много и они залипают - проблема на установке соединения (фаервол молча режет, потери пакетов, SYN-флуд).
  • TIME-WAIT - сторона, которая закрыла соединение первой, ждёт примерно 60 секунд (фиксированный в ядре 2*MSL), чтобы добить хвосты пакетов и не перепутать старое соединение с новым на том же порту. Это нормальная часть протокола. Тысячи TIME-WAIT на сервере, который делает много коротких исходящих запросов (например, к API или к базе по новому соединению на каждый запрос), - не баг сам по себе, но намёк, что стоит включить keep-alive или пул соединений.
  • FIN-WAIT-1 / FIN-WAIT-2 / LAST-ACK / CLOSING - промежуточные стадии закрытия. Сами по себе мелькают, но если массово залипают - сеть теряет пакеты закрытия.
  • CLOSE-WAIT - вот это почти всегда баг приложения. Оно означает: вторая сторона уже закрыла соединение (прислала FIN), ядро это подтвердило, но твоё приложение так и не вызвало close() на своём сокете. Соединение висит мёртвым грузом. Если CLOSE-WAIT копится и не уходит - в коде где-то забыли закрыть сокет, и ты медленно течёшь по файловым дескрипторам, пока не упрёшься в лимит (потом получишь "Too many open files").
Запомни разницу простыми словами: TIME-WAIT - "я закрыл и вежливо подождал" (норма, уйдёт сам). CLOSE-WAIT - "мне закрыли, а я не отреагировал" (мой косяк, сам не уйдёт). Растущий CLOSE-WAIT - повод идти в код приложения.

Отфильтровать по состоянию очень удобно прямо через ss:

Код: Выделить всё

ss -tan state close-wait
ss -tan state time-wait
ss -tan state established '( dport = :443 or sport = :443 )'
А посчитать, сколько подвисло, и следить за ростом:

Код: Выделить всё

watch -n 2 'ss -Htan state close-wait | wc -l'
Флаг H убирает строку заголовка, чтобы wc -l считал только соединения. Если число растёт минута за минутой - диагноз "приложение не закрывает сокеты" подтверждён.

Recv-Q и Send-Q: где затык

Две колонки, которые новички пролистывают, а зря - именно они показывают насыщение. И читаются они совершенно по-разному для слушающих и для установленных сокетов, это ключевой нюанс.

Для ESTABLISHED: Recv-Q - сколько байт пришло в приёмный буфер ядра, но приложение ещё не прочитало (не успело забрать через read/recv). Send-Q - сколько байт мы отправили, но другая сторона ещё не подтвердила (ACK). Если Recv-Q стабильно большой - приложение не успевает читать данные, тормозит обработка (упёрлись в CPU, в блокировку, в медленную бизнес-логику). Если большой Send-Q - данные не уходят: затык в сети, переполнено окно получателя или он не подтверждает.

Для LISTEN эти колонки значат совсем другое, и это супер-полезно. Recv-Q - сколько уже полностью установленных соединений лежит в accept-очереди и ждёт, пока приложение вызовет accept(). Send-Q - максимальный размер этой accept-очереди (тот самый backlog, равный минимуму из аргумента listen() в приложении и ядерного net.core.somaxconn). Смотри вывод выше: у nginx Send-Q равен 4096 - это лимит очереди. Важно: это именно accept-очередь готовых соединений, а не SYN-очередь полуоткрытых (та отдельная и регулируется net.ipv4.tcp_max_syn_backlog).

Что происходит при переполнении: если в Recv-Q у слушающего сокета число близко к Send-Q или равно ему - приложение не успевает вызывать accept(), очередь забита. Ядро тогда либо отбрасывает завершающий ACK от клиента (и клиент уходит в ретрансмит), либо роняет соединение. С клиента это выглядит как таймауты и подвисания "на ровном месте" при формально живом сервере. Счётчик таких отбросов виден в nstat -az TcpExtListenOverflows (или ListenDrops) - если он растёт, упираешься именно в backlog. Лечение: поднять somaxconn (на 2026 значение по умолчанию в свежих ядрах - 4096, на старых 128 и это часто мало), увеличить backlog в самом приложении и разобраться, почему оно медленно принимает соединения.

Фильтры можно комбинировать - по порту, адресу, состоянию:

Код: Выделить всё

ss -tn dport = :443
ss -tn sport = :80
ss -tn dst 10.0.0.5
ss -tn dst 10.0.0.0/24 dport = :5432
dport - порт назначения (куда мы подключены), sport - наш локальный порт, dst - адрес назначения, src - наш адрес. Так быстро отвечаешь на "кто куда подключён": например, ss -tn dport = :5432 покажет все живые соединения к Postgres. Полезные добавки на 2026: флаг -o (или --options) дорисует таймеры, -e даст расширенную инфу (uid, inode сокета), -m покажет память буферов сокета, а -i - внутренние TCP-метрики (rtt, cwnd, retrans, congestion control), это уже почти как мини-tcpdump без захвата трафика.

netstat для совместимости и связка с другими инструментами

Зашёл на старый сервер, а ss ведёт себя странно или хочется привычного формата - тогда netstat linux выручает. Прямые аналоги:

Код: Выделить всё

netstat -tlnp     # кто слушает (как ss -tlnp)
netstat -tan       # все TCP (как ss -tan)
netstat -s         # статистика протоколов (ss -s короче, nstat точнее)
Флаги почти те же. На многих минималистичных образах netstat живёт в пакете net-tools, который ставят отдельно (apt install net-tools или dnf install net-tools), - ещё одна причина, почему ss удобнее: он есть из коробки в составе iproute2. В Astra Linux и RED OS картина та же: ss доступен сразу, netstat иногда надо доустановить.

ss редко работает в одиночку. Типичные связки: lsof -i :PORT и fuser PORT/tcp - альтернативный способ узнать процесс на порту; ip (тоже iproute2) - для адресов и маршрутов; nstat и /proc/net/snmp - для счётчиков ретрансмитов и отбросов; ss -i вместе с tcpdump - когда надо понять, тормозит сеть или приложение. На 2026 для глубокой диагностики latency соединений в проде всё чаще берут eBPF-инструменты из пакета bcc и bpftrace (например tcpconnect, tcpretrans, tcplife, tcptracer) - они показывают события установки и закрытия соединений в реальном времени с PID и временем жизни, чего ss как срез "здесь и сейчас" дать не может. ss остаётся идеальным первым шагом, eBPF - следующим, когда нужен поток событий, а не моментальный снимок.

Грабли и заблуждения
  • Запустил ss без sudo и удивляешься пустой колонке Process. Имена процессов чужих пользователей видны только под root.
  • Перепутал sport и dport в фильтре и не понял, почему вывод пустой. sport - твой локальный порт, dport - удалённый.
  • Решил, что TIME-WAIT - это утечка, и кинулся крутить ядерные параметры. Нет: TIME-WAIT уходит сам примерно за минуту, это норма протокола. И отдельно: НЕ включай net.ipv4.tcp_tw_recycle - этот параметр сломан для NAT и вообще удалён из ядра начиная с версии 4.12 (на любом современном Linux 2026 года его просто нет). Если реально упёрся в нехватку портов на клиенте, делающем тьму исходящих, правильные шаги - connection pooling и keep-alive, расширение net.ipv4.ip_local_port_range, и аккуратно tcp_tw_reuse (только для исходящих). Опасен растущий CLOSE-WAIT - вот его и лови.
  • Забыл флаг n и ждёшь вывод секунды, потому что ss пытается резолвить каждый адрес и порт через DNS, а если DNS тупит - команда подвисает. На диагностике почти всегда ставь n.
  • Думаешь, что Recv-Q у LISTEN и у ESTAB - это одно и то же. Нет: у LISTEN это accept-очередь и backlog, у ESTAB - непрочитанные и неподтверждённые байты. Перепутаешь смысл - сделаешь неверный вывод.
  • Считаешь, что ss -s в строке TCP показывает все сокеты. timewait там может не входить в estab, а closed - это не "закрытые навсегда", а сокеты в процессе закрытия и orphaned. Для точных счётчиков протокола бери nstat.
Мини-лаба: повтори руками прямо сейчас
  • Выполни sudo ss -tlnp и найди, какой процесс слушает какой порт. Найди хотя бы один сокет на 127.0.0.1 (только локально) и один на 0.0.0.0 или [::] (наружу). Посмотри в колонку Send-Q - какой backlog у твоего веб-сервера?
  • Запусти ss -s и посмотри на estab и timewait. Прикинь соотношение - если timewait в разы больше estab, у тебя много короткоживущих соединений.
  • Открой в браузере любой сайт, тут же выполни ss -tnp dport = :443 - увидишь живые ESTABLISHED-соединения к нему с процессом-браузером.
  • Сосчитай зависшие соединения: ss -Htan state close-wait | wc -l. В норме на свежей системе будет 0.
  • Глянь внутренности живого соединения: ss -tin dport = :443 - найди rtt и cwnd, прикинь задержку до сервера без всякого ping.
  • Если есть netstat, сравни netstat -tlnp и ss -tlnp - убедись, что данные те же.
Контрольные вопросы
  • Какими флагами ss показать слушающие TCP-сокеты вместе с процессами, и зачем тут sudo?
  • Чем CLOSE-WAIT принципиально отличается от TIME-WAIT и какое из них указывает на баг в приложении?
  • Что означают Recv-Q и Send-Q у сокета в состоянии LISTEN, чем эта очередь отличается от SYN-очереди, и при каком соотношении сервер начнёт терять входящие соединения?
  • Как через ss отфильтровать все соединения к удалённому порту 5432, и почему включать tcp_tw_recycle для борьбы с TIME-WAIT в 2026 - плохая идея?
Что запомнить
ss - твой основной инструмент по сокетам, netstat - запасной для старых машин. ss -tlnp отвечает "кто слушает порт", ss -tan и ss -s дают общую картину по состояниям, ss -i заглядывает внутрь TCP. TIME-WAIT - норма и уходит сам; tcp_tw_recycle давно удалён из ядра, не трогай его. Растущий CLOSE-WAIT - баг приложения и утечка дескрипторов. Recv-Q/Send-Q у LISTEN - это accept-очередь готовых соединений и её лимит (backlog), а не SYN-очередь; их переполнение = тихая потеря соединений и таймауты у клиентов, смотри TcpExtListenOverflows. У ESTAB те же колонки значат непрочитанные и неподтверждённые байты. Всегда добавляй n, чтобы не висеть на DNS. А для потока событий "кто и когда соединялся" на 2026 переходи от снимка ss к eBPF-инструментам tcpconnect, tcplife и tcpretrans.
👍3 ❤️3 🔥1 😄 🤔1
Аватара пользователя
go1
Сообщения: 1
Зарегистрирован: 21 май 2026, 22:32

Re: Сокеты и соединения: ss и netstat

Сообщение go1 »

Спасибо, наконец дошло про Recv-Q у LISTEN и что это именно accept-очередь, а не SYN. У меня nginx иногда отдаёт таймауты под нагрузкой, пойду гляну Send-Q и заодно nstat по ListenOverflows. А то я грешил на сеть.
👍1 ❤️ 🔥1 😄 🤔2
Аватара пользователя
pasha1
Сообщения: 1
Зарегистрирован: 15 май 2026, 06:53

Re: Сокеты и соединения: ss и netstat

Сообщение pasha1 »

Вопрос новичка: у меня ss -tlnp показывает пустую колонку с процессом, хотя порт явно занят. Это из-за того что без sudo запускаю, да? И отдельно спасибо за предупреждение про tcp_tw_recycle, чуть не вкрутил его по старой статье 2015 года.
👍1 ❤️2 🔥 😄 🤔
Ответить
← Предыдущая глава
Сетевой стек Linux: путь пакета и где возникают задержки
Следующая глава →
Захват трафика: tcpdump для диагностики сети

Все главы курса «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Поделиться темой: ✈ Telegram VK
  • Похожие темы
Похожие запросы: ss как посмотреть открытые сокеты и соединения

Вернуться в «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость