Назад | Перейти на главную страницу

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

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

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