Есть ли способ для некорневых процессов привязываться к “привилегированным” портам в Linux?

StackOverflow https://stackoverflow.com/questions/413807

Вопрос

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

Я осведомлен о стандартные обходные пути, но ни один из них не делает именно то , что я хочу:

  1. аутентификация (Версия в тестируемом Debian, 1.0, поддерживает только IPv4)
  2. Использование цели ПЕРЕНАПРАВЛЕНИЯ iptables для перенаправления низкого порта на высокий порт (таблица "nat" еще не реализована для ip6tables, IPv6-версии iptables)
  3. sudo (запуск от имени root - это то, чего я пытаюсь избежать)
  4. Селинукс (или что-то подобное).(Это всего лишь мой блок разработки, я не хочу вводить много дополнительных сложностей.)

Есть ли какие-то простые sysctl переменная, позволяющая некорневым процессам привязываться к "привилегированным" портам (порты меньше 1024) в Linux, или мне просто не повезло?

Редактировать:В некоторых случаях вы можете возможности использования чтобы сделать это.

Это было полезно?

Решение

Хорошо, спасибо людям, которые указали на систему возможностей и CAP_NET_BIND_SERVICE возможности.Если у вас новое ядро, это действительно можно использовать для запуска службы как некорневой, но привязки к низким портам.Короткий ответ заключается в том, что вы делаете:

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

И тогда в любое время program выполняется, после чего он будет иметь CAP_NET_BIND_SERVICE возможности. setcap находится в пакете debian libcap2-bin.

Теперь перейдем к предостережениям:

  1. Вам понадобится как минимум ядро 2.6.24
  2. Это не сработает, если ваш файл является скриптом.(т.е. использует #!строка для запуска интерпретатора).В этом случае, насколько я понимаю, вам пришлось бы применить эту возможность к самому исполняемому файлу интерпретатора, что, конечно, является кошмаром безопасности, поскольку любая программа, использующая этот интерпретатор, будет иметь такую возможность.Я не смог найти ни одного чистого и простого способа обойти эту проблему.
  3. Linux отключит LD_LIBRARY_PATH для любого program который имеет повышенные привилегии, такие как setcap или suid.Так что, если ваш program использует свой собственный .../lib/, Возможно, вам придется рассмотреть другой вариант, такой как переадресация портов.

Ресурсы:

Примечание: RHEL впервые добавил это в версии 6.

Другие советы

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

Другим примером является Postfix, который использует несколько демонов, которые обмениваются данными по каналам, и только один или два из них (которые делают очень мало, за исключением принимаемых или отправляемых байтов) работают в качестве пользователя root, а остальные - с более низким уровнем привилегий.

Вы можете сделать перенаправление порта. Это то, что я делаю для сервера политики Silverlight, работающего на Linux-боксе

iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 943 -j REDIRECT --to-port 1300

Вы можете настроить локальный туннель SSH, например, если вы хотите, чтобы порт 80 достиг вашего приложения, привязанного к 3000:

sudo ssh $USERNAME@localhost -L 80:localhost:3000 -N

Это имеет преимущество работы с серверами сценариев и очень простое.

Или исправьте свое ядро и снимите проверку.

(Вариант на крайний случай, не рекомендуется).

В net/ipv4/af_inet.c, удалите две строки , которые гласят

      if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
              goto out;

и ядро больше не будет проверять привилегированные порты.

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

Идеальным решением, ИМХО, должна быть возможность создания оболочки с наследуемыми CAP_NET_BIND_SERVICE набор.

Вот несколько запутанный способ сделать это:

sg $DAEMONUSER "capsh --keep=1 --uid=`id -u $DAEMONUSER` \
     --caps='cap_net_bind_service+pei' -- \
     YOUR_COMMAND_GOES_HERE"

capsh утилиту можно найти в пакете libcap2-bin в дистрибутивах Debian / Ubuntu.Вот что происходит дальше:

  • sg изменяет действующий идентификатор группы на идентификатор пользователя-демона.Это необходимо, потому что capsh оставляет GID неизменным, и мы определенно этого не хотим.
  • Устанавливает бит "сохранять возможности при изменении UID".
  • Изменяет UID на $DAEMONUSER
  • Сбрасывает все заглушки (на данный момент все заглушки все еще присутствуют из-за --keep=1), за исключением наследуемых cap_net_bind_service
  • Выполняет вашу команду ('--' - это разделитель)

Результатом является процесс с указанным пользователем и группой, и cap_net_bind_service привилегии.

В качестве примера приведем строку из ejabberd сценарий запуска:

sg $EJABBERDUSER "capsh --keep=1 --uid=`id -u $EJABBERDUSER` --caps='cap_net_bind_service+pei' -- $EJABBERD --noshell -detached"

Две другие простые возможности:

Существует старое (немодное) решение для "демона, который привязывается к низкому порту и передает управление вашему демону".Это называется inetd (или xinetd).Минусы заключаются в следующем:

  • ваш демон должен взаимодействовать с stdin / stdout (если вы не управляете демоном - если у вас нет исходного кода - тогда это, возможно, showstopper, хотя некоторые службы могут иметь флаг совместимости с inetd)
  • для каждого соединения разветвляется новый демонический процесс
  • это еще одно звено в цепи

Плюсы:

  • доступно на любом старом UNIX
  • как только ваш системный администратор настроит конфигурацию, вы можете приступать к разработке (не потеряете ли вы возможности setcap при повторной сборке своего демона?И тогда вам придется вернуться к своему администратору: "пожалуйста, сэр ...")
  • daemon не должен беспокоиться об этих сетевых вещах, просто должен общаться через stdin / stdout
  • можете настроить запуск вашего демона от имени пользователя, не являющегося пользователем root, в соответствии с запросом

Еще одна альтернатива:взломанный прокси-сервер (netcat или еще что-то в этом роде более надежный) с привилегированного порта на какой-нибудь произвольный порт с высоким номером, где вы можете запустить свой целевой демон.(Netcat, очевидно, не производственное решение, а "просто мой ящик для разработчиков", верно?).Таким образом, вы могли бы продолжать использовать сетевую версию своего сервера, вам понадобился бы только root / sudo для запуска прокси (при загрузке), и вы не полагались бы на сложные / потенциально хрупкие возможности.

Мой " стандартный обходной путь " использует socat в качестве перенаправителя пользовательского пространства:

socat tcp6-listen:80,fork tcp6:8080

Остерегайтесь, что это не будет масштабироваться, разветвление дорого, но так работает socat.

Обновление 2017:

Использование аутентификация


Намного лучше, чем CAP_NET_BIND_SERVICE или пользовательское ядро.

  • CAP_NET_BIND_SERVICE предоставляет доверие двоичному файлу, но не предоставляет никакого контроля над доступом для каждого порта.
  • Authbind предоставляет доверие пользователю / группе и обеспечивает контроль над доступом к каждому порту, а также поддерживает как IPv4, так и IPv6 (поддержка IPv6 была добавлена в последнее время).

    1. Установить: apt-get install authbind

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

      sudo touch /etc/authbind/byport/80
      sudo touch /etc/authbind/byport/443
      sudo chmod 777 /etc/authbind/byport/80
      sudo chmod 777 /etc/authbind/byport/443

    3. Выполните свою команду через authbind
      (необязательно указывая --deep или другие аргументы, смотрите справочную страницу):

      authbind --deep /path/to/binary command line args
      

      например ,

      authbind --deep java -jar SomeServer.jar
      

В дополнение к потрясающей рекомендации Джошуа (= не рекомендуется, если вы не знаете, что делаете) взломать ядро:

Я впервые опубликовал это здесь.

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

Linux поддерживает возможности для поддержки более детальных разрешений, чем просто " это приложение запустить от имени root " ;. Одна из этих возможностей - CAP_NET_BIND_SERVICE , которая связана с привязкой к привилегированному порту (< 1024).

К сожалению, я не знаю, как использовать это для запуска приложения без полномочий root, все еще предоставляя его CAP_NET_BIND_SERVICE (возможно, используя setcap , но для этого обязательно существует существующее решение).

Я знаю, что это старый вопрос, но теперь, с последними (> = 4.3) ядрами, наконец, есть хороший ответ на этот вопрос - возможности окружающей среды.

Быстрый ответ заключается в том, чтобы получить копию последней (пока еще неизданной) версии libcap из git и скомпилируйте его.Скопируйте полученный progs/capsh где - то двоичный файл (/usr/local/bin это хороший выбор).Затем, как root, запустите свою программу с помощью

/usr/local/bin/capsh --keep=1 --user='your-service-user-name' \
    --inh='cap_net_bind_service' --addamb='cap_net_bind_service' \ 
    -- -c 'your-program'

По порядку, мы

  • Заявляя, что при смене пользователей мы хотим сохранить наши текущие наборы возможностей
  • Переключение пользователя и группы на "имя пользователя вашей службы"
  • Добавление cap_net_bind_service доступ к унаследованным и окружающим наборам
  • Разветвляющийся bash -c 'your-command' (с тех пор как capsh автоматически запускает bash с аргументами после --)

Здесь многое происходит под колпаком.

Во-первых, мы работаем от имени root, поэтому по умолчанию мы получаем полный набор возможностей.Сюда входит возможность переключать uid и gid с помощью setuid и setgid системные вызовы.Однако обычно, когда программа делает это, она теряет свой набор возможностей - это значит, что старый способ удаления root с setuid все еще работает.Тот Самый --keep=1 флаг подсказывает capsh для выдачи prctl(PR_SET_KEEPCAPS) системный вызов, который отключает удаление возможностей при смене пользователя.Фактическая смена пользователей на capsh происходит с --user флаг, который запускает setuid и setgid.

Следующая проблема, которую нам нужно решить, - это как настроить возможности таким образом, чтобы это продолжалось и после того, как мы exec наши дети.Система возможностей всегда имела "унаследованный" набор возможностей, который представляет собой "набор возможностей, сохраненных в execve (2)". [возможности (7)].Хотя это звучит так, как будто решает нашу проблему (просто установите cap_net_bind_service возможность наследования, верно?), на самом деле это применимо только к привилегированным процессам - а наш процесс больше не является привилегированным, потому что мы уже сменили пользователя (с --user флаг).

Новый набор внешних возможностей решает эту проблему - это "набор возможностей, которые сохраняются в execve (2) программы, у которой нет привилегий". Поместив cap_net_bind_service в окружающем наборе, когда capsh exec - это наша серверная программа, наша программа унаследует эту возможность и сможет привязывать слушателей к низким портам.

Если вам интересно узнать больше, возможности страница руководства объясняет это очень подробно.Выполняется capsh через strace это тоже очень информативно!

TLDR:Для получения "ответа" (как я его вижу) перейдите к >> TLDR<< примите участие в этом ответе.

Хорошо, я понял это (на этот раз по-настоящему), ответ на этот вопрос, и этот мой ответ также является способом извиниться за продвижение другой ответ (как здесь, так и в twitter), который я считал "лучшим", но, попробовав его, обнаружил, что ошибался на этот счет.Учитесь на моей ошибке, дети:не рекламируйте что-либо, пока не попробуете это сами!

Опять же, я просмотрел все ответы здесь.Я пытался некоторые из них (и решил не пробовать другие, потому что мне просто не нравились эти решения).Я думал, что решение состояло в том, чтобы использовать systemd с его Capabilities= и CapabilitiesBindingSet= Настройки.Поборовшись с этим некоторое время, я обнаружил, что это не решение потому что:

Возможности предназначены для ограничения корневых процессов!

Как мудро заметил ОП, это всегда лучше всего избегать этого (для всех ваших демонов, если это возможно!).

Вы не можете использовать параметры, связанные с Возможностями, с User= и Group= в systemd модульные файлы, поскольку возможности ВСЕГДА сброс, когда execev вызывается (или что бы это ни было за функция).Другими словами, когда systemd разветвляет и отбрасывает свою завивку, возможности сбрасываются.Обойти это невозможно, и вся эта логика привязки в ядре базируется на uid= 0, а не на возможностях.Это означает, что маловероятно, что Возможности когда-либо станут правильным ответом на этот вопрос (по крайней мере, в ближайшее время).Случайно, setcap, как уже упоминали другие, не является решением проблемы.У меня это не сработало, это плохо работает со скриптами, и они в любом случае сбрасываются при изменении файла.

В свою скудную защиту я заявил (в комментарии, который я сейчас удалил), что Джеймс ' iptables - таблицы предложение (которое также упоминается в OP) было "вторым лучшим решением".:-П

>>TLDR<<

Решение состоит в том, чтобы объединить systemd с технологией "на лету" iptables команды, подобные этой (взято из DNSChain):

[Unit]
Description=dnschain
After=network.target
Wants=namecoin.service

[Service]
ExecStart=/usr/local/bin/dnschain
Environment=DNSCHAIN_SYSD_VER=0.0.1
PermissionsStartOnly=true
ExecStartPre=/sbin/sysctl -w net.ipv4.ip_forward=1
ExecStartPre=-/sbin/iptables -D INPUT -p udp --dport 5333 -j ACCEPT
ExecStartPre=-/sbin/iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333
ExecStartPre=/sbin/iptables -A INPUT -p udp --dport 5333 -j ACCEPT
ExecStartPre=/sbin/iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333
ExecStopPost=/sbin/iptables -D INPUT -p udp --dport 5333 -j ACCEPT
ExecStopPost=/sbin/iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5333
User=dns
Group=dns
Restart=always
RestartSec=5
WorkingDirectory=/home/dns
PrivateTmp=true
NoNewPrivileges=true
ReadOnlyDirectories=/etc

# Unfortunately, capabilities are basically worthless because they're designed to restrict root daemons. Instead, we use iptables to listen on privileged ports.
# Capabilities=cap_net_bind_service+pei
# SecureBits=keep-caps

[Install]
WantedBy=multi-user.target

Здесь мы выполняем следующее:

  • Демон прослушивает на 5333, но соединения успешно принимаются на 53 благодаря iptables
  • Мы можем включить команды в сам файл модуля и таким образом избавить людей от головной боли. systemd очищает правила брандмауэра для нас, не забывая удалять их, когда демон не запущен.
  • Мы никогда не запускаемся от имени root и делаем невозможным повышение привилегий (по крайней мере systemd утверждает), предположительно, даже если демон скомпрометирован и устанавливает uid=0.

iptables к сожалению, это все еще довольно уродливая и сложная в использовании утилита.Если демон прослушивает eth0:0 вместо того, чтобы eth0, например, команды следующие немного другой.

systemd - это замена sysvinit, в которой есть возможность запустить демон с определенными возможностями. , Параметры Capabilities =, CapabilityBoundingSet = на systemd.exec (5) странице.

Перенаправление портов имело для нас наибольшее значение, но мы столкнулись с проблемой, когда наше приложение разрешало бы локальный URL-адрес, который также необходимо было перенаправить; (это означает, что вы shindig ).

Это также позволит вам перенаправляться при доступе к URL-адресу на локальном компьютере.

iptables -A PREROUTING -t nat -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -A OUTPUT -t nat -p tcp --dport 80 -j REDIRECT --to-port 8080

По какой-то причине никто не упоминает о снижении sysctl net.ipv4.ip_unprivileged_port_start до нужного вам значения.Пример:Нам нужно привязать наше приложение к порту 443.

sysctl net.ipv4.ip_unprivileged_port_start=443

Кто-то может сказать, что существует потенциальная проблема с безопасностью:непривилегированные пользователи теперь могут привязываться к другим привилегированным портам (444-1024).Но вы можете легко решить эту проблему с помощью iptables, заблокировав другие порты:

iptables -I INPUT -p tcp --dport 444:1024 -j DROP
iptables -I INPUT -p udp --dport 444:1024 -j DROP

Сравнение с другими методами.Этот метод:

  • с какой-то точки зрения (IMO) это даже более безопасно, чем установка CAP_NET_BIND_SERVICE / setuid, поскольку приложение вообще не использует setuid, даже частично (возможности на самом деле есть).Например, чтобы перехватить основной дамп приложения с включенными возможностями, вам нужно будет изменить sysctl fs.suid_dumpable (что приводит к другим потенциальным проблемам безопасности) Кроме того, когда установлен CAP /suid, каталог /proc / PID принадлежит root, поэтому ваш некорневой пользователь не будет иметь полной информации / контроля над запущенным процессом, например, пользователь не сможет (в общем случае) определить, какие соединения принадлежат приложению через /proc/PID/fd/ (netstat -aptn | grep PID).
  • имеет недостаток в безопасности:если ваше приложение (или любое приложение, использующее порты 443-1024) по какой-либо причине не работает, другое приложение может использовать этот порт.Но эта проблема также может быть применена к CAP / suid (в случае, если вы установили его в интерпретаторе, напримерjava/nodejs) и iptables-перенаправление.Используйте метод systemd-socket, чтобы исключить эту проблему.Используйте метод authbind, чтобы разрешить только специальную привязку пользователя.
  • не требует установки CAP / suid каждый раз, когда вы развертываете новую версию приложения.
  • не требует поддержки / модификации приложения, как метод systemd-socket.
  • не требует перестройки ядра (если текущая версия поддерживает этот параметр sysctl)
  • не выполняет LD_PRELOAD подобно методу authbind / privbind, это потенциально может повлиять на производительность, безопасность, поведение (не так ли?еще не тестировал).В остальном authbind - действительно гибкий и безопасный метод.
  • переопределяет метод ПЕРЕНАПРАВЛЕНИЯ iptables / DNAT, поскольку он не требует преобразования адреса, отслеживания состояния соединения и т.д.Это заметно только в системах с высокой нагрузкой.

В зависимости от ситуации я бы выбрал между sysctl, CAP, authbind и iptables-redirect.И это здорово, что у нас так много вариантов.

При запуске:

iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080

Затем вы можете привязать к порту, на который вы хотите перейти.

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

Позже вы сможете использовать активацию сокета systemd .

Никаких возможностей, iptables или других хитростей не требуется.

Это содержимое соответствующих системных файлов из этого примера простого Python http-сервера

Файл httpd-true.service

[Unit]
Description=Httpd true 

[Service]
ExecStart=/usr/local/bin/httpd-true
User=subsonic

PrivateTmp=yes

Файл httpd-true.socket

[Unit]
Description=HTTPD true

[Socket]
ListenStream=80

[Install]
WantedBy=default.target

Существует также «путь djb». Вы можете использовать этот метод для запуска вашего процесса от имени пользователя root, запущенного на любом порту в tcpserver, затем он передаст управление процессом пользователю, которого вы укажете, сразу после запуска процесса.

#!/bin/sh

UID=`id -u yourusername`
GID=`id -g yourusername`
exec tcpserver -u $UID -g $GID -RHl0 0 portnumber   /path/to/your/process &

Для получения дополнительной информации см. http://thedjbway.b0llix.net/daemontools/uidgid. HTML

Используйте утилиту privbind : позволяет непривилегированному приложению связываться с зарезервированными портами.

Поскольку OP - это просто разработка / тестирование, могут оказаться полезными менее чем гладкие решения:

setcap может использоваться в интерпретаторе сценария для предоставления возможностей сценариям. Если setcaps для двоичного файла глобального интерпретатора неприемлемы, сделайте локальную копию двоичного файла (любой пользователь может) и получите root для setcap для этой копии. Python2 (по крайней мере) правильно работает с локальной копией интерпретатора в вашем дереве разработки скриптов. Нет необходимости в suid, чтобы пользователь root мог контролировать, к каким возможностям пользователи имеют доступ.

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

#!/bin/sh
#
#  Watch for updates to the Python2 interpreter

PRG=python_net_raw
PRG_ORIG=/usr/bin/python2.7

cmp $PRG_ORIG $PRG || {
    echo ""
    echo "***** $PRG_ORIG has been updated *****"
    echo "Run the following commands to refresh $PRG:"
    echo ""
    echo "    $ cp $PRG_ORIG $PRG"
    echo "    # setcap cap_net_raw+ep $PRG"
    echo ""
    exit
}

./$PRG $*

Я пробовал метод iptables PREROUTING REDIRECT. В старых ядрах это правило не поддерживалось для IPv6 . Но, видимо, теперь он поддерживается в ip6tables v1.4.18 и ядре Linux v3.8.

Я также обнаружил, что PREROUTING REDIRECT не работает для соединений, инициированных внутри аппарата. Чтобы работать с соединениями с локального компьютера, добавьте также правило OUTPUT & # 8212; см. перенаправление портов iptables не работает для локального хоста . Например. что-то вроде:

iptables -t nat -I OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 8080

Я также обнаружил, что PREROUTING REDIRECT также влияет на перенаправленные пакеты . То есть, если машина также пересылает пакеты между интерфейсами (например, если она действует как точка доступа Wi-Fi, подключенная к сети Ethernet), тогда правило iptables также будет перехватывать подключения подключенных клиентов к адресатам Интернета и перенаправлять их на машина. Это не то, что я хотел. Я хотел перенаправить только те соединения, которые были направлены на саму машину. Я обнаружил, что могу повлиять только на пакеты, адресованные этому блоку, добавив -m addrtype --dst-type LOCAL . Например. что-то вроде:

iptables -A PREROUTING -t nat -p tcp --dport 80 -m addrtype --dst-type LOCAL -j REDIRECT --to-port 8080

Еще одна возможность - использовать переадресацию TCP-портов. Например. используя socat :

socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080

Однако одним из недостатков этого метода является то, что приложение, которое прослушивает порт 8080, не знает адрес источника входящих соединений (например, для регистрации или других целей идентификации).

Ответ на 2015/ Сентябрь:

ip6tables теперь поддерживает IPV6 NAT: http://www.netfilter.org/projects/iptables/files/changes-iptables-1.4.17.txt

Вам понадобится ядро 3.7 +

Доказательство:

[09:09:23] root@X:~ ip6tables -t nat -vnL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REDIRECT   tcp      eth0   *       ::/0                 ::/0                 tcp dpt:80 redir ports 8080
    0     0 REDIRECT   tcp      eth0   *       ::/0                 ::/0                 tcp dpt:443 redir ports 1443

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 6148 packets, 534K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 6148 packets, 534K bytes)
 pkts bytes target     prot opt in     out     source               destination
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top