Linux не привилегированные порты

Форвардинг портов через шлюз Linux в Iptables

NAT (network address translation, или трансляция сетевых адресов) – это технология перенаправления пакетов на альтернативный адрес. Как правило, она помогает трафику преодолеть границы сети. Хост, который реализует NAT, как правило, имеет доступ к двум или нескольким сетям и настроен для маршрутизации трафика между ними.

Форвардинг портов (или перенаправление портов) – это процесс переадресации запросов одного порта на другой хост, порт или сеть. Поскольку этот процесс изменяет назначение передаваемого пакета, он считается операцией NAT.

Данное руководство поможет настроить iptables для перенаправления портов на хосты с помощью технологии NAT. Такая настройка позволит допустить трафик в частную сеть с помощью шлюза.

Требования

Для работы вам понадобится:

  • Два хоста Ubuntu 14.04 в одном датацентре с включенной частной сетью.
  • Пользователь с доступом к sudo на каждом хосте.

Первый хост будет использоваться как брандмауэр и роутер дял частной сети. Второй хост будет работать как веб-сервер, который доступен только через закрытый интерфейс. Первый хост будет передавать запросы на открытый интерфейс веб-сервера, после чего они будут поступать на его закрытый интерфейс.

Данные хостов

Сначала нужно узнать свои сетевые интерфейсы. Чтобы узнать интерфейсы хостов и связанные с ними адреса, введите:

ip -4 addr show scope global
2: eth0 :
mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 198.51.100.45 /18 brd 45.55.191.255 scope global eth0
valid_lft forever preferred_lft forever
3: eth1 :
mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.1.5 /16 brd 10.132.255.255 scope global eth1
valid_lft forever preferred_lft forever

Вывод показал два интерфейса, eth0 и eth1, и присвоенные им адреса, 192.51.100.45 и 192.168.1.5 соответственно. Чтобы узнать свой открытый интерфейс, введите:

ip route show | grep default
default via 111.111.111.111 dev eth0

Команда выведет на экран интерфейс, подключенный к шлюзу по умолчанию (в данном примере это eth0). Обычно это и есть открытый интерфейс.

Найдите эти значения на каждой машине и используйте их в дальнейшей работе.

Условные данные руководства

Для приведения примеров в руководстве используются условные данные хостов. Пожалуйста, во время работы замените их своими данными.

  • Внешний IP: 203.0.113.2
  • Внутренний IP: 192.0.2.2
  • Открытый интерфейс: eth0
  • Закрытый интерфейс: eth1
  • Внешний IP: 203.0.113.15
  • Внутренний IP: 192.0.2.15
  • Открытый интерфейс: eth0
  • Закрытый интерфейс: eth1

Настройка веб-сервера

Установка Nginx

Сначала нужно установить Nginx и настроить его для прослушивания закрытого интерфейса. Так веб-сервер будет доступен только в случае правильной настройки форвардинга портов.

Обновите индекс пакетов и установите пакет:

sudo apt-get update
sudo apt-get install nginx

Настройка Nginx

Откройте виртуальный хост по умолчанию:

sudo nano /etc/nginx/sites-enabled/default

В нём найдите директиву listen:

server <
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
. . .
>

В файле она встречается дважды. В первой директиве listen нужно указать внутренний IP веб-сервера и задать порт 80.

Данное руководство предназначено только для IPv4, потому вторую директиву listen, для IPv6, можно просто удалить.

server <
listen 192.0.2.2:80 default_server;
. . .
>

Сохраните и закройте файл. Проверьте синтаксис на наличие ошибок:

Если ошибок нет, перезапустите Nginx:

sudo service nginx restart

Проверка настройки Nginx

Теперь нужно убедиться, что Nginx доступен только на закрытом интерфейсе.

Перейдите на сервер брандмауэра и попробуйте получить доступ к закрытому интерфейсу веб-сервера:

curl —connect-timeout 5 192.0.2.2

Welcome to nginx!

Welcome to nginx!

Попробуйте использовать открытый интерфейс:

curl —connect-timeout 5 203.0.113.2
curl: (7) Failed to connect to 203.0.113.2 port 80: Connection refused

Настройка форвардинга

Перейдите на сервер брандмауэра.

Включение форвардинга в ядро

Сначала нужно включить форвардинг на уровне ядра. По умолчанию в большинстве систем эта функция отключена.

Чтобы включить форвардинг на одну сессию, введите:

echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

Чтобы включить форвардинг на постоянной основе, нужно отредактировать файл /etc/sysctl.conf.

sudo nano /etc/sysctl.conf

Найдите и раскомментируйте эту строку:

Сохраните и закройте файл, а затем обновите настройки:

sudo sysctl -p
sudo sysctl —system

Настройка брандмауэра

Чтобы выполнить базовую настройку брандмауэра, читайте это руководство, которое поможет вам:

  • Установить iptables-persistent.
  • Сохранить набор правил по умолчанию в /etc/iptables/rules.v4.
  • Научиться добавлять и редактировать правила брандмауэра.

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

Правила форвардинга

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

Читайте также:  Linux bridge interface centos

Согласно базовой настройке брандмауэра, цепочка FORWARD сбрасывает (DROP) трафик по умолчанию. Теперь нужно добавить правила, которые перенаправят соединения на веб-сервер. При этом рекомендуется ограничиться только необходимыми соединениями, а остальные заблокировать.

Цепочка FORWARD будет принимать новые соединения, предназначенные для порта 80 и поступающие от открытого интерфейса, и передавать их закрытому интерфейсу. Новые соединения обнаруживаются по расширению conntrack и пакету TCP SYN.

sudo iptables -A FORWARD -i eth0 -o eth1 -p tcp —syn —dport 80 -m conntrack —ctstate NEW -j ACCEPT

Это правило пропустит через брандмауэр первый пакет, который предназначен для создания соединения. Также необходимо разрешить любой последующий трафик в обоих направлениях, что является результатом этого соединения. Чтобы разрешить трафик между открытым и закрытым интерфейсом (ESTABLISHED,RELATED), введите:

iptables -A FORWARD -i eth0 -o eth1 -m conntrack —ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i eth1 -o eth0 -m conntrack —ctstate ESTABLISHED,RELATED -j ACCEPT

Если цепочка FORWARD использует другую политику по умолчанию, установите в ней политику DROP:

sudo iptables -P FORWARD DROP

Теперь брандмауэр пропускает трафик между открытым и закрытым интерфейсом. Однако пока iptables ещё не знает, как именно нужно направлять этот трафик.

Правила NAT

Теперь нужно добавить правила iptables для маршрутизации трафика. Чтобы iptables мог правильно изменять пакеты и поддерживать взаимодействие между клиентами и веб-сервером, нужно выполнить две операции.

Первая операция, DNAT, будет выполняться в цепи PREROUTING таблицы nat. Эта операция изменяет целевой адрес пакета. Клиенты будут подключаться к серверу брандмауэра по общедоступной сети, не подозревая о перенаправлении пакетов. Нужно изменить адрес получателя каждого пакета, чтобы пакет, попадая в частную сеть, знал, как найти веб-сервер.

NAT не нужно применять ко всем пакетам, которые прошли брандмауэр. Настройте NAT для пакетов, поступающих на порт 80 внутреннего IP-адреса (в данном примере это 192.0.2.2).

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp —dport 80 -j DNAT —to-destination 192.0.2.2

Теперь пакет будет перенаправлен на веб-сервер. Однако на данный момент исходным адресом пакета все еще остается адрес клиента. Сервер попытается отправить ответ непосредственно на этот адрес, в результате чего TCP-соединение не будет легитимным.

Чтобы настроить правильную переадресацию, нужно также изменить исходный адрес пакета. Этот адрес нужно заменить внутренним IP-адресом сервера брандмауэра (в данном примере это 192.0.2.15). После этого ответ будет отправлен на сервер брандмауэра, а уже оттуда он попадёт к клиенту.

Для этого нужно добавить правило в цепочку POSTROUTING в таблицу nat. Она читается непосредственно перед отправкой пакетов по сети.

sudo iptables -t nat -A POSTROUTING -o eth1 -p tcp —dport 80 -d 192.0.2.2 -j SNAT —to-source 192.0.2.15

Теперь веб-сервер будет доступен в браузере, если направить его на внешний адрес хоста брандмауэра.

curl 203.0.113.15

Welcome to nginx!

Welcome to nginx!

Форвардинг портов настроен.

Сохранение правил

Добавив правила для форвардинга портов, нужно сохранить их в наборе постоянных правил брандмауэра.

Если в постоянном наборе правил нет важных комментариев, можете просто использовать такую команду:

sudo service iptables-persistent save

Чтобы сохранить комментарии, откройте файл и отредактируйте его вручную:

sudo nano /etc/iptables/rules.v4

Отредактируйте конфигурации в таблице filter, в цепочке FORWARD. Также нужно отредактировать таблицу nat, в которую нужно добавить правила PREROUTING и POSTROUTING. В данном случае эти правила будут выглядеть так:

*filter
# Allow all outgoing, but drop incoming and forwarding packets by default
:INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] # Custom per-protocol chains
:UDP — [0:0] :TCP — [0:0] :ICMP — [0:0] # Acceptable UDP traffic
# Acceptable TCP traffic
-A TCP -p tcp —dport 22 -j ACCEPT
# Acceptable ICMP traffic
# Boilerplate acceptance policy
-A INPUT -m conntrack —ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT
# Drop invalid packets
-A INPUT -m conntrack —ctstate INVALID -j DROP
# Pass traffic to protocol-specific chains
## Only allow new connections (established and related should already be handled)
## For TCP, additionally only allow new SYN packets since that is the only valid
## method for establishing a new TCP connection
-A INPUT -p udp -m conntrack —ctstate NEW -j UDP
-A INPUT -p tcp —syn -m conntrack —ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack —ctstate NEW -j ICMP
# Reject anything that’s fallen through to this point
## Try to be protocol-specific w/ rejection message
-A INPUT -p udp -j REJECT —reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT —reject-with tcp-reset
-A INPUT -j REJECT —reject-with icmp-proto-unreachable
# Rules to forward port 80 to our web server
# Web server network details:
# * Public IP Address: 203.0.113.2
# * Private IP Address: 192.0.2.2
# * Public Interface: eth0
# * Private Interface: eth1
#
# Firewall network details:
#
# * Public IP Address: 203.0.113.15
# * Private IP Address: 192.0.2.15
# * Public Interface: eth0
# * Private Interface: eth1
-A FORWARD -i eth0 -o eth1 -p tcp —syn —dport 80 -m conntrack —ctstate NEW -j ACCEPT
-A FORWARD -i eth0 -o eth1 -m conntrack —ctstate ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -i eth1 -o eth0 -m conntrack —ctstate ESTABLISHED,RELATED -j ACCEPT
# End of Forward filtering rules
# Commit the changes
COMMIT
*raw
:PREROUTING ACCEPT [0:0] :OUTPUT ACCEPT [0:0] COMMIT
*nat
:PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] # Rules to translate requests for port 80 of the public interface
# so that we can forward correctly to the web server using the
# private interface.
# Web server network details:
# * Public IP Address: 203.0.113.2
# * Private IP Address: 192.0.2.2
# * Public Interface: eth0
# * Private Interface: eth1
#
# Firewall network details:
#
# * Public IP Address: 203.0.113.15
# * Private IP Address: 192.0.2.15
# * Public Interface: eth0
# * Private Interface: eth1
-A PREROUTING -i eth0 -p tcp —dport 80 -j DNAT —to-destination 192.0.2.2
-A POSTROUTING -d 192.0.2.2 -o eth1 -p tcp —dport 80 -j SNAT —to-source 192.0.2.15
# End of NAT translations for web server traffic
COMMIT
*security
:INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] COMMIT
*mangle
:PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] COMMIT

Читайте также:  Микрофон не работает компьютер windows

Сохраните и закройте файл.

Проверьте ошибки в файле:

sudo iptables-restore -t

Если ошибок нет, обновите список правил:

sudo service iptables-persistent reload

Убедитесь, что веб-сервер всё ещё доступен по внешнему адресу сервера брандмауэра:

Заключение

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

Источник

Разрешить процесс без полномочий root связываться с портами 80 и 443?

Можно ли настроить параметр ядра, чтобы позволить программе пользовательского интерфейса связываться с портами 80 и 443?

Причина, по которой я спрашиваю, заключается в том, что глупо разрешать привилегированному процессу открывать сокет и слушать. Все, что открывает сокет и прослушивает, представляет собой высокий риск, и приложения с высоким риском не должны запускаться от имени пользователя root.

Я бы предпочел попытаться выяснить, какой непривилегированный процесс прослушивает порт 80, а не пытаться удалить вредоносное ПО, проникшее с правами root.

4 ответа 4

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

Вариант 1. Используйте CAP_NET_BIND_SERVICE для предоставления доступа к порту с низким номером для процесса:

При этом вы можете предоставить постоянный доступ к конкретному двоичному файлу для привязки к портам с низким номером с помощью команды setcap :

Для получения дополнительной информации о части e/i/p см. cap_from_text .

После этого /path/to/binary сможет связываться с портами с низким номером. Обратите внимание, что вы должны использовать setcap для самого двоичного файла , а не символическую ссылку.

Вариант 2. Используйте authbind для предоставления одноразового доступа с более точным контролем пользователя / группы / порта:

Инструмент authbind (man-страница) существует именно для этого.

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

Настройте его для предоставления доступа к соответствующим портам, например, для разрешения 80 и 443 от всех пользователей и групп:

Теперь выполните вашу команду через authbind (при желании можно указать —deep или другие аргументы, см. Справочную страницу):

Есть и плюсы и минусы обоих вышеперечисленных. Вариант 1 предоставляет доверие к двоичному файлу, но не обеспечивает контроль доступа к каждому порту. Вариант 2 предоставляет доверие пользователю / группе и обеспечивает контроль доступа к каждому порту, но AFAIK поддерживает только IPv4.

Дейл Хэгглунд на месте. Так что я просто собираюсь сказать то же самое, но по-другому, с некоторыми особенностями и примерами. ☺

В мире Unix и Linux нужно сделать следующее:

  • иметь небольшую, простую, легко проверяемую программу, которая работает от имени суперпользователя и связывает сокет прослушивания;
  • иметь другую маленькую, простую, легко проверяемую программу, которая отбрасывает привилегии, порожденные первой программой;
  • чтобы основная часть службы работала в отдельной третьей программе под учетной записью не-суперпользователя и цепью, загруженной второй программой, ожидая простого наследования дескриптора открытого файла для сокета.

Вы неправильно поняли, где находится высокий риск. Высокий риск заключается в чтении из сети и воздействии на то, что читается, а не в простых действиях по открытию сокета, привязке его к порту и вызову listen() . Это часть службы, которая осуществляет фактическое общение с высоким риском. Открываемые части, bind() и listen() и даже (в некоторой степени) accepts() часть не представляют высокого риска и могут выполняться под эгидой суперпользователя. Они не используют и не обрабатывают (за исключением исходных IP-адресов в случае accept() ) данные, которые находятся под контролем ненадежных незнакомцев в сети.

Читайте также:  Этот компьютер windows fonts

Есть много способов сделать это.

inetd

Как говорит Дейл Хагглунд, старый inetd «сетевого суперсервера» делает это. Учетная запись, под которой запускается сервисный процесс, является одним из столбцов в inetd.conf . Он не разделяет прослушивающую часть и часть удаления привилегий на две отдельные программы, маленькие и легко проверяемые, но он разделяет основной код службы на отдельную программу, exec() созданную в процессе службы, который порождается с помощью дескриптор открытого файла для сокета.

Сложность аудита — не такая уж большая проблема, поскольку нужно проверять только одну программу. Основная проблема inetd заключается не столько в аудите, сколько в том, что он не обеспечивает простого детального управления сервисом во время выполнения по сравнению с более поздними инструментами.

UCSPI-TCP и daemontools

Daniel J. Бернштейна UCSPI-TCP и DaemonTools пакеты были разработаны , чтобы сделать это в сочетании. В качестве альтернативы можно использовать практически эквивалентный набор инструментов Брюса Гюнтера на бис .

Программа для открытия дескриптора файла сокета и привязки к привилегированному локальному порту — tcpserver , из UCSPI-TCP. Это делает listen() и accept() .

Затем tcpserver запускает либо служебную программу, которая сама отбрасывает привилегии root (поскольку обслуживаемый протокол включает в себя запуск в качестве суперпользователя, а затем «вход в систему», как, например, в случае с демоном FTP или SSH), либо setuidgid который это отдельная небольшая и легко проверяемая программа, которая только отбрасывает привилегии и затем загружает их в цепочку непосредственно в служебную программу (ни одна из частей которой, таким образом, никогда не будет работать с привилегиями суперпользователя, как, например, в случае с qmail-smtpd ).

Таким образом, сценарий run службы может быть, например, таким (для dummyidentd для предоставления нулевой службы IDENT):

перекус

Мой пакет Nosh предназначен для этого. У него есть небольшая утилита setuidgid , как и у других. Одно небольшое отличие состоит в том, что его можно использовать со службами в стиле systemd «LISTEN_FDS», а также со службами UCSPI-TCP, поэтому традиционная программа tcpserver заменяется двумя отдельными программами: tcp-socket-listen и tcp-socket-accept .

Опять же, одноразовые утилиты порождают и загружают друг друга. Одна интересная особенность дизайна заключается в том, что можно отказаться от привилегий суперпользователя после listen() но даже до accept() . Вот скрипт run для qmail-smtpd который действительно делает именно это:

Программы, которые работают под эгидой суперпользователя — это небольшие сервисно-независимые инструменты загрузки fdmove , clearenv , envdir , softlimit , tcp-socket-listen и setuidgid . К моменту запуска sh , сокет открыт и привязан к порту smtp , и у процесса больше нет привилегий суперпользователя.

S6, S6-сети и Execline

Пакеты Laurent Bercot s6 и s6-network были разработаны для того, чтобы сделать это совместно. Команды структурно очень схожи с daemontools и UCSPI-TCP.

Сценарии run будут почти такими же, за исключением замены s6-tcpserver на tcpserver и s6-setuidgid на setuidgid . Тем не менее, можно также использовать набор инструментов execline М. Bercot в то же время.

Вот пример службы FTP, слегка измененной по сравнению с оригинальной Уэйн Маршалл, которая использует execline, s6, s6-network и программу сервера FTP из publicfile:

ipsvd

Ipsvd Gerrit Pape — это еще один набор инструментов, который работает по тем же принципам, что и ucspi-tcp и s6-network. На этот раз инструментами являются chpst и tcpsvd , но они делают то же самое, и код высокого риска, который выполняет чтение, обработку и запись вещей, отправленных по сети ненадежными клиентами, все еще находится в отдельной программе.

Вот пример М. Pape запуска fnord в сценарии run :

systemd

systemd , новая система управления службами и инициализации, которую можно найти в некоторых дистрибутивах Linux, предназначена для того, чтобы делать то, что может делать inetd . Тем не менее, он не использует набор небольших автономных программ. К сожалению, приходится проверять systemd полностью.

С помощью systemd создаются файлы конфигурации для определения сокета, который слушает systemd , и запускается служба, которая запускает systemd . Файл «модуля» службы имеет настройки, которые позволяют значительно контролировать процесс службы, в том числе от имени пользователя, с которым он работает.

Когда этот пользователь настроен как не суперпользователь, systemd выполняет всю работу по открытию сокета, привязке его к порту и вызову listen() (и, если требуется, accept() ) в процессе № 1 в качестве суперпользователя. и сервисный процесс, который он порождает, выполняется без привилегий суперпользователя.

Источник

Оцените статью