Я довольно долго искал решение в Google, но не нашел ответа.
Я использую Ubuntu Linux и хочу запустить сервер на порту 80, но из-за механизма безопасности Ubuntu я получаю следующую ошибку:
java.net.BindException: в доступе отказано: 80
Я думаю, должно быть достаточно просто либо отключить этот механизм безопасности, чтобы порт 80 был доступен для всех пользователей, либо назначить необходимые привилегии текущему пользователю для доступа к порту 80.
Короткий ответ: нельзя. Порты ниже 1024 могут быть открыты только root. Согласно комментарию - ну, вы можете, используя CAP_NET_BIND_SERVICE, но этот подход, примененный к java bin, заставит любую java-программу запускаться с этим параметром, что нежелательно, если не угрожать безопасности.
Длинный ответ: вы можете перенаправить соединения с порта 80 на другой порт, который вы можете открыть как обычный пользователь.
Запускаем как root:
# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
Поскольку устройства с обратной связью (например, localhost) не используют правила предварительной маршрутизации, если вам нужно использовать localhost и т. Д., Добавьте это правило также (спасибо @Francesco):
# iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 8080
ПРИМЕЧАНИЕ. Приведенное выше решение не является хорошо подходит для многопользовательских систем, поскольку любой пользователь может открыть порт 8080 (или любой другой порт высокого уровня, который вы решите использовать), таким образом перехватив трафик. (Кредиты на CesarB).
РЕДАКТИРОВАТЬ: согласно вопросу комментария - чтобы удалить указанное выше правило:
# iptables -t nat --line-numbers -n -L
Это выведет что-то вроде:
Chain PREROUTING (policy ACCEPT)
num target prot opt source destination
1 REDIRECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 redir ports 8088
2 REDIRECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 redir ports 8080
Правило, которое вас интересует, - это номер. 2, чтобы его удалить:
# iptables -t nat -D PREROUTING 2
Использовать authbind.
Он работает даже с Java, если вы включите стек Java только для IPv4. Я использую:
authbind --deep $JAVA_HOME/bin/java -Djava.net.preferIPv4Stack=true …
Если ваша система поддерживает это, вы могли бы использовать возможности. Посмотрите возможности человека, вам понадобится CAP_NET_BIND_SERVICE.
В более новых версиях Debian / Ubuntu вы можете запустить:
sudo apt-get install libcap2-bin
sudo setcap 'cap_net_bind_service=+ep' /path/to/program
Другое решение - сделать приложение setuid таким образом, чтобы оно могло связываться с портом 80. От имени пользователя root выполните следующие действия.
chown root ./myapp
chmod +S ./myapp
Имейте в виду, что это, если все сделано правильно, подвергнет вас потенциальным дырам в безопасности, потому что ваше приложение будет взаимодействовать с сетью и будет работать с полными привилегиями root. Если вы воспользуетесь этим решением, вам следует взглянуть на исходный код Apache или Lighttpd или чего-то подобного, где они используют привилегии root для открытия порта, но затем немедленно откажутся от этих привилегий и «станут» пользователем с более низкими привилегиями, чтобы угонщик не может захватить весь ваш компьютер.
Обновление: как видно на этот вопрос, похоже, что ядра Linux, начиная с версии 2.6.24, имеют новую возможность, которая позволяет вам отмечать исполняемый файл (но, конечно, не сценарий) как имеющий "CAP_NET_BIND_SERVICE
"возможность. Если вы установите пакет debian" libcap2-bin ", вы можете сделать это, введя команду
setcap 'cap_net_bind_service=+ep' /path/to/program
Я просто использую Nginx спереди. Он также может работать на локальном хосте.
apt-get install nginx
.. или ..
pkg_add -r nginx
.. или что нибудь подходит вашей ОС.
Все, что вам нужно в nginx.conf, если он работает на localhost, это:
server { listen 80; server_name some.domain.org; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:8081; } }
Подход, предложенный Sunny и CesarB:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
работает нормально, но имеет небольшой недостаток - он не мешает пользователю подключаться напрямую к порту 8080 вместо 80.
Рассмотрим следующий сценарий, когда это может быть проблемой.
Допустим, у нас есть сервер, который принимает HTTP-соединения на порту 8080 и HTTPS-соединения на порту 8181.
Мы используем iptables для установки следующих перенаправлений:
80 ---> 8080
443 ---> 8181
Теперь предположим, что наш сервер решает перенаправить пользователя со страницы HTTP на страницу HTTPS. Если мы внимательно не перепишем ответ, он будет перенаправлен на https://host:8181/
. На этом этапе мы облажались:
https://host:8181/
URL-адрес, и нам нужно будет поддерживать этот URL-адрес, чтобы не нарушать их закладки. Я использую следующий подход:
iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -p tcp --dport 443 -j MARK --set-mark 1
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8181
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -m mark --mark 1 -j ACCEPT
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8181 -m mark --mark 1 -j ACCEPT
В сочетании с правилом REJECT по умолчанию в цепочке INPUT этот подход предотвращает подключение пользователей напрямую к портам 8080, 8181.
Традиционно в Unix только root может связываться с младшими портами (<1024).
Самый простой способ обойти это - запустить сервер на высокая порт (например, 8080) и используйте простое правило iptables для перенаправления соединений с порта 80 на порт 8080. Обратите внимание, что при этом вы теряете дополнительную защиту от портов низкого уровня; любой пользователь на вашем компьютере может подключиться к порту 8080.
Если ваша система поддерживает это, вы могли бы использовать возможности. Видеть man capabilities
, тот, который вам нужен, будет CAP_NET_BIND_SERVICE
. Нет, сам никогда не использовал и не знаю, действительно ли они работают :-)
Используйте обратный прокси (nginx, apache + mod_proxy) или кеширующий обратный прокси (Squid, Varnish) перед вашими серверами приложений!
С обратным прокси-сервером вы можете добиться множества интересных вещей, таких как:
Вы можете использовать программу redir:
sudo redir --lport=80 --laddr=192.168.0.101 --cport 9990 --caddr=127.0.0.1
ответ Sunny правильный, но вы можете столкнуться с дополнительными проблемами, поскольку интерфейс обратной связи не использует таблицу PREROUTING,
Итак, нужно добавить два правила iptables:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 8080
Используйте sudo.
Настройте sudo так, чтобы обычный пользователь мог запускать соответствующие команды:
/etc/init.d/httpd start
Или
apachectl stop
Или
/usr/local/apache2/apachectl restart
Или
/myapp/myappbin start
(Или любую другую команду / сценарий, которые вы используете для запуска / остановки конкретного веб-сервера / приложения)
В Linux у вас есть еще два варианта:
Оба расширения ядра Linux позволяют предоставлять права доступа на очень мелком уровне. Это позволит вам разрешить этому процессу открыть порт 80, но он не унаследует другие права root.
Из того, что я слышал, grsecurity намного проще в использовании, но SELinux более безопасен.
Некоторые хост-системы не позволяют использовать модуль NAT, iptables в этом случае не решает проблему.
Как насчет xinetd?
В моем случае (ubuntu 10.04)
# apt-get install xinetd
# touch /etc/xinetd.d/my_redirect
# vim /etc/xinetd.d/my_redirect
Вставьте конфигурацию:
service my_redirector_80
{
disable = no
socket_type = stream
protocol = tcp
user = root
wait = no
port = 80
redirect = localhost 8080
type = UNLISTED
}
Затем:
# service xinetd restart
http://docs.codehaus.org/display/JETTY/port80 объясняет лучше.
Я думаю, что лучшим решением является sgid вашего приложения, и как только у него будет привязан порт, он должен отказаться от привилегий, переключившись на другого пользователя.
Когда у меня есть различные приложения для веб-обслуживания (сценарии Python, механизмы tomcat, ...), которые я не хочу запускать с правами root, я обычно настраиваю перед ними веб-сервер apache. Apache слушает порт 80, а tomcat слушает 8080.
В конфигурации apache: s:
ProxyPass /webapp http://localhost:8080/webapp
ProxyPassReverse /webapp http://localhost:8080/webapp
Дополнительную информацию см. В документации по мод-прокси: http://httpd.apache.org/docs/2.2/mod/mod_proxy.html
Если вы пытаетесь сделать это так, чтобы команда, выполняемая пользователем, могла использовать порт 80, то единственное решение - уловки iptables или установка исполняемого файла setuid-to-root.
То, как это делает что-то вроде Apache (он привязывается к порту 80, но работает как кто-то, кроме root), - это запускать как root, связываться с портом, а затем менять владельца процесса на непривилегированного пользователя после порта настроен. Если приложение, которое вы пишете, можно бегать от имени root вы можете изменить владельца на пользователя non-priv после настройки портов. Но если это просто для обычного пользователя, запускающего из командной строки, вам придется использовать одно из других решений.
Одним из решений является использование iptables для выполнения PAT для пакетов для порта 80. Вы можете использовать это, например, для маршрутизации пакетов на локальный порт 8080. Обязательно отрегулируйте исходящие пакеты обратно на порт 80.
По моему опыту, подробные функции разрешений Linux не компилируются в стандартные ядра из-за проблем с безопасностью.
Кстати, FreeBSD и Solaris (кто-нибудь помнит который one?) позволяет делать это (связываться с нижними портами) без повышения привилегий (т. е. с помощью программ для переключения на root). Поскольку вы указали Linux, я просто отправляю это сообщение другим пользователям, которые могут найти этот вопрос.
Некромантинг.
Просто. С нормальным или старым ядром вы этого не сделаете.
Как указывали другие, iptables может перенаправлять порт.
Как также указывали другие, CAP_NET_BIND_SERVICE также может выполнять эту работу.
Конечно, CAP_NET_BIND_SERVICE выйдет из строя, если вы запустите свою программу из скрипта, если вы не установите ограничение на интерпретатор оболочки, что бессмысленно, вы можете запустить свою службу как root ...
например для Java необходимо применить его к JAVA JVM
sudo /sbin/setcap 'cap_net_bind_service=ep' /usr/lib/jvm/java-8-openjdk/jre/bin/java
Очевидно, это означает, что любая программа на Java может связывать системные порты.
Дито для моно / .NET.
Я также почти уверен, что xinetd - не лучшая идея.
Но поскольку оба метода являются взломами, почему бы просто не поднять лимит, сняв ограничение?
Никто не говорил, что вам нужно запускать нормальное ядро, поэтому вы можете просто запустить собственное.
Вы просто загружаете исходный код последней версии ядра (или того, что у вас есть в настоящее время). После этого вы переходите к:
/usr/src/linux-<version_number>/include/net/sock.h:
Там вы ищите эту строку
/* Sockets 0-1023 can't be bound to unless you are superuser */
#define PROT_SOCK 1024
и измените его на
#define PROT_SOCK 0
если вы не хотите иметь небезопасную ситуацию ssh, вы измените ее на это: #define PROT_SOCK 24
Как правило, я бы использовал самый низкий уровень, который вам нужен, например 79 для http или 24 при использовании SMTP на порту 25.
Это уже все.
Скомпилируйте ядро и установите его.
Перезагрузка.
Готово - этот дурацкий предел ушел, и он также работает для скриптов.
Вот как вы собираете ядро:
https://help.ubuntu.com/community/Kernel/Compile
# You can get the kernel-source via package linux-source, no manual download required
apt-get install linux-source fakeroot
mkdir ~/src
cd ~/src
tar xjvf /usr/src/linux-source-<version>.tar.bz2
cd linux-source-<version>
# Apply the changes to PROT_SOCK define in /include/net/sock.h
# Copy the kernel config file you are currently using
cp -vi /boot/config-`uname -r` .config
# Install ncurses libary, if you want to run menuconfig
apt-get install libncurses5 libncurses5-dev
# Run menuconfig (optional)
make menuconfig
# Define the number of threads you wanna use when compiling (should be <number CPU cores> - 1), e.g. for quad-core
export CONCURRENCY_LEVEL=3
# Now compile the custom kernel
fakeroot make-kpkg --initrd --append-to-version=custom kernel-image kernel-headers
# And wait a long long time
cd ..
Вкратце, используйте iptables, если вы хотите оставаться в безопасности, скомпилируйте ядро, если вы хотите быть уверены, что это ограничение никогда вас больше не беспокоит.