socat: швейцарский нож сетевых соединений

10 минут чтения
Средний рейтинг статьи — 4.8

socat — утилита для соединения двух потоков данных: TCP-порта, файла, stdin, UNIX-сокета, TLS-соединения, псевдотерминала или процесса. Поэтому её называют «швейцарским ножом» для сети — она не заменяет прокси, балансировщики и VPN, но отлично закрывает разовые инженерные задачи.

Если netcat — это простой TCP-клиент и сервер из консоли, то socat идёт дальше: умеет TLS, UNIX domain sockets, форвардинг между разными типами адресов, fork для параллельных подключений, подробный вывод трафика и запуск процессов на одном из концов соединения.

Разработчикам и DevOps-инженерам socat пригождается при отладке API, проверке сетевой доступности, тестировании проксирования, временном пробросе портов и работе с контейнерами и локальными сервисами. Главное — разбираться в синтаксисе адресов и не превращать временный хак в постоянную и небезопасную схему.

Что такое socat и чем он отличается от netcat

Название socat обычно расшифровывают как SOcket CAT — по аналогии с cat, только вместо чтения файла в stdout он соединяет два произвольных канала ввода-вывода.

Базовая форма команды выглядит так:

socat [опции] АДРЕС1 АДРЕС2

Например, соединить терминал с TCP-портом:

socat - TCP:example.com:80

Здесь - означает стандартный ввод-вывод, а TCP:example.com:80 — TCP-соединение с example.com на порт 80.

Главное отличие от nc — ширина набора адресов. socat умеет не только TCP и UDP, но и OPENSSL, UNIX-CONNECT, UNIX-LISTEN, EXEC, SYSTEM, PTY, FILE, OPEN, TUN, UDP-LISTEN, TCP-LISTEN и другие типы. Это не просто «стучаться в порт», а строить трубу между двумя источниками данных.

1) Где удобнее netcat — быстрая проверка TCP-порта, ручная отправка HTTP-запроса, простейший listener. Если нужно «подключиться и посмотреть, отвечает ли сервис», nc обычно короче.

2) Где удобнее socat — когда нужно связать TCP с UNIX-сокетом, добавить TLS, прокинуть порт с fork, поднять временный мост между контейнером и хостом, создать псевдотерминал или логировать байты в обе стороны.

3) Где нужны другие инструменты — для анализа маршрута лучше traceroute или mtr, для просмотра открытых портов — ss и netstat, для HTTP-диагностики — curl, для TLS — openssl s_client. socat хорошо дополняет эти инструменты, но не делает их ненужными. Например, перед пробросом порта стоит проверить, кто слушает сокет, через утилиту ss, а HTTP-ответ удобнее разобрать через curl.

Установка и базовый синтаксис

В большинстве Linux-дистрибутивов socat есть в стандартных репозиториях.

Debian и Ubuntu:

sudo apt update
sudo apt install socat

RHEL, CentOS Stream, Fedora:

sudo dnf install socat

Arch Linux:

sudo pacman -S socat

macOS через Homebrew:

brew install socat

Проверить версию:

socat -V

Синтаксис строится вокруг двух адресов, каждый из которых состоит из типа и параметров:

socat [опции] АДРЕС1 АДРЕС2

Примеры адресов:

  • - — STDIO, то есть стандартный ввод и вывод;
  • TCP:host:port — TCP-клиент;
  • TCP-LISTEN:port,reuseaddr,fork — TCP-сервер;
  • UDP:host:port — UDP-клиент;
  • UDP-LISTEN:port,reuseaddr — UDP-listener;
  • UNIX-CONNECT:/path/socket — подключение к UNIX-сокету;
  • UNIX-LISTEN:/path/socket,fork — создание UNIX-сокета;
  • OPENSSL:host:port,verify=1 — TLS-клиент;
  • OPEN:file — файл;
  • EXEC:'command' — процесс.

Часто используемые опции:

  • -d -d — диагностические сообщения;
  • -v — печатать передаваемые данные;
  • -x — печатать данные в hex;
  • -T 5 — таймаут бездействия в секундах;
  • -ly — отправлять сообщения в syslog;
  • fork — создавать отдельный процесс на каждое входящее соединение;
  • reuseaddr — переиспользовать адрес после перезапуска listener;
  • bind=127.0.0.1 — слушать только на конкретном IP.

Пример echo-сервера на порту 9000:

socat -v TCP-LISTEN:9000,reuseaddr,fork EXEC:'/bin/cat'

Теперь в другом терминале:

socat - TCP:127.0.0.1:9000

Всё, что вы введёте, вернётся обратно. Минимальный пример, но он хорошо показывает суть: socat связывает сокет и процесс.

Быстрая проверка TCP и UDP

socat можно использовать как интерактивный клиент. Подключимся к HTTP-серверу и отправим запрос вручную:

socat - TCP:example.com:80

После подключения введите:

GET / HTTP/1.1
Host: example.com
Connection: close
 

Пустая строка в конце обязательна: она завершает HTTP-заголовки.

То же самое одной командой:

printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' \
  | socat - TCP:example.com:80

Для быстрой проверки, что порт принимает TCP-соединение, удобно добавить таймаут:

socat -T 3 - TCP:example.com:443

Если соединение установилось, проблема может быть выше сетевого уровня: TLS, HTTP, авторизация, reverse proxy, приложение. Если соединение не устанавливается, проверьте DNS, firewall, слушающий процесс и маршрут. Для базовой диагностики портов пригодится материал про netstat, а для маршрутов — разбор mtr и WinMTR.

С UDP всё менее однозначно: отсутствие ответа не всегда означает недоступность, потому что UDP не устанавливает соединение. Но отправить пакет и послушать ответ можно:

socat - UDP:127.0.0.1:9999

Поднять UDP-listener:

socat -v UDP-LISTEN:9999,reuseaddr -

В другом терминале отправить сообщение:

echo 'hello' | socat - UDP:127.0.0.1:9999

Для UDP-диагностики socat полезен как генератор и приёмник тестовых пакетов. Но если нужно смотреть реальные пакеты, флаги, ретрансляции и направление трафика, лучше подключать tcpdump.

Проброс портов и временный TCP-прокси

Один из самых частых сценариев — временно пробросить локальный порт на другой адрес. Например, на сервере есть PostgreSQL на 127.0.0.1:5432, а вам нужно открыть локальный порт 15432 только для теста:

socat TCP-LISTEN:15432,bind=127.0.0.1,reuseaddr,fork TCP:127.0.0.1:5432

Теперь клиент может подключаться к 127.0.0.1:15432, а socat передаст трафик в 127.0.0.1:5432.

Если нужно слушать на всех интерфейсах:

socat TCP-LISTEN:15432,reuseaddr,fork TCP:127.0.0.1:5432

Но это уже риск: порт может стать доступен извне. Перед такой командой проверьте firewall, security group и список слушающих портов. В Linux для базовой защиты удобно использовать UFW; подробный разбор есть в статье как настроить фаервол с помощью UFW в Ubuntu.

Можно сделать цепочку между двумя хостами:

socat TCP-LISTEN:8080,reuseaddr,fork TCP:10.0.0.25:80

Полезно для временной проверки, когда приложение ожидает сервис на одном адресе, а реальный endpoint находится на другом. Но не стоит превращать это в постоянную архитектуру: нет health check, балансировки, метрик и прозрачного логирования — для продакшена лучше reverse proxy, firewall rules, load balancer или service mesh.

socat также умеет работать через HTTP CONNECT-прокси:

socat - PROXY:proxy.example.com:target.example.com:443,proxyport=3128

И через SOCKS4:

socat - SOCKS4:proxy.example.com:target.example.com:443,socksport=1080

Такие команды удобны для проверки, проходит ли трафик через корпоративный прокси или промежуточный bastion. Для стабильного доступа к серверу за NAT чаще выбирают SSH-туннели; близкая тема разобрана в статье про reverse SSH tunnel.

UNIX-сокеты, Docker и локальные сервисы

Многие локальные сервисы слушают не TCP-порт, а UNIX domain socket. Примеры: Docker daemon, PostgreSQL, Redis, Nginx upstream, systemd-сервисы. socat удобен, когда нужно быстро связать UNIX-сокет с TCP или руками отправить запрос.

Подключение к UNIX-сокету:

socat - UNIX-CONNECT:/var/run/docker.sock

Docker API говорит по HTTP поверх UNIX-сокета. Можно отправить запрос:

printf 'GET /_ping HTTP/1.1\r\nHost: docker\r\n\r\n' \
  | socat - UNIX-CONNECT:/var/run/docker.sock

Если всё в порядке, Docker вернёт OK.

Временный мост TCP → UNIX-сокет:

socat TCP-LISTEN:23750,bind=127.0.0.1,reuseaddr,fork UNIX-CONNECT:/var/run/docker.sock

Теперь локальный TCP-порт 23750 проксирует запросы в Docker socket. Команда полезна для отладки клиентов, которые не умеют UNIX-сокеты, но умеют TCP.

С Docker socket нужно быть особенно аккуратным. Доступ к /var/run/docker.sock почти равен root-доступу к хосту: через Docker API можно запускать контейнеры, монтировать файловую систему и менять окружение. Никогда не публикуйте такой мост на внешнем интерфейсе.

Создать UNIX-сокет и связать его с TCP-сервисом:

rm -f /tmp/app.sock
socat UNIX-LISTEN:/tmp/app.sock,fork,reuseaddr TCP:127.0.0.1:8080

Это полезно, когда один компонент ожидает UNIX-сокет, а реальное приложение слушает TCP: в контейнерных окружениях такой мост помогает быстро проверить гипотезу до изменения конфигурации. Если нужно глубже разобраться с сетями контейнеров, посмотрите материал как работает Docker networking.

TLS-соединения через socat

socat умеет работать с TLS через адреса OPENSSL и OPENSSL-LISTEN. Это не замена специализированным инструментам, но удобный способ быстро проверить защищённое соединение или поднять временный TLS-терминатор.

Подключиться к HTTPS-серверу:

socat - OPENSSL:example.com:443,verify=1,snihost=example.com

После подключения можно отправить HTTP-запрос:

GET / HTTP/1.1
Host: example.com
Connection: close
 

Если сертификат не проходит проверку, socat завершит соединение. Для системного хранилища сертификатов можно явно указать cafile или capath, если это нужно в вашей ОС:

socat - OPENSSL:example.com:443,verify=1,snihost=example.com,cafile=/etc/ssl/certs/ca-certificates.crt

Отключить проверку можно так:

socat - OPENSSL:example.com:443,verify=0

Но это стоит делать только для локальной диагностики. В таком режиме вы проверяете не «безопасное TLS-соединение», а лишь факт, что сервер отвечает на TLS-порту.

Временный TLS-listener перед локальным HTTP-сервисом:

socat OPENSSL-LISTEN:8443,reuseaddr,fork,cert=server.crt,key=server.key,verify=0 \
  TCP:127.0.0.1:8080

Команда принимает TLS на 8443 и передаёт расшифрованный трафик в локальный сервис на 8080. Для нормального reverse proxy в продакшене лучше Nginx, Caddy или HAProxy, но для проверки клиента, который требует TLS, socat часто быстрее.

Если задача — подробно разобрать сертификат, цепочку, SNI и ошибки рукопожатия, удобнее использовать openssl s_client. А для понимания самого процесса пригодится статья как работает HTTPS.

Логирование трафика и отладка протоколов

socat хорош не только как мост, но и как простой инструмент наблюдения. Опция -v печатает данные, проходящие через соединение:

socat -v TCP-LISTEN:8080,reuseaddr,fork TCP:127.0.0.1:3000

Теперь клиент подключается к 8080, реальное приложение остаётся на 3000, а вы видите поток запросов и ответов в терминале.

Для бинарных протоколов полезен hex-вывод:

socat -x TCP-LISTEN:9000,reuseaddr,fork TCP:127.0.0.1:9001

Диагностические сообщения включаются через -d -d:

socat -d -d TCP-LISTEN:8080,reuseaddr,fork TCP:127.0.0.1:3000

Команда покажет, когда listener поднялся, когда пришло соединение, какой адрес подключился, когда процесс завершился.

Типичный сценарий отладки:

1) Проверить, слушает ли сервис порт — ss -lntp или netstat -lntp.

2) Подключиться вручную — socat - TCP:host:port или curl, если это HTTP.

3) Вставить временный прокси с логированием — socat -v TCP-LISTEN:... TCP:....

4) При необходимости снять пакеты — tcpdump на нужном интерфейсе и порту.

5) Сравнить с внешней проверкой — если локально всё работает, а пользователи жалуются, проверьте DNS, CDN, firewall, географию и доступность извне.

Здесь уместен мониторинг доступности: внешний сервис видит проблему не так, как сервер изнутри. Например, Statuser может проверять сайт с заданным интервалом и присылать уведомление о сбое, а socat уже пригодится во время расследования: быстро проверить порт, TLS или промежуточный прокси. Базовый подход к таким проверкам описан в статье про uptime monitoring.

Полезные рецепты socat

Ниже — набор команд, которые часто используют в админской и разработческой практике. Их стоит адаптировать под свои адреса, интерфейсы и правила доступа.

1) Проверить HTTP через raw TCP

printf 'GET /health HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n' \
  | socat - TCP:127.0.0.1:8080

Полезно, когда нужно исключить влияние клиента, SDK или прокси-библиотеки.

2) Поднять простой TCP-listener

socat -v TCP-LISTEN:9000,reuseaddr,fork -

Всё, что отправит клиент, появится в терминале. Удобно для проверки, доходит ли трафик.

3) Отправить файл по TCP

На принимающей стороне:

socat TCP-LISTEN:9000,reuseaddr OPEN:received.bin,creat,trunc

На отправляющей стороне:

socat OPEN:file.bin TCP:server.example.com:9000

Для регулярной передачи файлов лучше scp, rsync или объектное хранилище, но для одноразового теста команда рабочая.

4) Проксировать локальный порт на удалённый сервис

socat TCP-LISTEN:8081,bind=127.0.0.1,reuseaddr,fork TCP:remote.internal:8080

Подходит для проверки приложения, которое умеет обращаться только к localhost.

5) Создать псевдотерминал

socat -d -d PTY,raw,echo=0 PTY,raw,echo=0

socat выведет два пути вида /dev/pts/3 и /dev/pts/4. Данные, записанные в один, появятся в другом. Это полезно при отладке программ, которые ожидают serial-like устройство.

6) Связать команду с TCP-портом

socat TCP-LISTEN:9001,bind=127.0.0.1,reuseaddr,fork EXEC:'/usr/bin/env'

Каждое подключение получит вывод команды env. Это безопаснее, чем отдавать shell, но всё равно требует контроля: любой EXEC на сетевом порту должен считаться потенциальной точкой атаки.

7) Ограничить время ожидания

socat -T 5 - TCP:10.0.0.10:8080

Если соединение зависло без данных, socat завершит работу через 5 секунд бездействия.

Безопасность и ограничения

socat легко создаёт мосты там, где их не было. Это мощно, но именно поэтому опасно: команда на одну строку может случайно открыть внутренний сервис наружу или дать доступ к UNIX-сокету с повышенными правами.

1) Привязывайте listener к нужному адресу — если доступ нужен только локально, используйте bind=127.0.0.1 и не полагайтесь на «я запущу ненадолго»: временные процессы часто забывают остановить.

2) Проверяйте firewall — listener на 0.0.0.0 может стать доступен из интернета. Используйте ss -lntp, iptables, nftables, UFW или cloud security groups.

3) Не публикуйте Docker socket — TCP-мост к /var/run/docker.sock должен быть только локальным и временным. Внешний доступ к нему почти всегда критическая уязвимость.

4) Осторожно с EXEC и SYSTEM — не запускайте shell на сетевом порту. Даже если порт доступен только «внутри сети», это может стать точкой lateral movement.

5) Не используйте verify=0 как норму — для TLS-диагностики допустимо, для продакшена нет. Отключение проверки сертификата скрывает часть проблем: неправильную цепочку, подмену, неверный hostname.

6) Не заменяйте мониторинг временным процессом — socat помогает расследовать, но не отвечает на вопросы «когда началось», «кого затронуло», «как часто повторяется». Для этого нужны метрики, логи, алерты и внешние проверки. Statuser, например, проверяет сайт с заданным интервалом и уведомляет о сбое; это дополняет ручную диагностику, а не конкурирует с ней.

Ограничения тоже стоит учитывать. socat не даёт полноценной observability, не хранит историю, не делает балансировку, не управляет конфигурацией, не заменяет TLS-терминацию в Nginx или HAProxy. Его сила — быстро построить соединение и проверить гипотезу.

Когда socat действительно выручает

socat полезен в промежутке между «непонятно, что происходит» и «мы уже меняем конфигурацию сервиса». Он позволяет быстро сделать эксперимент без кода и без деплоя.

1) Приложение не может подключиться к локальному сервису — поднимите listener или прокси и посмотрите, приходит ли трафик.

2) Нужно проверить доступность внутреннего endpoint — соедините локальный порт с удалённым адресом и протестируйте клиентом.

3) Клиент требует TLS, а тестовый сервис слушает HTTP — временно оберните соединение через OPENSSL-LISTEN.

4) Сервис работает через UNIX-сокет, а инструмент умеет только TCP — постройте мост TCP-LISTEN → UNIX-CONNECT.

5) Нужно увидеть сырой протокол — включите -v или -x и смотрите байты до подключения тяжёлой трассировки.

6) Нужно воспроизвести проблему минимальным способом — уберите SDK, фреймворк, браузер и оставьте только сокет.

Главное правило: после эксперимента зафиксируйте выводы и уберите временный мост. Если команда стала нужна постоянно, её лучше заменить нормальной конфигурацией reverse proxy, firewall, systemd unit, Docker Compose или инфраструктурным кодом.

FAQ

Можно ли заменить curl на socat? Для HTTP-запросов — только частично. socat показывает сырой обмен и полезен для низкоуровневой отладки, но curl удобнее для редиректов, заголовков, TLS-деталей, методов и статусов.

Чем socat лучше netcat? Он поддерживает больше типов соединений: TLS, UNIX-сокеты, псевдотерминалы, файлы, процессы, TCP/UDP-listener с fork. Для простых TCP-проверок netcat часто короче.

Безопасно ли открывать порт через socat? Безопасно только при понятных границах доступа: bind=127.0.0.1, firewall, минимум прав, отсутствие опасного EXEC. Listener на всех интерфейсах может случайно открыть внутренний сервис наружу.

Можно ли использовать socat в продакшене? Можно для точечных задач, но осторожно. Для постоянного проксирования, TLS-терминации и балансировки лучше использовать специализированные инструменты: Nginx, HAProxy, Caddy, SSH-туннели или сетевые компоненты платформы.

Опубликовано 30 октября 202610 минут чтенияАнастасия Левина
Средний рейтинг статьи — 4.8

Настроить мониторинг за 30 секунд

Надёжные уведомления о даунтаймах. Без ложных срабатываний