Проброс и перенаправление портов в 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-адрес клиента внутри локальной сети.
- Пользователь вводит в адресную строку браузера адрес example.com;
- Сервер обращается к DNS и разрешает имя example.com в адрес 1.2.3.4;
- Маршрутизатор понимает, что это внешний адрес и отправляет пакет на шлюз;
- Шлюз, в соответствии с нашим правилом, подменяет в пакете адрес 1.2.3.4 на 192.168.1.50, после чего отправляет пакет серверу;
- Веб-сервер видит, что клиент находится в этой же локальной сети (обратный адрес пакета — 192.168.1.31) и пытается передать данные напрямую клиенту, в обход шлюза;
- Клиент игнорирует ответ, потому что он приходит не с 1.2.3.4, а с 192.168.1.50;
- Клиент и сервер ждут, но связи и обмена данными нет.
Есть два способа избежать данной ситуации.
Первый — разграничивать обращения к серверу изнутри и извне, для этого создать на локальном DNS-сервере А-запись для example.com указывающую на 192.168.1.50
Второй — с помощью того же iptables заменить обратный адрес пакета.
Правило должно быть добавлено после принятия решения о маршрутизации и перед непосредственной отсылкой пакета. То есть — в цепочке POSTROUTING таблицы nat.
Рассмотрим пример
Если пакет предназначен веб-серверу, то обратный адрес клиента заменяется на внутренний адрес шлюза.
Этим мы гарантируем, что ответный пакет пойдёт через шлюз.
Надо дополнительно отметить, что это правило важно только для внутренних клиентов. Ответ внешним клиентам пойдёт через шлюз в любом случае.
Но, пока что, для нормальной работы этого недостаточно. Предположим, что в качестве клиента выступает сам шлюз.
В соответствии с нашими предыдущими правилами он будет гонять трафик от себя к себе и представлять исходящие пакеты транзитными.
Рассмотрим пример
Теперь для удобства запилим скрипт, чтобы не прописывать правила каждый раз вручную.
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, запускаемых на
- хосте, откуда осуществляется коннект
- роутере
- принимающей стороне
Нет, подключаюсь с десктопа через графический 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
Источник