Меню

Iptables не работает проброс портов

Проброс и перенаправление портов в iptables

Проброс трафика за NAT или проброс трафика на другой сервер

Чаще всего проброс трафика используется, если мы находимся в локальной сети и от внешнего мира отделены шлюзом. Для того, чтобы открыть доступ для локальных служб (ssh, web, ftp), нам необходимо пробросить порты. Поскольку в качестве шлюза мы будем использовать сервер на Linux, то осуществлять данные действия будем с помощью iptables.

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

$EXT_IP — внешний, реальный IP-адрес шлюза;
$INT_IP — внутренний IP-адрес шлюза, в локальной сети;
$LAN_IP — внутренний IP-адрес сервера, предоставляющего службы внешнему миру;
$SRV_PORT — порт службы. Для веб-сервера равен 80, для SMTP — 25 и т.д.;
eth0 — внешний интерфейс шлюза. Именно ему присвоен сетевой адрес $EXT_IP;
eth1 — внутренний интерфейс шлюза, с адресом $INT_IP;

Проброс портов

На шлюз приходит пакет, который мы должны перенаправить на нужный сервер в локальной сети перед принятием решения о маршрутизации, то есть — в цепочке PREROUTING таблицы nat.

Рассмотрим пример

Если входящий пакет пришёл извне на шлюз (1.2.3.4), но предназначен веб-серверу (порт 80), то адрес назначения подменяется на локальный адрес 192.168.1.50. И впоследствии маршрутизатор передаст пакет в локальную сеть.

Дальше принимается решение о маршрутизации. В результате пакет пойдёт по цепочке FORWARD таблицы filter, поэтому в неё надо добавить разрешающее правило. Оно может выглядеть, например, так:

Рассмотрим пример

Пропустить пакет, который пришёл на внешний интерфейс, уходит с внутреннего интерфейса и предназначен веб-серверу (192.168.1.50:80) локальной сети.

С одной стороны, этих двух правил уже достаточно для того, чтобы любые клиенты за пределами локальной сети успешно подключались к внутреннему серверу. С другой — а что будет, если попытается подключиться клиент из локальной сети? Подключение просто не состоится: стороны не поймут друг друга.

Допустим, 192.168.1.31 — ip-адрес клиента внутри локальной сети.

  1. Пользователь вводит в адресную строку браузера адрес example.com;
  2. Сервер обращается к DNS и разрешает имя example.com в адрес 1.2.3.4;
  3. Маршрутизатор понимает, что это внешний адрес и отправляет пакет на шлюз;
  4. Шлюз, в соответствии с нашим правилом, подменяет в пакете адрес 1.2.3.4 на 192.168.1.50, после чего отправляет пакет серверу;
  5. Веб-сервер видит, что клиент находится в этой же локальной сети (обратный адрес пакета — 192.168.1.31) и пытается передать данные напрямую клиенту, в обход шлюза;
  6. Клиент игнорирует ответ, потому что он приходит не с 1.2.3.4, а с 192.168.1.50;
  7. Клиент и сервер ждут, но связи и обмена данными нет.

Есть два способа избежать данной ситуации.

Первый — разграничивать обращения к серверу изнутри и извне, для этого создать на локальном DNS-сервере А-запись для example.com указывающую на 192.168.1.50

Второй — с помощью того же iptables заменить обратный адрес пакета.
Правило должно быть добавлено после принятия решения о маршрутизации и перед непосредственной отсылкой пакета. То есть — в цепочке POSTROUTING таблицы nat.

Рассмотрим пример

Если пакет предназначен веб-серверу, то обратный адрес клиента заменяется на внутренний адрес шлюза.
Этим мы гарантируем, что ответный пакет пойдёт через шлюз.

Читайте также:  Сломалась посудомоечная машина beko

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

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

Рассмотрим пример

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

rules.sh

Теперь, чтобы обеспечить доступ извне к локальному FTP по адресу 192.168.1.52, достаточно набрать в консоли от имени супер-пользователя:

Перенаправление портов

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

Пусть $FAKE_PORT — обманный порт на внешнем интерфейсе шлюза, подключившись к которому мы должны попасть на адрес $LAN_IP и порт $SRV_PORT .

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

Источник

Почему проброс порта через ssh работает, а через iptables нет?

Проброс порта VNC из lxc контейнера наружу:

В варианте ssh нормально подключаюсь, а iptables — connecting. и все

Что я делаю не так?

То есть, ты делаешь telnet localhost 9500 и удивляешься, почему не срабатывает prerouting-правило, в котором написано -i eth0 ? Если же ты телнетишься к внешнему IP, то не хватает MASQUERADE правила, без которого сеть внутри контейнера не будет понимать, а кому же отправлять ответ.

Вообще такое хорошо отлаживать с tmpdump/wireshark, запускаемых на

  1. хосте, откуда осуществляется коннект
  2. роутере
  3. принимающей стороне

Нет, подключаюсь с десктопа через графический VNC-клиент на порт 9500

В правиле iptables добавьте ip машины, с которой соединяетесь:

Где $IP — адрес сервера, к которому Вы подключаетесь.

с десктопа из сети eth0_NET на docker_host_IP:9500, так? И десктоп это не docker_host (другая машина)

А если пробросить 5900->5900 то все работает:

может при запуске контейнера проще -p 9500:5900 ?

Это же более частный случай изначального правила. Те все что попадает под ваше правило попадет и под изначальное.

Не проще, на самом хосте тоже есть VNC, на 5900 как раз, поэтому другой порт

В правиле iptables добавьте ip машины, с которой соединяетесь

Нет, он не постоянный, подключаюсь с обычного ноута

Почему не проще? Ведь docker run -p 9500:5900 какраз и пробросит вам 9500 порт хоста на 5900 порт контейнера. И никаких дополнительных правил iptables не надо будет. Если я все правильно понимаю.

Как контейнер запущен (порты проброшены)?

Похоже забыл написать, что у меня не docker, а lxc

Это же более частный случай изначального правила.

Согласен, ерунду написал. Тогда тут что-то контейнер-специфическое. Вроде прав доступа, например. Мне сложно сказать, не имел дело с контейнерами.

Кстати, как сеть организована? Контейнер как подключен?

Читайте также:  Не работают только входящие вызовы

Потому что FORWARD не разрешил

Вот только что заметил секцию # For Ubuntu 14.04

А у меня 18.04. И на хосте и в контейнере

Но это вписывал не я, автоматом при создании прописалось.
Я вписывал только секции #Mount directory и #Enable VPN

ip_forwarding включен? eth0 не в бридже случайно?

в случае с ssh forwarding не нужен. а вот с iptables нужен

в filter FORWARD не дропается (разрешено там)?

10.0.3.1 — маршрут по умолчанию в контейнере?

10.0.3.1 — маршрут по умолчанию в контейнере?

# iptables -vnL FORWARD

Пробовали на хосте VNC остановить и пробросить 5900 (не 9500) для теста?

пробовал — нет разницы

Кстати, счетчики всегда 0?

можно еще в FORWARD добавить два отдельных правила и посмотреть счетчики. Да и в snat/postrouting тоже отдельное правило перед masquerade можно добавить.

PREROUTING есть. А где POSTROUTING? Ну и

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

Если у тебя транзитная машина не является шлюзом, а тем более комп с которого ты подключаешься, транзитная машина и система на которую села проброс порта в одной сети, то тебе нужно писать в начале правило dnat в prerouting, а потом правило snat в postrouting или masquerade.

Блин, я вот вас всех заставил думать, а опять, оказывается, не всю информацию сказал.

У меня же в контейнере VPN запущен.

Короче так,
ВНУТРИ контейнера:

И все работает
Чет я вчера жестко тупил, извините

10.0.3.1 — маршрут по умолчанию в контейнере?

Источник

Перенаправление портов не работает

Есть сеть впн (10.1.1.1) (Centos 6.6), на сервере есть апач с сайтами. Обмен данными между клиентами не разрешен.

В одной сети с сервером есть сервер с сайтом-статистикой (192.168.1.3).

Нужно сделать, чтобы при вводе в сроке адреса 10.1.1.1:8083 появлялся сайт 192.168.1.3

В iptables в nat прописал

Но не перенаправляет.

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

Как сделать так. чтобы введя 10.1.1.1:8083 — попасть на второй сервера и спокойно смотреть все страницы:?

Или может дело все в апаче?

-A FORWARD . за тебя кто сделает?

-A FORWARD -d 10.1.1.1 -p tcp -m tcp —dport 8083 -j DNAT —to-destination 192.168.1.3:80

тоже не помогло .. сейчас посмотрю ман

тоже не помогло .. сейчас посмотрю ман

У тебя порядок действий неправильный. Меняй.

Уверен? Смотрел снифером?

С тем правилом, что ты привел, хосту 192.168.1.3 прилетит пакет из сети 10.1.1.1 , вопрос в том, сможет ли он на него ответить?

И да, как выше отметили, у тебя может быть просто закрыт путь подобному трафику через FORWARD. iptables-save в студию.

тоже не помогло .. сейчас посмотрю ман

У тебя порядок действий неправильный. Меняй.

Поменял, не помогло.

Ввожу в строке адреса 10.1.1.1:8083 — ожидание истекло

Читайте также:  Справочник не найден настройте пути подготовка документов

И сразу фейл. У тебя правило с таргетом REJECT «съедает» все пакеты и следующим за ним правилам ничего не остается.

Если не нужно отправлять ICMP-сообщений на каждый заблокированный пакет, проще будет убрать это правило и установить default policy FORWARD’а в DROP.

Это касается и остальных цепочек. И да, в чем сакральный смысл цепочки RH-Firewall-1-INPUT в твоей настройке, если все можно писать в INPUT?

Что это и зачем/откуда оно?

Первая строка в куске выделенного мной кода нивелирует вторую.

Что-то я не помню таких фаервольных конструкций в 7 центоси. Это закидон 6 или отдельная приблуда какая-то?

Что-то я не помню таких фаервольных конструкций в 7 центоси. Это закидон 6 или отдельная приблуда какая-то?

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

Вторая строчка появилась, скажем так случайно . )

Это все из 6 центоси.

Верно понял. либо убираю либо ставлю ниже всех это:

-A FORWARD -j REJECT —reject-with icmp-host-prohibited

Почти верно. Тебе выше посоветовали с политиками фаера разобраться.

Откуда другие правила? Что за дурь и рукожопие? Сделал бы схему на листочке и перекроил по-нормальному.

Во-первых, ниже всех. Во-вторых, какой у тебя маршрут по умолчанию там, куда ты делаешь проброс?

Делаю проброс с сервера впн на другую машину в локальной сети с сервером.

route на той машине. но которую перенаправляю.

Другие правила. это какие?

Часть открывает порты, а A RH-Firewall-1-INPUT, тут да .. тут копировал с другого сервера и не стал менять на просто инпут.

А 10.1.1.1 и 192.168.1.1 — это разные интерфейсы одного сервера?

192,168,1,1 — эт шлюз, он дает интернет обоим

Ну что ты тогда хочешь? Если делаешь перенаправление портов иптаблесами, то должен учесть ограничения. В общем, советую не мучить иптаблесы, поставить rinetd. Сам так делаю постоянно. Брат жив.

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

вариант 2. редиректор — rinetd

вариант 3. туннели ssh

вариант 4. nginx

Хорошо, посмотрю в строну rinetd

агап. спасибо , уже два совета про rinetd — нужно посмотреть, о нем и не думал даже

Отлично — rinetd решил проблему быстрей, чем думал.

Только оказалось что с https на https он не передает. или пока не нашел как .

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

По идее, должен, он же траффик напрямую гонит.

Сделать всё через жёпу. Но зачем.

Почему бы просто не попросить openvpn выступать в режиме прокси для твоего сайта? Опенвпн вполне себе умеет разделять один порт с web сервером, к примеру, порт 443/tcp.

так сайт находится за пределами впн.

По идее, должен, он же траффик напрямую гонит.

Посмотрел, да гонит.

Но у меня 443 порт занят, а проброс с 8083 на 443 в локалку не сработал, получаю сообщение о ssl

Источник

Adblock
detector