Как использовать сокет, созданный пользователем root, с обычным пользователем - PullRequest
2 голосов
/ 08 октября 2019

Итак, у меня есть этот сервер:

import socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind('/tmp/sock.sock')
sock.listen(1)
while True:
    conn, ca = sock.accept()
    print(conn.recv(1024))

И этот клиент:

import socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect('/tmp/sock.sock')
sock.send('Hello, World')

Фактическая отправка и получение немного сложнее, но отлично работает, если обасервер и клиент запускаются пользователем root. Это также работает, когда клиент запускается как root, а сервер запускается обычным пользователем. Но когда я пытаюсь запустить сервер с рутом и клиентом от обычного пользователя, я получаю это:

$ python3 client.py
connecting to /tmp/sock.sock
[Errno 13] Permission denied

Как я могу решить эту проблему? Сервер должен быть запущен от имени пользователя root, а клиент - как непривилегированный пользователь.

Я понял так же, как это связано с правами доступа к файлу сокета, но я не понимаю, как мне это исправить. ,Я не мог видеть какие-либо опции для передачи конструктору сокета, который мог бы это исправить.

Ответы [ 3 ]

1 голос
/ 08 октября 2019

Измените режим файла, чтобы любой мог получить к нему доступ. Добавьте эти строки на ваш сервер

import os
os.chmod("/tmp/sock.sock", 0o777)
0 голосов
/ 08 октября 2019

Это не очень хорошая идея, если у вас весь сервер спроектирован для работы с правами root, где-то есть ошибка проектирования.

Здесь происходит то, что пользователь root создает файл /tmp/sock.sock со своимсобственные привилегии, и этот файл доступен только пользователю, который его создал.

Проблема в том, что даже если метод bind в Linux (но не в Mac OS!) был исправлен, чтобы не следовать символическим ссылкамвы все еще создаете проблему безопасности. Предположим, что файла там нет, а сервер не работает. Обычный пользователь может затем создать символическую ссылку от /tmp/sock.sock до /etc/passwd, и когда сервер попытается запустить, он попытается выполнить привязку, установить разрешения и затем потерпит неудачу из-за символической ссылки, но разрешения будут установлены. Таким образом, ваш файл passwd будет установлен как доступный для записи.

Даже если проблем с разрешениями не было, предположим, что кто-то отправляет действительно большой объем данных и заполняет диск, что приводит к сбою сервера. Если вы запускаете сервер с обычным пользователем, вы можете установить максимальную квоту, но вы не хотите устанавливать ее для root.

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

0 голосов
/ 08 октября 2019

Спасибо П.Дмитри за то, что он указал мне правильное направление. Я закончил с этой модификацией той же идеи, которая немного лучше соответствует моим потребностям:

import pwd
import grp
...
# Change the owner of the socket
os.chown('/tmp/sock.sock', 
         pwd.getpwnam('user').pw_uid, 
         grp.getgrnam('group').gr_gid)
# Restrict access to only this user (and root of course)
os.chmod('/tmp/sock.sock', 0o600)

Примечание:

0o - восьмеричный префикс в Python3. В Python2 это просто 0 как в C.

...