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

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

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

java.net.BindException: в доступе отказано:80

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

20 ответов

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

Правило, которое вас интересует, это nr. 2, чтобы удалить его:

# iptables -t nat -D PREROUTING 2

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

В более новой версии Debian/Ubuntu вы можете запустить:

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

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

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

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

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

  • apt-get install nginx

.. или же..

  • pkg_add -r nginx

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

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

сервер {
        слушай 80;
        имя_сервера 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;
        }
}

Другое решение - настроить приложение так, чтобы оно могло связываться с портом 80. От имени пользователя root выполните следующие действия.

chown root ./myapp
chmod +S ./myapp

Имейте в виду, что если вы сделаете это, если это не сделано абсолютно правильно, вы столкнетесь с потенциальными пробелами в безопасности, потому что ваше приложение будет общаться с сетью и будет работать с полными привилегиями суперпользователя. Если вы воспользуетесь этим решением, вам следует взглянуть на исходный код Apache или Lighttpd или чего-то подобного, где они используют привилегии root для открытия порта, но затем сразу же откажутся от этих привилегий и "станут" пользователями с более низкими привилегиями, чтобы угонщик не может захватить весь ваш компьютер.

Обновление: Как видно из этого вопроса, похоже, что ядра Linux начиная с 2.6.24 имеют новую возможность, позволяющую пометить исполняемый файл (но, конечно, не скрипт) как имеющий "CAP_NET_BIND_SERVICE"возможность. Если вы устанавливаете пакет debian"libcap2-bin", вы можете сделать это, выполнив команду

setcap 'cap_net_bind_service=+ep' /path/to/program

Подход, предложенный 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.

Традиционно в 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

Солнечный ответ правильный, но вы можете столкнуться с дополнительными проблемами, так как интерфейс обратной связи не использует таблицу 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

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

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

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

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

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

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

Я думаю, что лучшим решением является 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

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

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

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

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

Necromancing.

Просто. С нормальным или старым ядром у вас нет.
Как отмечают другие, iptables может переадресовывать порт.
Как также отметили другие, CAP_NET_BIND_SERVICE также может выполнять эту работу.
Конечно, CAP_NET_BIND_SERVICE потерпит неудачу, если вы запустите свою программу из скрипта, если вы не установите ограничение на интерпретатор оболочки, что бессмысленно, вы также можете запустить свой сервис как root...
например, для Java, вы должны применить его к JAVA JAVA

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

Другие вопросы по тегам