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

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

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

  

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

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

268 голосов | спросил Deepak Mittal 10 12008vEurope/Moscow11bEurope/MoscowMon, 10 Nov 2008 17:31:11 +0300 2008, 17:31:11

20 ответов


317

Короткий ответ: вы не можете. Порты ниже 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
ответил Sunny 10 12008vEurope/Moscow11bEurope/MoscowMon, 10 Nov 2008 17:41:10 +0300 2008, 17:41:10
74

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

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

authbind --deep $JAVA_HOME/bin/java -Djava.net.preferIPv4Stack=true …
ответил geocar 14 52008vEurope/Moscow11bEurope/MoscowFri, 14 Nov 2008 16:12:48 +0300 2008, 16:12:48
43

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

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

sudo apt-get install libcap2-bin 
sudo setcap 'cap_net_bind_service=+ep' /path/to/program
ответил Otto Kekäläinen 31 Mayam12 2012, 00:32:19
39

Другим решением является создание вашего приложения 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
ответил Paul Tomblin 10 12008vEurope/Moscow11bEurope/MoscowMon, 10 Nov 2008 17:44:10 +0300 2008, 17:44:10
35

Подход, предложенный 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/. В этот момент мы ввернуты:

  • Некоторые пользователи будут добавлять URL-адрес https://host:8181/, и нам нужно будет поддерживать этот 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

ответил Misha 20 FebruaryEurope/MoscowbSat, 20 Feb 2010 19:19:54 +0300000000pmSat, 20 Feb 2010 19:19:54 +030010 2010, 19:19:54
31

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

  • 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;
        }
}
ответил CosmicB 20 22012vEurope/Moscow11bEurope/MoscowTue, 20 Nov 2012 18:30:07 +0400 2012, 18:30:07
29

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

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

ответил CesarB 10 12008vEurope/Moscow11bEurope/MoscowMon, 10 Nov 2008 17:36:44 +0300 2008, 17:36:44
23

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

ответил WMR 10 12008vEurope/Moscow11bEurope/MoscowMon, 10 Nov 2008 19:27:54 +0300 2008, 19:27:54
11

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

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

  • балансировки нагрузки
  • Перезапуск серверов приложений с пользователями, получающими причудливую страницу ошибок
  • Ускорить работу с кешем
  • Точные настройки, которые обычно выполняются с обратным прокси-сервером, а не с сервером приложений
ответил Giovanni Toraldo 18 +04002011-10-18T19:36:38+04:00312011bEurope/MoscowTue, 18 Oct 2011 19:36:38 +0400 2011, 19:36:38
6

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

sudo redir --lport=80 --laddr=192.168.0.101 --cport 9990 --caddr=127.0.0.1
ответил user340994 27 22012vEurope/Moscow11bEurope/MoscowTue, 27 Nov 2012 16:48:36 +0400 2012, 16:48:36
4

Использовать sudo.

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

/etc/init.d/httpd start

или

apachectl stop

или

/usr/local/apache2/apachectl restart

или

/myapp/myappbin start

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

ответил Not Now 10 12008vEurope/Moscow11bEurope/MoscowMon, 10 Nov 2008 22:40:32 +0300 2008, 22:40:32
4

Ответ солнечный правильный, но вы можете столкнуться с дополнительными проблемами, поскольку интерфейс loopback не использует таблицу 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
ответил Francesco 31 Jpm1000000pmThu, 31 Jan 2013 20:41:08 +040013 2013, 20:41:08
3

В Linux у вас есть еще два варианта:

Оба расширения ядра Linux позволяют предоставлять права доступа на очень мелкозернистом уровне. Это позволит вам открыть этот процесс для открытия порта 80, но он не наследует ни один из других прав root.

Из того, что я слышал, grsecurity гораздо проще в использовании, но SELinux более безопасен.

ответил Aaron Digulla 11 22008vEurope/Moscow11bEurope/MoscowTue, 11 Nov 2008 11:27:04 +0300 2008, 11:27:04
2

Одним из решений является использование iptables для выполнения PAT для пакетов для порта 80. Вы можете использовать это для маршрутизации пакетов на локальный порт 8080, например. Обязательно установите и настройте исходящие пакеты обратно на порт 80.

По моему опыту мелкие свойства разрешений Linux не компилируются в стандартные ядра из-за проблем с безопасностью.

ответил 10 12008vEurope/Moscow11bEurope/MoscowMon, 10 Nov 2008 17:36:36 +0300 2008, 17:36:36
2

Если вы пытаетесь сделать это, чтобы пользовательская команда могла использовать порт 80, то ваши единственные решения - это трюки iptables или установка исполняемого файла setuid-to-root.

Как это делает Apache (он привязывается к порту 80, но работает как кто-то, кроме root) должен запускаться от имени root, привязываться к порту, а затем изменять права собственности на процесс на не привилегированного пользователя после того, как порт настроен. Если приложение, которое вы пишете, может быть run от пользователя root, вы можете заставить его изменить владельца на неприемлемого пользователя после настройки портов. Но если это просто для обычного пользователя, запускаемого из командной строки, вам придется использовать одно из других решений.

ответил rjray 11 22008vEurope/Moscow11bEurope/MoscowTue, 11 Nov 2008 02:57:39 +0300 2008, 02:57:39
2

Когда у меня есть различные приложения для веб-приложений (скрипты python, двигатели tomcat, ...), которые я не хочу запускать как root, я обычно настраиваю веб-сервер Apache перед ними. Apache прослушивает порт 80, а tomcat - 8080.

В apache: s config:

ProxyPass /webapp http://localhost:8080/webapp
ProxyPassReverse /webapp http://localhost:8080/webapp

Дополнительную информацию см. в документации по mod-proxy: http://httpd.apache.org/docs/2.2/mod/mod_proxy. HTML

ответил 12 32008vEurope/Moscow11bEurope/MoscowWed, 12 Nov 2008 12:58:51 +0300 2008, 12:58:51
2

Я думаю, что лучшим решением является sgid для вашего приложения, и как только он будет связан своим портом, он должен отказаться от привилегий, переключившись на другого пользователя.

ответил Anxy Dicy 18 +04002011-10-18T19:31:03+04:00312011bEurope/MoscowTue, 18 Oct 2011 19:31:03 +0400 2011, 19:31:03
1

Некоторые хост-системы не разрешают использовать модуль 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 объясняет лучше.

ответил Thomas 10 FebruaryEurope/MoscowbFri, 10 Feb 2012 18:33:56 +0400000000pmFri, 10 Feb 2012 18:33:56 +040012 2012, 18:33:56
0

Как в стороне, FreeBSD и Solaris (кто-нибудь помнит , что один?), вы можете сделать это (привязать к низким портам) без повышения привилегий (т. е. с помощью программ для переключения на root). Поскольку вы указали Linux, я просто отправляю это как уведомление другим, которые могут найти этот вопрос.

ответил Daniel C. Sobral 6 FebruaryEurope/MoscowbMon, 06 Feb 2012 18:48:26 +0400000000pmMon, 06 Feb 2012 18:48:26 +040012 2012, 18:48:26
0

Necromancing.

Simple. С обычным или старым ядром вы этого не делаете.
Как отмечают другие, 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 может связывать системные порты.
Dito для mono /.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.

Это уже все.
Скомпилируйте ядро ​​и установите его.
Reboot.
Закончено - этот глупый лимит GONE, и это также работает для скриптов.

Вот как вы скомпилируете ядро:

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

ответил Quandary 16 Jpm1000000pmFri, 16 Jan 2015 20:04:53 +030015 2015, 20:04:53

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132