- Перенаправление (forward) портов iptables
- Пример 1: FORWARD (снаружи в локальную сеть, DNAT, меняется только адрес назначения)
- PREROUTING
- FORWARD
- Пример 2: FORWARD с одного ip на другой (DNAT с MASQUERADE, меняется адрес источника и назначения)
- Отладка
- Проброс портов iptables в Linux
- Как работает NAT?
- Проброс портов в iptables
- Настройка прохождения пакетов
- Модификация пакетов в iptables
- Сохранение настроек iptables
- Выводы
- Проброс и перенаправление портов в iptables
- Проброс портов
- Рассмотрим пример
- Рассмотрим пример
- Рассмотрим пример
- Рассмотрим пример
- Перенаправление портов
Перенаправление (forward) портов iptables
Рассмотрим перенаправление (forward) на двух примерах:
1. с внешнего IP на внутренний сервер (без masquerade, IP-адрес источника сохраняется);
2. forward с использованием masquerade, с подменой IP-адреса источника (в локалку, и просто с сервера на сервер).
Пример 1: FORWARD (снаружи в локальную сеть, DNAT, меняется только адрес назначения)
Предположим, у вас есть веб-сервер в локальной сети, который должен быть доступным из дикого интернета только по https (443/tcp). Причин не использовать VPN или отдельный IP для отдельного сервера может быть много. Например, архитектура сети, отсутствие свободных IP, веб-сервер — гостевая виртуальная машина, а наш шлюз — хост )) Ну, не знаю, сами придумайте ситуацию.
Причем мы хитрые и хотим, чтобы наш веб сервер из интернета не был виден на 443 порту, а был доступен, скажем, на 1293 порту (примерно вот так: https://1.2.3.4:1293).
Итак, мы хотим перенаправить входящие из интернет на порт 1293 на порт 443 сервера в локальной сети.
IF_EXT=»eth0″ # Внешний сетевой адаптер
IF_INT=»eth1″ # Внутренний сетевой адаптер
IP_EXT=»1.2.3.4″ # Внешний IP
IP_INT=»192.168.1.1″ # Внутренний IP
FAKE_PORT=»1293″ # Фейковый порт, доступен из интернет
LOCAL_SRV=»192.168.1.28″ # Web сервер в LAN
SRV_PORT=»443″ # Настоящий порт
# NAT
$IPT -t nat -A PREROUTING -i $IF_EXT -p tcp -d $IP_EXT —dport $FAKE_PORT -j DNAT —to $LOCAL_SRV:$SRV_PORT
# FORWARD
$IPT -A FORWARD -i $IF_EXT -o $IF_INT -d $LOCAL_SRV -p tcp —dport $SRV_PORT -j ACCEPT
PREROUTING
Каждый пакет, попадающий на интерфейс, сначала предварительно обрабатывается (prerouting). Нам нужно, чтобы до того, как шлюз примет решение о маршрутизации (типа, а что с этим делать-то?), всем пакетам, пришедшим на внешний ($IF_EXT) интерфейс на порт 1293 (например, так: https://1.2.3.4:1293), был бы изменен пункт назначения на IP и порт сервера во внутренней сети. Т.е. шлюз «подкорректирует» destination пришедшего пакета так, чтобы можно было принять правильное решение о маршрутизации.
/sbin/iptables -t nat -A PREROUTING -i eth0 -p tcp -d 1.2.3.4 —dport 1293 -j DNAT —to 192.168.1.28:443
Дальше пакет попадет в цепочку FORWARD.
FORWARD
Пакет изменен и, очевидно, что он не предназначен хосту 1.2.3.4. Хост знает, как добраться до локальной сети 192.168.1.0. Поэтому после прохождения цепочки PREROUTING пакет будет направлен на маршрутизацию (а не в INPUT или OUTPUT) — до хоста 192.168.1.28. Т.к. все FORWARD по умолчанию запрещены, разрешаем в явном виде отправку данных, попавших на внешний интерфейс, уходящих через внутренний интерфейс на адрес в локальной сети 192.168.1.28 на порт 443:
/sbin/iptables -A FORWARD -i eth0 -o eth1 -d 192.168.1.28 -p tcp —dport 443 -j ACCEPT
Есть тонкость: это не маскарадинг (когда сервер-получатель не знает, откуда реально пришел запрос). Это изменение адреса назначения. Сервер в локальной сети получит пакет с реального адреса клиента, а не с ip шлюза. Это не плюс и не минус. Это просто факт. Иногда это удобно (когда именно ваш внутренний веб-сервер должен решать, давать кому-то доступ к его ресурсам или нет), а иногда — нет (это в данном случае ответ от веб-сервера пойдет через наш шлюз и не возникнет проблем, а если бы мы делали forward не в локальную сеть, а на другой публичный ip-адрес, то веб-сервер послал бы ответ не шлюзу, а сразу клиенту, и тот мог бы отбросить ответ от ip, который он не запрашивал).
Пример 2: FORWARD с одного ip на другой (DNAT с MASQUERADE, меняется адрес источника и назначения)
Не всегда перенаправление совершается из/в локальную сеть. Бывает, что необходимо сделать проброс соединения на какой-то сервер, используя промежуточный. Это может быть необходимо для дополнительной фильтрации подключаемых клиентов, для разделения нагрузки и других задач.
Есть хост с публичным IP-адресом (1.1.1.1), ему может быть сопоставлено доменное имя, для которого могут быть выпущены SSL-сертификаты и прочее.
Нужно, чтобы клиенты, обращающиеся на 1.1.1.1:25, направлялись бы на 2.2.2.2:25, с 1.1.1.1:443 — на 3.3.3.3:443, а с ip 4.4.4.4 обращения на порт 3535 шли бы на 3.3.3.3:22.
1.1.1.1, 2.2.2.2, 3.3.3.3 — это публичные IP-адреса (а могут быть и внутренними, не важно, могут быть от разных ISP и вообще, в разных местах). Подключающимся клиентам это знать незачем, не придется ничего перенастраивать в почтовых программах и т.п.
(!) Естественно, хосты 2.2.2.2 и 3.3.3.3 должны разрешать трафик на соответствующие порты!
Вот идея правил iptables на сервере 1.1.1.1:
Комментарии к скрипту:
1) INPUT разрешен только для 22/tcp, для ssh.
2) Несмотря на то, что интерфейс всего один, masquerade включен все равно. При переброске трафика все последующие сервера будут считать, что источник всего — это 1.1.1.1, а не реальные клиенты! Это важное отличие от предыдущего примера forward, когда менялся только адрес назначения!
3) Пусть вас не смущает, что OUTPUT по дефолту DROP, а ниже — все ACCEPT. Привык всегда вначале ставить DROP на все, а потом по необходимости разрешаю. В данном случае нет необходимости фильтровать исходящие со шлюза пакеты.
Отладка
На удаленном компьютере-клиенте запустите что-то вроде «telnet 1.1.1.1 25». Пакет должен прийти на 1.1.1.1:25. Это можно контролировать, запустив на сервере 1.1.1.1 в консоли команду:
tcpdump -n port 25
Если все правильно, то на удаленном клиенте пойдет сеанс связи с SMTP-сервером 2.2.2.2.
Если что-то не так, вы должны понимать, что пакет все же пришел на 1.1.1.1:25. А вот потом не ушел. Он не должен попасть никуда, кроме FORWARD. Поэтому для отлова отбрасываемого трафика в цепочке FORWARD раскомментируйте правило лога (есть в примере) и просматривайте события в реальном времени (например, «tail -f /var/log/messages»). В соответствии с тем, что вы увидите в логе, испрвьте ваши правила iptables. Все должно получиться. Когда это произойдет, не забудьте выключить логирование (иначе размер лог-файла станет огромным).
$IPT -t nat -A POSTROUTING -o $IF_EXT -j MASQUERADE
тут ошибка
должно быть
$IPT -t nat -A POSTROUTING -o $IF_INT -j MASQUERADE
проверил — работает — только маскарад проверял
ну и не мешало бы описать какие интерфейсы у вас IN а какие EXT
Спасибо! помогла статья!
Хм. Вроде бы все правильно. Вот это:
$IPT -t nat -A POSTROUTING -o $IF_EXT -j MASQUERADE
относится к случаю, когда внутренние пользователи из локалки лезут в интернет (NAT на внешнем сетевом интерфейсе). Т.е. после принятия решения о направлении трафика происходит подмена адреса на внешний IP на внешнем интерфейсе роутера.
А «$IPT -t nat -A PREROUTING -i $IF_EXT -p tcp —dport 25 -j DNAT —to 2.2.2.2:25»
происходит ДО принятия решения о маршрутизации. Просто пакет свалился на голову роутеру, роутер ДО принятия решения, что с ним делать, подменяет адрес назначения на конечный (2.2.2.2) и только потом уже принимает решение как этот пакет маршрутизировать дальше.
Источник
Проброс портов iptables в Linux
С увеличением количества компьютеров, необходимое количество IP адресов увеличивалось и диапазона IPv4 начало не хватать. Тогда была разработана технология NAT, которая позволяет нескольким компьютерам объединяться в локальную сеть и быть доступными из внешней сети по IP адресу маршрутизатора.
Когда пакет приходит на маршрутизатор, выполняется выяснение какому устройству он был адресован и замена ip адресата на нужный. Кроме переопределения IP получателя и отправителя, NAT может изменять порты. Это называется проброс портов и может быть полезно если вы создали частную сеть, но все же хотите пропускать некоторые виды трафика. Всем этим можно управлять с помощью iptables. В этой статье мы рассмотрим как выполняется проброс портов iptables в Linux.
Как работает NAT?
Чтобы иметь возможность общаться с другими компьютерами в сети компьютер должен иметь уникальный ip адрес. Но поскольку количество адресов уменьшалось нужно было придумать технологию, которая позволяла бы давать один адрес нескольким машинам. И была придумана технология NAT или Network Address Translation.
Все работает очень просто. Компьютер имеет свой адрес в локальной сети, он не виден из интернета. Когда ему нужно отправить пакет, он отправляет его роутеру, затем роутер подменяет адрес отправителя на свой и передает пакет дальше к цели. Параллельно роутер запоминает с какого локального компьютера был отправлен пакет на этот адрес. Дальше ответный пакет приходит роутеру, он подменяет адрес назначения на адрес нужного компьютера и отдает пакет в локальную сеть.
Недостаток в том, что инициировать подключение извне нельзя, потому что маршрутизатор просто еще не знает к кому обращаются. Тут на помощь приходит проброс портов. Мы можем сказать роутеру: при поступлении пакетов на порт 80 перенаправлять их на порт 80 компьютера 192.168.1.2. Теперь адрес отправителя и порт будет заменяться на указанный нами и пакет будет передан туда, куда нужно. Если на маршрутизаторе установлен Linux, то все это можно настроить с помощью iptables.
Проброс портов в iptables
Первое что нужно сделать, это включить переадресацию трафика на уровне ядра, если это еще не сделано. Для этого выполните:
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
Чтобы настройка сохранялась после перезагрузки используйте такую команду:
sudo sysctl -w net.ipv4.ip_forward=1
Мы не будем здесь подробно рассматривать правила iptables и значение каждой опции, поэтому перед тем, как читать дальше вам лучше ознакомиться со статьей iptables для начинающих. Дальше рассмотрим проброс портов iptables nat.
Настройка прохождения пакетов
Сначала мы рассмотрим как разрешить прохождение пакетов через маршрутизатор. Для этого в брандмауэре есть цепочка FORWARD. По умолчанию для всех пакетов применяется правило DROP, которое означает что все нужно отбросить. Сначала разрешим инициализацию новых соединений, проходящих от eth0 до eth1. Они имеют тип contrack и представлены пакетом SYN:
sudo iptables -A FORWARD -i eth0 -o eth1 -p tcp —syn —dport 80 -m conntrack —ctstate NEW -j ACCEPT
Действие ACCEPT означает, что мы разрешаем это соединение. Но это правило разрешает только первый пакет, а нам нужно пропускать любой следующий трафик в обоих направлениях для этого порта (80). поэтому добавим правила для ESTABLIHED и RLEATED:
sudo iptables -A FORWARD -i eth0 -o eth1 -m conntrack —ctstate ESTABLISHED,RELATED -j ACCEPT
$ sudo iptables -A FORWARD -i eth1 -o eth0 -m conntrack —ctstate ESTABLISHED,RELATED -j ACCEPT
Дальше явно установим что наша политика по умолчанию — DROP:
sudo iptables -P FORWARD DROP
Это еще не проброс портов, мы только разрешили определенному трафику, а именно на порт 80, проходить через маршрутизатор на другие машины локальной сети. Теперь настроим правила, которые будут отвечать за перенаправление трафика.
Модификация пакетов в iptables
Далее мы настроим правила, которые будут указывать как и куда нужно перенаправить пакеты, приходящие на порт 80. Сейчас маршрутизатор может их пропускать в сеть, но он еще не знает куда. Для этого нам нужно будет настроить две вещи — модификацию адреса назначения (Destination) DNAT и модификацию адреса отправителя (Source) SNAT.
Правила DNAT настраиваются в цепочке PREROUTING, в таблице NAT. Эта операция изменяет адрес назначения пакета чтобы он достиг нужной нам цели, когда проходит между сетями. Клиенты будут отправлять пакеты нашему маршрутизатору, и им не нужно знать топологию внутренней сети. Пакет автоматически будет приходить нашему веб-серверу (192.168.1.2).
С помощью этого правила мы перенаправляем все пакеты, пришедшие на порт 80, к 192.168.1.2 опять же на порт 80:
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp —dport 80 -j DNAT —to-destination 192.168.1.2
Но это только половина работы. Пакет будет иметь исходный адрес клиента, а значит будет пытаться отправить ответ ему. Так как клиент ожидает получить ответ от маршрутизатора, то нормального TCP соединения не получиться. Чтобы решить эту проблему нужно модифицировать адрес источника и заменить его на адрес маршрутизатора 192.168.1.1. Тогда ответ придет маршрутизатору, а тот уже от своего имени передаст его в сеть.
sudo iptables -t nat -A POSTROUTING -o eth1 -p tcp —dport 80 -d 192.168.1.2 -j SNAT —to-source 192.168.1.1
Если вы хотите перенаправить трафик на порт 8080, то нужно указать его после ip адреса:
sudo iptables -t nat -A POSTROUTING -o eth1 -p tcp —dport 80 -d 192.168.1.2 -j SNAT —to-source 192.168.1.1:8080
Также может понадобиться выполнить проброс диапазона портов iptables, для этого просто укажите диапазон, например, 1000:2000:
sudo iptables -t nat -A POSTROUTING -o eth1 -p tcp —dport 1000:2000 -d 192.168.1.2 -j SNAT —to-source 192.168.1.1
После добавления этого правила можете проверять работу перенаправление портов iptables будет выполняться и все будет отправляться так, как нужно.
Сохранение настроек iptables
Теперь, когда все настроено, нужно сохранить этот набор правил, чтобы он загружался автоматически при каждом старте. Для этого выполните:
sudo service iptables-persistent save
Готово. Теперь проброс портов iptables ubuntu будет работать так, как нужно.
Выводы
В этой статье мы рассмотрели как выполняется перенаправление портов iptables. Процесс включает в себя разрешение на проходящий трафик на уровне ядра, разрешение определенного типа трафика, а также настройку адресов источника и назначения для правильного прохождения пакетов.
На завершение, видео о том, что такое NAT:
Источник
Проброс и перенаправление портов в 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 будет отличаться несущественно, поэтому приведу сразу пример итогового скрипта для ленивых.
Источник