Я бы хотел, чтобы программа Python начала прослушивать порт 80, но после этого выполнялась без прав root. Есть ли способ сбросить рут или получить 80 порт без него?
Удаление корневых разрешений в Python
Ответы (6)
Вы не сможете открыть сервер на 80-м порту без прав root, это ограничение на уровне ОС. Таким образом, единственное решение - отказаться от привилегий root после того, как вы откроете порт.
Вот возможное решение для отказа от привилегий root в Python: Отмена привилегий в Python < / а>. В целом это хорошее решение, но вам также необходимо добавить os.setgroups([])
к функции, чтобы гарантировать, что членство в группе пользователя root не сохраняется.
Я немного скопировал и очистил код, а также удалил ведение журнала и обработчики исключений, поэтому вам остается правильно обрабатывать OSError
(он будет выброшен, когда процессу не разрешено переключать свой эффективный UID или GID):
import os, pwd, grp
def drop_privileges(uid_name='nobody', gid_name='nogroup'):
if os.getuid() != 0:
# We're not root so, like, whatever dude
return
# Get the uid/gid from the name
running_uid = pwd.getpwnam(uid_name).pw_uid
running_gid = grp.getgrnam(gid_name).gr_gid
# Remove group privileges
os.setgroups([])
# Try setting the new uid/gid
os.setgid(running_gid)
os.setuid(running_uid)
# Ensure a very conservative umask
old_umask = os.umask(077)
/root
, а не /home/uid_name
, и этот uid_name не сможет ничего делать с ~/
, который затем расширится до /root/
. Это может повлиять на такие модули, как matplotlib, которые хранят данные конфигурации в HOME каталоге. authbind
кажется правильным способом решения этой проблемы.
- person Daniel F; 02.05.2014
Я рекомендую использовать authbind
для запуска вашей программы Python, поэтому ни одна из них не должна запускаться от имени пользователя root.
https://en.wikipedia.org/wiki/Authbind
authbind
- goo.gl/fxFde6 - замените NodeJS на то, что вам нравится (например, python )
- person starlocke; 22.04.2015
/etc/authbind/byport/80
.
- person mwfearnley; 15.03.2018
Не рекомендуется просить пользователя вводить свое имя пользователя и группу всякий раз, когда мне нужно отказаться от привилегий. Вот слегка измененная версия кода Тамаша, которая теряет привилегии и переключается на пользователя, инициировавшего команду sudo. Я предполагаю, что вы используете sudo (если нет, используйте код Тамаша).
#!/usr/bin/env python3
import os, pwd, grp
#Throws OSError exception (it will be thrown when the process is not allowed
#to switch its effective UID or GID):
def drop_privileges():
if os.getuid() != 0:
# We're not root so, like, whatever dude
return
# Get the uid/gid from the name
user_name = os.getenv("SUDO_USER")
pwnam = pwd.getpwnam(user_name)
# Remove group privileges
os.setgroups([])
# Try setting the new uid/gid
os.setgid(pwnam.pw_gid)
os.setuid(pwnam.pw_uid)
#Ensure a reasonable umask
old_umask = os.umask(0o22)
#Test by running...
#./drop_privileges
#sudo ./drop_privileges
if __name__ == '__main__':
print(os.getresuid())
drop_privileges()
print(os.getresuid())
SUDO_USER=someone
, но это хитрость. Гораздо чаще демоны запускаются как root, выполняют привилегированную работу, необходимую им для настройки, а затем переходят к «никому» или пользователю, указанному в их конфигурации для своей повседневной работы.
- person nevelis; 04.06.2019
systemd может сделать это за вас, если вы запустите свою программу через systemd, systemd может передать ей уже открытый прослушивающий сокет, а также может активировать вашу программу при первом подключении. и вам даже не нужно демонизировать его.
Если вы собираетесь использовать автономный подход, вам понадобится возможность CAP_NET_BIND_SERVICE (см. Справочную страницу о возможностях). Это может быть сделано для каждой программы с помощью правильного инструмента командной строки, или сделав ваше приложение (1) suid root (2) start up (3) прослушиванием порта (4) немедленно отбросив привилегии / возможности .
Помните, что программы suid root имеют множество соображений безопасности (чистая и безопасная среда, umask, привилегии, rlimits, все эти вещи, которые ваша программа должна будет настроить правильно). Если вы можете использовать что-то вроде systemd, тем лучше.
Ниже приводится дальнейшая адаптация ответа Тамаша со следующими изменениями:
- Используйте
python-prctl
модуль, чтобы сохранить возможности Linux в указанном списке возможностей. - При желании пользователя можно передать в качестве параметра (по умолчанию выполняется поиск пользователя, запустившего
sudo
). - Устанавливает все группы пользователей и
HOME
. - При желании он меняет каталог.
(Я относительно новичок в использовании этой функции, поэтому, возможно, я что-то пропустил. Это может не работать на старых ядрах (‹3.8) или ядрах с отключенными возможностями файловой системы.)
def drop_privileges(user=None, rundir=None, caps=None):
import os
import pwd
if caps:
import prctl
if os.getuid() != 0:
# We're not root
raise PermissionError('Run with sudo or as root user')
if user is None:
user = os.getenv('SUDO_USER')
if user is None:
raise ValueError('Username not specified')
if rundir is None:
rundir = os.getcwd()
# Get the uid/gid from the name
pwnam = pwd.getpwnam(user)
if caps:
prctl.securebits.keep_caps=True
prctl.securebits.no_setuid_fixup=True
# Set user's group privileges
os.setgroups(os.getgrouplist(pwnam.pw_name, pwnam.pw_gid))
# Try setting the new uid/gid
os.setgid(pwnam.pw_gid)
os.setuid(pwnam.pw_uid)
os.environ['HOME'] = pwnam.pw_dir
os.chdir(os.path.expanduser(rundir))
if caps:
prctl.capbset.limit(*caps)
try:
prctl.cap_permitted.limit(*caps)
except PermissionError:
pass
prctl.cap_effective.limit(*caps)
#Ensure a reasonable umask
old_umask = os.umask(0o22)
Его можно использовать следующим образом:
drop_privileges(user='www', rundir='~', caps=[prctl.CAP_NET_BIND_SERVICE])
Большая часть этого работает, если вам не нужно запрашивать сокет после того, как вы выполните некоторые другие действия, которые вы не хотите быть суперпользователем.
Некоторое время назад я создал проект под названием tradesocket. Это позволяет передавать между процессами в системе posix сокеты вперед и назад. Что я делаю, так это вначале выделяю процесс, который остается суперпользователем, а остальная часть процесса падает в разрешениях, а затем запрашивает сокет у другого.