Очень неприятно иметь такое ограничение на моем блоке разработки, когда не будет никаких пользователей, кроме меня.
Мне известны стандартные обходные пути , но никто из них не делает именно то, что я хочу:
- authbind (версия в тестировании Debian, 1.0, поддерживает только IPv4)
- Использование цели iptables REDIRECT для перенаправления низкого порта на высокий порт (таблица «nat» еще не реализована для ip6tables, версии iptables IPv6)
- sudo (Запуск от имени root - это то, чего я пытаюсь избежать)
- SELinux (или аналогичный). (Это всего лишь мой блок разработчика, я не хочу вводить много дополнительной сложности.)
Есть ли какая-нибудь простая sysctl
переменная, позволяющая процессам без полномочий root связываться с «привилегированными» портами (портами менее 1024) в Linux, или мне просто не повезло?
РЕДАКТИРОВАТЬ: В некоторых случаях вы можете использовать возможности, чтобы сделать это.
Ответы:
Хорошо, спасибо людям, которые указали на возможности системы и
CAP_NET_BIND_SERVICE
возможности. Если у вас последнее ядро, это действительно возможно использовать для запуска службы без полномочий root, но для привязки низких портов. Короткий ответ: вы делаете:И затем в любое время
program
выполняется после этого он будет иметьCAP_NET_BIND_SERVICE
возможность.setcap
находится в пакете Debianlibcap2-bin
.Теперь о предостережениях:
program
с повышенными привилегиями, напримерsetcap
илиsuid
. Так что, если выprogram
используете его самостоятельно.../lib/
, вам может понадобиться другой вариант, например, переадресация портов.Ресурсы:
setcap
.Примечание: RHEL впервые добавил это в v6 .
источник
/usr/bin/java
а затем открыть возможность для любого Java-приложения, работающего в системе. Слишком плохие возможности не могут быть установлены для каждого пользователя./etc/security/capability.conf
Debian / Ubuntu?Вы можете сделать перенаправление порта. Это то, что я делаю для сервера политики Silverlight, работающего на Linux
источник
/etc/network/if-up.d/firewall
.Стандартный способ состоит в том, чтобы сделать их «setuid», чтобы они запускались как root, а затем они отбрасывают эту привилегию root, как только они привязаны к порту, но до того, как они начнут принимать подключения к нему. Вы можете увидеть хорошие примеры этого в исходном коде для Apache и INN. Мне сказали, что Lighttpd - еще один хороший пример.
Другим примером является Postfix, который использует несколько демонов, которые обмениваются данными по каналам, и только один или два из них (которые делают очень мало, за исключением принимаемых или отправляемых байтов) работают как root, а остальные работают с более низкими привилегиями.
источник
binfmt_misc
своего флага 'C'; я не уверен насчет других.)Или исправьте свое ядро и уберите проверку.
(Вариант последней инстанции, не рекомендуется).
В
net/ipv4/af_inet.c
, удалите две строки, которые читаюти ядро больше не будет проверять привилегированные порты.
источник
Вы можете настроить локальный туннель SSH, например, если вы хотите, чтобы порт 80 достиг вашего приложения, привязанного к 3000:
Это имеет преимущество работы с серверами сценариев и является очень простым.
источник
sudo nc -l 80 | nc localhost 3000
Обновление 2017:
Использовать authbind
Гораздо лучше, чем CAP_NET_BIND_SERVICE или пользовательское ядро.
Authbind предоставляет доверие пользователю / группе и обеспечивает контроль доступа к каждому порту, а также поддерживает IPv4 и IPv6 (поддержка IPv6 была добавлена в последнее время).
Установка:
apt-get install authbind
Настройте доступ к соответствующим портам, например, 80 и 443 для всех пользователей и групп:
Выполните вашу команду через
authbind
(необязательно указав
--deep
или другие аргументы, см. Справочную страницу):например
В качестве продолжения сказочной рекомендации Джошуа (= не рекомендуется, если вы не знаете, что делаете) взломать ядро:
Я впервые опубликовал это здесь .
Просто. С нормальным или старым ядром у вас нет.
Как отмечают другие, iptables может переадресовывать порт.
Как также отметили другие, CAP_NET_BIND_SERVICE также может выполнять эту работу.
Конечно, CAP_NET_BIND_SERVICE потерпит неудачу, если вы запустите свою программу из скрипта, если вы не установите ограничение на интерпретатор оболочки, что бессмысленно, вы также можете запустить свой сервис как root ...
например, для Java вы должны применить его в JAVA JVM
Очевидно, это означает, что любая Java-программа может связывать системные порты.
Дито для моно / .NET.
Я также уверен, что xinetd не лучшая идея.
Но поскольку оба метода являются хакерами, почему бы просто не снять ограничение, сняв ограничение?
Никто не говорил, что вам нужно запустить нормальное ядро, поэтому вы можете просто запустить свое собственное.
Вы просто скачиваете исходный код для самого последнего ядра (или того же, что у вас есть). После этого вы идете к:
Там вы ищете эту строку
и изменить его на
если вы не хотите иметь небезопасную ситуацию с ssh, измените ее следующим образом: #define PROT_SOCK 24
Как правило, я бы использовал самый низкий параметр, который вам нужен, например, 79 для http или 24 при использовании SMTP на порту 25.
Это уже все.
Скомпилируйте ядро и установите его.
Перезагрузка.
Закончено - этот глупый предел ушел, и это также работает для сценариев.
Вот как вы собираете ядро:
https://help.ubuntu.com/community/Kernel/Compile
Короче говоря, используйте iptables, если вы хотите оставаться в безопасности, скомпилируйте ядро, если вы хотите быть уверенным, что это ограничение вас больше не беспокоит.
источник
Возможности файлов не идеальны, потому что они могут сломаться после обновления пакета.
Идеальным решением, ИМХО, должна быть возможность создания оболочки с наследуемым
CAP_NET_BIND_SERVICE
набором.Вот несколько запутанный способ сделать это:
capsh
утилиту можно найти в пакете libcap2-bin в дистрибутивах Debian / Ubuntu. Вот что происходит:sg
изменяет эффективный идентификатор группы на идентификатор пользователя демона. Это необходимо, потому чтоcapsh
оставляет GID без изменений, и мы определенно не хотим этого.$DAEMONUSER
--keep=1
), кроме наследуемыхcap_net_bind_service
Результатом является процесс с указанными пользователем и группой и
cap_net_bind_service
привилегиями.В качестве примера, строка из
ejabberd
скрипта запуска:источник
capsh
могу ничего сделать, кроме «не могу выполнить двоичный файл» при использовании опций--
или==
. Интересно, что мне не хватает.--
передается/bin/bash
, так что вы можете попробовать-c 'your command'
. Увы, я, похоже, испытываю ту же проблему, что и @Cyberax, потому что при попытке получить разрешение «мне отказано»bind
.--gid
вместоsg
(или--user
какие наборы--uid
,--gid
и--groups
):sudo capsh --caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' --keep=1 --user="$service_user" --addamb=cap_net_bind_service -- -c 'exec $service $service_args'
По какой-то причине никто не упомянул о снижении sysctl net.ipv4.ip_unprivileged_port_start до необходимого вам значения. Пример: нам нужно привязать наше приложение к порту 443.
Некоторые могут сказать, что существует потенциальная проблема безопасности: непривилегированные пользователи теперь могут связываться с другими привилегированными портами (444-1024). Но вы можете легко решить эту проблему с помощью iptables, заблокировав другие порты:
Сравнение с другими методами. Этот способ:
В зависимости от ситуации я бы выбрал sysctl, CAP, authbind и iptables-redirect. И это здорово, что у нас так много вариантов.
источник
Две другие простые возможности:
Существует старое (немодное) решение для «демона, который привязывается к низкому порту и передает управление вашему демону». Это называется inetd (или xinetd). Минусы:
Плюсы:
Другая альтернатива: взломанный прокси (netcat или даже что-то более устойчивое ) с привилегированного порта на произвольный порт с большим номером, где вы можете запустить целевой демон. (Очевидно, что Netcat - это не производственное решение, а «просто мой компьютер разработчика», верно?). Таким образом, вы можете продолжать использовать версию вашего сервера с поддержкой сети, для запуска прокси-сервера (при загрузке) потребуется только root / sudo, не полагаясь на сложные / потенциально хрупкие возможности.
источник
Мой «стандартный обходной путь» использует socat в качестве перенаправителя пространства пользователя:
Остерегайтесь, что это не будет масштабироваться, разветвление дорого, но так работает socat.
источник
Linux поддерживает возможности для поддержки более детальных разрешений, чем просто «это приложение запускается с правами root». Одной из таких возможностей
CAP_NET_BIND_SERVICE
является привязка к привилегированному порту (<1024).К сожалению, я не знаю, как использовать это для запуска приложения без полномочий root, при этом предоставляя его
CAP_NET_BIND_SERVICE
(возможно, используяsetcap
, но для этого обязательно найдется решение).источник
Я знаю, что это старый вопрос, но теперь с последними (> = 4.3) ядрами, наконец, есть хороший ответ на это - окружающие возможности.
Быстрый ответ - взять из git копию последней (пока не выпущенной) версии libcap и скомпилировать ее. Скопируйте полученный
progs/capsh
бинарный файл куда-нибудь (/usr/local/bin
это хороший выбор). Затем, с правами root, запустите вашу программу сПо порядку мы
cap_net_bind_service
возможности к унаследованным и окружающим наборамbash -c 'your-command'
(посколькуcapsh
автоматически запускает bash с аргументами после--
)Здесь много всего происходит под капотом.
Во-первых, мы работаем от имени пользователя root, поэтому по умолчанию мы получаем полный набор возможностей. В это входит возможность переключения uid и gid с помощью
setuid
иsetgid
системных вызовов. Однако, обычно, когда программа делает это, она теряет свой набор возможностей - это так, что старый способ удаления root с помощьюsetuid
все еще работает.--keep=1
Флаг указываетcapsh
выдаватьprctl(PR_SET_KEEPCAPS)
системный вызов, который отключает капания возможностей при смене пользователя. Фактическая смена пользователейcapsh
происходит с--user
флагом, который запускаетсяsetuid
иsetgid
.Следующая проблема, которую нам нужно решить, - это как настроить способности таким образом, чтобы это продолжалось после того, как мы стали
exec
нашими детьми. Система возможностей всегда имела «унаследованный» набор возможностей, который является «набором возможностей, сохраняемых в execve (2)» [ abilities (7) ]. Хотя это звучит так, как будто это решает нашу проблему (просто установитеcap_net_bind_service
возможность наследоваться, верно?), На самом деле это применимо только к привилегированным процессам - и наш процесс больше не является привилегированным, потому что мы уже изменили пользователя (с--user
флагом).Новый набор возможностей окружения работает вокруг этой проблемы - это «набор возможностей, которые сохраняются в execve (2) программы, которая не является привилегированной». Включив
cap_net_bind_service
окружение, когдаcapsh
наша серверная программа exec будет наследовать эту возможность, она сможет привязывать слушателей к низким портам.Если вам интересно узнать больше, страница руководства по возможностям объясняет это очень подробно. Запуск
capsh
черезstrace
это тоже очень познавательно!источник
--addamb
Флаг был введен с libcap 2,26. В моей системе было 2.25, и мне пришлось строить из исходного кода.TLDR: для «ответа» (как я его вижу), перейдите к части >> TLDR << в этом ответе.
Хорошо, я понял (на этот раз реально), ответ на этот вопрос, и этот мой ответ также является способом извинения за продвижение другого ответа (и здесь, и в твиттере), который я считаю "лучшим ", но попробовав это, обнаружил, что я ошибся по этому поводу. Учитесь на моих ошибках, дети: не рекламируйте что-нибудь, пока не попробуете это сами!
Опять же, я рассмотрел все ответы здесь. Я попробовал некоторые из них (и решил не пробовать другие, потому что мне просто не нравились решения). Я думал , что решение было использовать
systemd
с егоCapabilities=
иCapabilitiesBindingSet=
настроек. После некоторой борьбы с этим я обнаружил, что это не решение, потому что:Возможности предназначены для ограничения корневых процессов!
Как мудро заявил OP, всегда лучше избегать этого (для всех ваших демонов, если это возможно!).
Вы не можете использовать опции, связанные с возможностями, в файлах модулей
User=
иGroup=
в нихsystemd
, потому что возможности ВСЕГДА сбрасываются приexecev
вызове (или любой другой функции). Другими словами, когдаsystemd
разветвляется и отбрасывает перманент, возможности сбрасываются. Обойти это невозможно, и вся эта логика привязки в ядре основана на uid = 0, а не на возможностях. Это означает, что маловероятно, что Возможности когда-либо будут правильным ответом на этот вопрос (по крайней мере, в ближайшее время). Кстати,setcap
как уже упоминали другие, это не решение проблемы. Это не сработало для меня, оно не работает хорошо со скриптами, и они в любом случае сбрасываются при изменении файла.В своей скудной защите я утверждал (в комментарии, который я сейчас удалил), что предложение iptables Джеймса (о котором также упоминает ФП) было «вторым лучшим решением». :-П
>> << TLDR
Решение состоит в том, чтобы объединить
systemd
сiptables
командами на лету , как это ( взято из DNSChain ):Здесь мы выполняем следующее:
iptables
systemd
очищает правила брандмауэра для нас, убирая их, когда демон не работает.systemd
утверждаем), предположительно, даже если демон скомпрометирован и установленuid=0
.iptables
к сожалению, это все еще довольно уродливая и сложная в использовании утилита. Если демон , например, слушаетeth0:0
вместоeth0
, например, команды немного отличаются .источник
eth0:0
, если у них нет действительно древнего дистрибутива Linux. Они устарели в течение многих лет и в конечном итоге уйдут.# Generated by SolusVM
AmbientCapabilities=CAP_NET_BIND_SERVICE
отлично работала для меня в сочетании сUser=
.systemd - это замена sysvinit, у которой есть возможность запустить демон с определенными возможностями. Параметры Возможности =, CapabilityBoundingSet = в man-странице systemd.exec (5) .
источник
systemd
.Перенаправление портов имело для нас наибольшее значение, но мы столкнулись с проблемой, когда наше приложение решало бы локально URL-адрес, который также необходимо перенаправить; (это означает, что ты shindig ).
Это также позволит вам быть перенаправлены при доступе к URL на локальном компьютере.
источник
Современный Linux поддерживает
/sbin/sysctl -w net.ipv4.ip_unprivileged_port_start=0
.источник
При использовании systemd вам просто нужно немного изменить свой сервис, чтобы принимать предварительно активированные сокеты.
Позже вы можете использовать systemd socket для активации .
Никаких возможностей, iptables или других хитростей не требуется.
Это содержимое соответствующих системных файлов из этого примера простого Python http-сервера
файл
httpd-true.service
файл
httpd-true.socket
источник
При запуске:
Затем вы можете привязать к порту, к которому вы перешли.
источник
--to-port
существует?man iptables
только упоминания--to-ports
(множественное число).systemd
.Используйте утилиту privbind : она позволяет непривилегированному приложению связываться с зарезервированными портами.
источник
Существует также «путь DJB». Вы можете использовать этот метод для запуска вашего процесса с правами root на любом порту в tcpserver, тогда он передаст управление процессом пользователю, которого вы укажете, сразу после запуска процесса.
Для получения дополнительной информации см .: http://thedjbway.b0llix.net/daemontools/uidgid.html
источник
Поскольку OP - это просто разработка / тестирование, могут оказаться полезными менее чем гладкие решения:
setcap может использоваться в интерпретаторе сценария для предоставления возможностей сценариям. Если setcaps для двоичного файла глобального интерпретатора неприемлемы, сделайте локальную копию двоичного файла (любой пользователь может) и получите root для setcap для этой копии. Python2 (по крайней мере) правильно работает с локальной копией интерпретатора в вашем дереве разработки скриптов. Нет необходимости в suid, чтобы пользователь root мог контролировать, к каким возможностям пользователи имеют доступ.
Если вам нужно отслеживать общесистемные обновления интерпретатора, используйте скрипт оболочки, как показано ниже, чтобы запустить ваш скрипт:
источник
Я пробовал метод iptables PREROUTING REDIRECT. В старых ядрах этот тип правил не поддерживался для IPv6. . Но, по-видимому, теперь он поддерживается в ip6tables v1.4.18 и ядре Linux v3.8.
Я также обнаружил, что PREROUTING REDIRECT не работает для соединений, инициированных в машине. Для работы с соединениями с локального компьютера также добавьте правило OUTPUT - смотрите, что перенаправление порта iptables не работает для localhost . Например, что-то вроде:
Я также обнаружил, что PREROUTING REDIRECT также влияет на перенаправленные пакеты . То есть, если машина также пересылает пакеты между интерфейсами (например, если она действует как точка доступа Wi-Fi, подключенная к сети Ethernet), тогда правило iptables также будет перехватывать подключения подключенных клиентов к адресатам Интернета и перенаправлять их на машина. Это не то, что я хотел - я только хотел перенаправить соединения, которые были направлены на саму машину. Я обнаружил, что могу сделать так, чтобы это влияло только на пакеты, адресованные коробке, добавив
-m addrtype --dst-type LOCAL
. Например, что-то вроде:Еще одна возможность - использовать переадресацию TCP-портов. Например, используя
socat
:Однако одним из недостатков этого метода является то, что приложение, которое прослушивает порт 8080, не знает адрес источника входящих соединений (например, для регистрации или других целей идентификации).
источник
Ответ на 2015 / сентябрь:
ip6tables теперь поддерживает IPV6 NAT: http://www.netfilter.org/projects/iptables/files/changes-iptables-1.4.17.txt
Вам понадобится ядро 3.7+
Доказательство:
источник