Служба не видит, кто обратился по сокету
Локальный сокет может сообщать службе, кто именно обратился: идентификаторы пользователя, группы и процесса. Без явного включения эти сведения не передаются, и служба не может различать вызывающих — а именно на этом часто строят разграничение доступа.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Передача учётных данных не включена
По умолчанию сведения о вызывающем не приходят. Служба видит соединение без источника.
-
Разграничение доступа строится на правах файла сокета
Права на файл сокета решают, кто может подключиться, но не дают службе знать, кто подключился.
-
Служба ожидает сведения, а сокет сетевой
Учётные данные передаются только по локальным сокетам. По сетевому соединению их не существует.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Параметры передачи сведений и права сокета.
systemctl show myapp.socket -p PassCredentials -p SocketMode -p SocketGroupПрава файла сокета: кто вообще может подключиться.
sudo ls -l /run/myapp/app.sockЧто служба сообщает о подключениях.
journalctl -u myapp.service -n 20 --no-pagerРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- По умолчанию сведения о вызывающем не приходят. Служба видит соединение без источника.
- Как проверить
-
Посмотрите параметры сокета.
systemctl show myapp.socket -p PassCredentials -p PassSecurity
- Как исправить
-
Включите передачу учётных данных в описании сокета. Тогда служба сможет проверить, от кого пришло обращение.
[Socket] ListenStream=/run/myapp/app.sock PassCredentials=true
- Почему происходит
- Права на файл сокета решают, кто может подключиться, но не дают службе знать, кто подключился.
- Как проверить
-
Посмотрите права сокета и параметры передачи сведений.
sudo ls -l /run/myapp/app.sock 2>/dev/null systemctl show myapp.socket -p SocketMode -p SocketUser -p SocketGroup
- Как исправить
- Используйте оба средства: права файла ограничивают подключение, передача сведений даёт различать вызывающих внутри службы.
- Почему происходит
- Учётные данные передаются только по локальным сокетам. По сетевому соединению их не существует.
- Как проверить
-
Посмотрите вид слушателя.
systemctl cat myapp.socket | grep -E "^Listen"
- Как исправить
- Для различения вызывающих используйте локальный сокет. По сети источник определяется аутентификацией, а не средствами ядра.
Пример вывода
Служба не получает сведений о вызывающем. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
myapp[9200]: warning: SO_PEERCRED returned uid=0 gid=0 pid=0, cannot identify caller
myapp[9200]: refusing privileged command from unidentified caller
$ systemctl show myapp.socket -p PassCredentials
PassCredentials=no
Связанные ошибки
- Сокет с каналом: права не позволяют писать Служба принимает данные через канал, но клиенты не могут в него писать: владелец и права задаются в сокете.
- Interactive authentication required при управлении службой systemctl требует аутентификации: обращение от непривилегированного пользователя через polkit. Как разрешить точечно.
- status=243/CREDENTIALS в systemd Код 243/CREDENTIALS: не удалось подготовить учётные данные службы из LoadCredential=, SetCredential= или ImportCredential=.
- Puma слушает сокет, а веб-сервер получает отказ доступа Разъём между приложением и веб-сервером: сокет создаётся с правами приложения, читает его другой пользователь.
- status=235/CHOWN в systemd Код 235/CHOWN: не удалось изменить владельца сокета. Код относится только к unit-файлам сокетов.
- uWSGI: веб-сервер не может писать в сокет nginx получает отказ доступа к сокету uWSGI: права и владелец сокета задаются в описании приложения.
- Фильтр почты недоступен почтовой службе: сокет и группы Почтовая служба не может обратиться к фильтру: сокет создан с правами, недоступными её пользователю.
- AppArmor: apparmor="DENIED" в журнале ядра Профиль AppArmor запретил операцию: как прочитать запись, найти профиль и поправить его правильно.
Источники
-
systemd.socket(5)
PassCredentials=, SocketMode= и владельцы сокета. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Проверено на systemd 255: без включения сведения о вызывающем не приходят.