Кто слушает сокет
u_str — потоковый сокет (как TCP), u_dgr — датаграммы (как UDP). Ключ -p
добавляет процесс: users:(("python3",pid=1750,fd=3)); чужие процессы видно
только с sudo. Файл есть, а в ss -xl его нет — сокет никто не слушает.
Unix-сокет — файл, через который процессы одной машины обмениваются данными; подключается тот, у кого есть право записи.
ls -l /run/app/app.sock
s первой буквой — сокет
stat -c '%F %a %U:%G' /run/app/app.sock
тип, режим, владелец
ss -xl
слушающие unix-сокеты
sudo ss -xlp | grep app.sock
какой процесс слушает
sudo find /run -type s
сокеты в /run
curl --unix-socket /run/app/app.sock http://localhost/
HTTP в сокет
nc -U /run/app/app.sock
сырое соединение
sudo chgrp www-data /run/app/app.sock
доступ группе nginx
sudo chmod 660 /run/app/app.sock
Unix-сокет — точка связи двух процессов на одной машине.
Как и с сетевым сокетом, сервер его слушает, а клиент
подключается, только адрес — не IP и порт, а путь к файлу:
/run/app/app.sock. Данные идут через ядро и в сеть не попадают.
Где встречается: PostgreSQL слушает /var/run/postgresql/.s.PGSQL.5432 —
через него подключается psql без -h; Docker — /run/docker.sock; systemd и
D-Bus держат десятки сокетов в /run. Приложение за nginx часто слушает
сокет вместо порта: порт не занят, снаружи до приложения не достать, доступ
решают права файла.
s первой буквой — тип «сокет». Размер всегда 0: данные в файле не лежат.
Чтобы подключиться, клиенту нужно право записи на файл сокета и право
входа (x) во все каталоги пути. Право чтения не нужно.
Файл создаёт сервер, права берутся из его umask. Процесс от root с маской
022 создаёт srwxr-xr-x root root — подключится только root. Клиент nginx —
пользователь www-data:
| Права сокета | www-data подключится? |
|---|---|
srwxr-xr-x root root |
нет: у остальных нет w |
srw-rw---- root www-data |
да: w у группы |
srwxrwxrwx root root |
да, как и любой пользователь |
Режим 777 открывает сокет всем процессам машины. Доступ дают группой, в
которой состоит клиент, и режимом 660 или 770.
Сервер создаёт файл, когда начинает слушать, и сам должен удалить его при
выходе. Упавший или убитый процесс оставляет файл: путь есть, а слушать некому.
Клиент тогда получает Connection refused, а новый запуск сервера —
Address already in use, пока старый файл не удалят.
/run живёт в памяти и после перезагрузки пуст. Каталог для сокета службы
создаёт systemd: строка RuntimeDirectory=app в юните — и /run/app
появляется при старте службы и исчезает при остановке.
u_str — потоковый сокет (как TCP), u_dgr — датаграммы (как UDP). Ключ -p
добавляет процесс: users:(("python3",pid=1750,fd=3)); чужие процессы видно
только с sudo. Файл есть, а в ss -xl его нет — сокет никто не слушает.
curl шлёт HTTP-запрос в сокет, имя в адресе идёт только в заголовок Host.
Ошибку curl пишет обманчиво: и без прав, и без файла —
Failed to connect to localhost port 80 … Couldn't connect to server, хотя ни
localhost, ни порт 80 тут ни при чём. nc -U называет причину прямо:
nc: /run/app/app.sock: Permission denied.
Такая правка живёт до перезапуска приложения: сокет — а с RuntimeDirectory и
весь каталог — создаётся заново, с прежними правами. Насовсем — в настройках приложения (многие умеют задать режим и группу сокета)
или в юните службы, которая создаёт сокет:
Сокет получит группу www-data и режим srwxrwx---.
Другой путь — добавить www-data в группу сокета:
sudo usermod -aG app www-data. Группы рабочих процессов nginx берёт при их
запуске, поэтому после usermod нужен sudo systemctl reload nginx — он
запускает новые рабочие процессы уже с этой группой.
Каталог в -h — подключение через сокет, как без -h вовсе. Такое подключение
PostgreSQL проверяет по строкам local в pg_hba.conf;
-h 127.0.0.1 — уже TCP и строки host.
nginx пишет connect() to unix:/run/app/app.sock failed (13: Permission
denied) while connecting to upstream и отвечает 502, nc -U —
Permission denied. У клиента нет права записи на файл или входа в каталог
пути. Посмотри ls -l файла и namei -l пути: клиент (для nginx —
www-data) должен попадать в группу с w и проходить все каталоги.
nginx — (2: No such file or directory), psql — connection to server on
socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory.
Файла нет: опечатка в пути у клиента, сервер не запущен или создаёт сокет в
другом месте. Где он слушает на самом деле, покажет ss -xl.
Файл остался от остановленного процесса — в ss -xl его нет. Запусти службу;
не стартует из-за Address already in use — удали старый файл.
Сервер не может создать сокет: файл с этим именем уже есть. У Python —
OSError: [Errno 98] Address already in use. Проверь, что старый процесс не
работает (sudo ss -xlp), и удали файл — или пусть служба удаляет его перед
стартом.
Сокет с w для всех принимает команды от любого пользователя машины. Для
/run/docker.sock это доступ уровня root: кто пишет в него, запускает
контейнеры с любыми правами. Доступ дают группой.
proxy_pass на сокет, ошибки 502.ss -xl, слушающие сокеты.docker.sock и группа docker.RuntimeDirectory, Group, UMask в юните.Есть неточность? Сообщить об ошибке в статье