Вопрос: Как запустить сервер на порту 80 как обычный пользователь в Linux?


Я довольно долго искал эту тему, но не смог найти ее.

Я на Ubuntu Linux и хочу запустить сервер на порту 80, но из-за механизма безопасности Ubuntu я получаю следующую ошибку:

java.net.BindException: Разрешение отклонено: 80

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


269
2017-11-10 14:31


Источник


В чем проблема с запуском сервера на другом неприемлемом порту? Вы думаете о чем-то жестком, как о отключении механизма безопасности, не предоставляя по крайней мере очень серьезной причины для запуска сервера на этом порту. Является ли сервер жестко привязанным к порту 80? Если это так, выбросьте его. - Anonymous
Или сообщение об ошибке Python: socket.error: [Errno 13] Permission denied - Kazark
возможный дубликат Обычный пользователь, использующий порты ниже 1024 - Roman
Вы не можете. Порты ниже 1024 являются привилегированными, и только root может открывать на них прослушивающие сокеты. Соответствующая задача - сбросить разрешения после ее открытия. - Falcon Momot
«Анонимный» - пользователи в мире обучены поиску определенных услуг в определенных портах. В некоторых случаях его стандартизация. Например, HTTP на порту 80 и HTTPS на порту 443. Его трудно изменить пользователей и стандарты мира. - jww


Ответы:


Короткий ответ: вы не можете. Порты ниже 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

Поскольку устройства loopback (например, 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

Правило, которое вас интересует, - nr. 2, поэтому для его удаления:

# iptables -t nat -D PREROUTING 2

318
2017-11-10 14:41



@Sunny: upvotes - это не самый быстрый пистолет на западе, но для лучших ответов. Ваш лучший показ (я упомянул только iptables, вы фактически предоставили полную командную строку). Единственное, что у меня не имеет, - это предостережение о том, что другие пользователи также могут привязываться к порту 8080. - CesarB
Обратите внимание, что это не работает с IPv6. - Emmanuel Bourg
Может ли кто-нибудь объяснить, как я могу удалить это правило позже, когда захочу? После запуска он работает, но это, видимо, не «правило», потому что оно не появляется, когда я делаю sudo iptables --list, Я знаю, что iptables есть и делает, но я никогда не использовал его до этого. - Encoderer
Спасибо за ваш ответ ... всякий раз, когда я перезагружаю Ubuntu, это правило исчезает, и я должен запустить его снова. Есть ли способ сохранить его навсегда? - Coderji
@Coderji: проверьте раздел «save» в документации сообщества: help.ubuntu.com/community/IptablesHowTo - Sunny


использование authbind,

Он даже работает с Java, если вы включаете стек Java только для IPv4. Я использую:

authbind --deep $JAVA_HOME/bin/java -Djava.net.preferIPv4Stack=true …

74
2017-11-14 13:12



Если сервер Tomcat вы можете использовать authbind автоматически, установив AUTHBIND=yes в / etc / default / tomcat6 - Emmanuel Bourg
Я не мог заставить это работать на сервере Ubuntu с пакетом Java по умолчанию ... - Ashley Steel
Я тоже, ни одно известное решение? - mark
Обратите внимание, что вы должны настроить authbind чтобы фактически это произошло. На странице руководства: «/ etc / authbind / byport / port проверен. Если этот файл доступен для выполнения вызывающему пользователю, в соответствии с доступом (2), то привязка к порту разрешена»., например. для порта 80, sudo touch /etc/authbind/byport/80 ; sudo chmod 777 /etc/authbind/byport/80, Первоначальная установка authbind обычно не имеет предварительно настроенных разрешений. - Jason C
О нонононононо, ни в коем случае никогда не хочешь что-нибудь! - Johannes


Если ваша система поддерживает его, вы можете использовать возможности. Посмотрите возможности человека, вам нужно будет CAP_NET_BIND_SERVICE.

На новом Debian / Ubuntu вы можете запускать:

sudo apt-get install libcap2-bin 
sudo setcap 'cap_net_bind_service=+ep' /path/to/program

44
2018-05-30 20:32



это работает для nodejs: setcap 'cap_net_bind_service = + ep' / usr / bin / nodejs - JasonS
Эта. Интересно, почему в этом ответе больше нет. Гораздо проще, чем вариант iptables imho. - Dominik R
это правильный и наиболее эффективный ответ, все остальные ответы приводят к поражению производительности или просто неуверенному / неуверенному. - OneOfOne


Другим решением является создание вашего приложения 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

39
2017-11-10 14:44



Это то же самое, что и root, если приложение не знает, как отказаться от привилегий. - CesarB
Это опасно. Это означает, что любой запрос будет выполняться с правами root. По какой-то причине даже apache запускается с правами root для привязки, а затем передает привилегии другому пользователю. - Sunny
Пол: iptables не так опасен, потому что даже если приложение скомпрометировано, оно не будет подвергать систему атакам, по крайней мере, не с привилегиями root. Запуск приложения как пользователя root - это еще одна история. - Sunny
Опасность для iptables заключается только в том, что это многопользовательская система, как сказал CesarB, поскольку любой может связываться с 8080 и перехватывать трафик. - Sunny
lol, люблю, как принятый ответ имеет -15 - Evan Teran


Подход, предложенный 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, чтобы не нарушать их закладки.
  • Другие пользователи не смогут подключиться, потому что их прокси-серверы не поддерживают нестандартные SSL-порты.

Я использую следующий подход:

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


35
2018-02-20 16:19



Это хорошо, но почему бы просто не привязать демона к localhost: 8080 вместо 0.0.0.0:8080? Я хочу сделать это, но для этого мне нужны iptables. - Amala
Он работает, действительно круто. - xtian


Я просто использую Nginx впереди. Он может работать и на localhost.

  • apt-get install nginx

.. или ..

  • pkg_add -r nginx 

.. или то, что когда-либо подходит вашей ОС.

Все, что вам нужно в nginx.conf, если работает на localhost, это:

сервер {
        слушайте 80;
        server_name some.domain.org;
        место нахождения / {
            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;
        }
}

31
2017-11-20 14:30



Мне действительно нравится это решение. - thomasfedb
Это (одно из) предложенное решение от JFrog: jfrog.com/confluence/display/RTF/nginx - stolsvik


Традиционно в Unix только root может связываться с низкими портами (<1024).

Самый простой способ обойти это - запустить ваш сервер на высокая порт (например, 8080) и используйте простое правило iptables для пересылки соединений с порта 80 на порт 8080. Обратите внимание, что при этом вы теряете дополнительную защиту от низких портов; любой пользователь на вашем компьютере может привязываться к порту 8080.


29
2017-11-10 14:36





Если ваша система поддерживает его, вы можете использовать возможности. Видеть man capabilities, тот, который вам нужен, будет CAP_NET_BIND_SERVICE, Нет, я никогда не использовал их сам, и я не знаю, действительно ли они работают :-)


23
2017-11-10 16:27



они работают, я использую CAP_NET_RAW для запуска таких инструментов, как tcpdump, как обычный пользователь. - Justin


Используйте обратный прокси (nginx, apache + mod_proxy) или обратный прокси-сервер кэширования (Squid, Varnish) перед серверами приложений!

С помощью обратного прокси-сервера вы можете получить множество интересных вещей, таких как:

  • Балансировка нагрузки
  • Перезапуск серверов приложений с пользователями, получающими причудливую страницу с ошибкой
  • Ускорить работу с кешем
  • Мелкозернистые настройки, которые обычно выполняются с обратным прокси-сервером, а не с сервером приложений

11
2017-10-18 15:36





Вы можете использовать программу redir:

sudo redir --lport=80 --laddr=192.168.0.101 --cport 9990 --caddr=127.0.0.1

6
2017-11-27 12:48





Используйте sudo.

Настройте sudo, чтобы обычный пользователь мог запускать соответствующие команды:

/etc/init.d/httpd start

Или

apachectl stop

Или

/usr/local/apache2/apachectl restart

Или

/myapp/myappbin start

(Или любую другую команду / скрипт, которую вы используете для запуска / остановки вашего конкретного веб-сервера / приложения)


4
2017-11-10 19:40



Это имеет ту же проблему - запуск службы с правами root - это плохая практика. - Kevin Panko