- How to do local port forwarding with iptables
- 1 Answer 1
- Перенаправление портов и сокетов через SSH туннели
- Перенаправление внутреннего порта удалённого сервера на локальную машину
- Пример с перенаправлением удалённого порта
- Перенаправление вашего локального порта на удалённую машину
- Пример с перенаправлением локального порта
- Прокси сервер SOCKS5 через SSH
- Как пробросить порт в Linux
- Начальные данные
- Алгоритм проброса портов в iptables.
- Настройка port forwarding на Linux
- Перенаправления всего трафика
- Как посмотреть правила iptables
How to do local port forwarding with iptables
I have an application (server) listening on port 8080. I want to be able to forward port 80 to it, such that hitting http://localhost resolves my application (on localhost:8080 ). This should be generalized for any port mapping (e.g. 80:8080 => P_src:P_target ), and use best practices for modern *nix machines (e.g. Ubuntu). N.B. This is all done locally, so there is no need to accept connections from anyone but localhost.
1 Answer 1
So after much searching around, I found the answer uses iptables, setting up a NAT, and using the built-ins PREROUTING and OUTPUT.
First, you must have port forwarding enabled:
echo «1» > /proc/sys/net/ipv4/ip_forward
Then you have to add the following rules to your iptables NAT table, using your own values for $ and $ :
iptables -t nat -A PREROUTING -s 127.0.0.1 -p tcp --dport $ -j REDIRECT --to $` iptables -t nat -A OUTPUT -s 127.0.0.1 -p tcp --dport $ -j REDIRECT --to $`
If you want to remove the rules, you simply need to use the -D switch instead of -A for each rule.
I build a nice little script for this that does adding and removing of mappings.
#!/bin/bash # # API: ./forwardPorts.sh add|rm p1:p1' p2:p2' . # # Results in the appending (-A) or deleting (-D) of iptable rule pairs that # would otherwise facilitate port forwarding. # # E.g # sudo iptables -t nat -A PREROUTING -s 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to 8080 # sudo iptables -t nat -A OUTPUT -s 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to 8080 # if [[ $# -lt 2 ]]; then echo "forwardPorts takes a state (i.e. add or rm) and any number port mappings (e.g. 80:8080)"; exit 1; fi case $1 in add ) append_or_delete=A;; rm ) append_or_delete=D;; * ) echo "forwardPorts requires a state (i.e. add or rm) as it's first argument"; exit 1; ;; esac shift 1; # Do a quick check to make sure all mappings are integers # Many thanks to S.O. for clever string splitting: # http://stackoverflow.com/questions/918886/how-do-i-split-a-string-on-a-delimiter-in-bash for map in "$@" do IFS=: read -a from_to_array =~ ^-?2+$ ]] || [[ ! $ =~ ^-?3+$ ]]; then echo "forwardPorts port maps must go from an integer, to an integer (e.g. 443:4443)"; exit 1; fi mappings[$]=$ done # We're shooting for transactional consistency. Only manipulate iptables if all # the rules have a chance to succeed. for map in "$" do IFS=: read -a from_to_array to=$ sudo iptables -t nat -$append_or_delete PREROUTING -s 127.0.0.1 -p tcp --dport $from -j REDIRECT --to $to sudo iptables -t nat -$append_or_delete OUTPUT -s 127.0.0.1 -p tcp --dport $from -j REDIRECT --to $to done exit 0;
Перенаправление портов и сокетов через SSH туннели
SSH клиент под Linux можно использовать не только для безопасного подключения к консоли других компьютеров. Эта программа имеет ряд полезных функций, одной из которых является создание защищенных туннелей и эмуляция SOCKS5 прокси на локальной машине.
С помощью SSH-туннелей вы можете соединиться с сервером и использовать его сервисы через проброс портов и сокетов, и наоборот можно пробросить на сервер ресурсы со своего локального ПК, или создать прокси сервер с динамическим портом. И всё это с теми же средствами защиты данных, какие присутствуют при стандартном соединении с сервером по SSH.
Перенаправление внутреннего порта удалённого сервера на локальную машину
Если на сервере работает какой-то сервис и слушает внутренний порт, на который нет доступа извне, вы можете перебросить этот порт на ваш локальный компьютер.
Команда запускается на локальном ПК. Синтаксис команды выглядит так:
# ssh -L [локальный_адрес:]порт:удалённый_адрес:порт [user@]hostname
Если не указывать [локальный_адрес:] , соединение по умолчанию будет привязано к интерфейсу localhost.
Пример с перенаправлением удалённого порта
Допустим, на удаленном сервере 172.16.10.2 у вас открыт порт localhost:80 , который доступен только внутри этого сервера. Необходимо сделать так, чтобы этот порт был доступен с вашего компьютера уже по вашему локальному адресу localhost:8080 :
# ssh -L localhost:8080:localhost:80 user@172.16.10.2
Перенаправление вашего локального порта на удалённую машину
Если вы хотите перенаправить на удаленный сервер какой-то внутренний сервис с вашей локальной машины, то вместо опции -L следует использовать опцию -R .
Команда запускается на локальном ПК. Синтаксис команды:
# ssh -R [удаленный_адрес:]порт:локальный_адрес:порт [user@]hostname
Пример с перенаправлением локального порта
На локальном ПК у вас открыт ssh порт по адресу localhost:22 , недоступный извне. Вы не хотите или не имеете возможности напрямую открыть «в мир» свой ssh порт. Вам необходимо использовать удаленный сервер 172.16.10.2 , через который можно было бы подключиться к вашему ПК по ssh, используя порт 2222 .
Возможны два варианта подключения:
1. Перенаправление вашего ssh на внутренний адрес сервера. После установки туннеля, вам нужно будет зайти на сервер, и в его консоли подключиться по ssh к localhost:2222 , вы будете перенаправлены на ssh своего локального ПК. Команда для установки туннеля:
# ssh -R localhost:2222:localhost:22 user@172.16.10.2
2. Перенаправление вашего ssh порта на внешний адрес удалённого сервера, в этом случае заходить на сервер не нужно, вы попадёте на свой ПК просто подключившись к ssh 172.16.10.2:2222 из любого места.
Команда для привязки удалённого порта 2222 ко всем интерфейсам/адресам сервера:
# ssh -R 0.0.0.0:2222:localhost:22 user@172.16.10.2
# ssh -R \*:2222:localhost:22 user@172.16.10.2
Если вы хотите привязать порт 2222 к определённому адресу на сервере:
# ssh -R 172.16.10.2:2222:localhost:22 user@172.16.10.2
По умолчанию в целях безопасности все эти команды будут привязывать ваш удалённый порт только к localhost . Чтобы использовать внешние интерфейсы сервера, необходимо отредактировать опцию GatewayPorts в конфигурационном файле /etc/ssh/sshd_config на сервере:
# nano /etc/ssh/sshd_config GatewayPorts clientspecified # systemctl restart sshd
Не забудьте настроить firewall на сервере, иначе внешний порт будет недоступен. На CentOS 7 и выше используется firewalld.
Командами с опциями -L и -R вы можете пробросить не только порт, но и сокет. После выполнения этих команд (без других опций) вы попадете в консоль сервера, при этом ваш туннель уже будет работать. Вы можете добавить другие опции: -C для сжатия данных; -N запрещаем ввод команд; -q не выводим в консоль сообщения. Подробное описание команд смотрите в конце статьи.
Прокси сервер SOCKS5 через SSH
Сначала устанавливается соединение с удаленным ssh сервером и происходит туннелирование. Потом ssh эмулирует SOCKS5 сервер на локальной машине, к которому можно подключиться из любой поддерживающей SOCKS5 программы, например, из браузера, указав в качестве сервера localhost , а в качестве порта установленный вами порт.
Команда для организации SSH туннеля и локального SOCKS5 сервера:
# ssh -D localhost:4444 -C -N -q root@172.16.10.2
- -D localhost:4444 – Включает эмуляцию SOCKS5 с указанным портом. Вы можете использовать любой свободный порт. Можно не указывать localhost: , а указать только порт , соединение так же привяжется к localhost;
- -C – Соединение со сжатием данных, которое сэкономит некоторую часть трафика;
- -N – Указываем на то, что нам не нужно запускать никаких команд на удаленном сервере, используем соединение только как туннель;
- -q – Использовать «тихий режим». Не выводит большинство информационных и предупреждающих сообщений в консоль;
- root@172.16.10.2 – удаленный SSH сервер, с которым вы производите соединение.
После запуска ssh спросит пароль и останется работать в консоли, пока вы не прервете его по CTRL+C . Если вы не хотите занимать консоль работой ssh, вы можете запустить его в фоновом режиме, добавив к команде опцию -f .
Как пробросить порт в Linux
В этой статье поговорим о том, как можно перенаправить трафик с IP адреса (белого) на другой IP адрес (серый) использую утилиту iptables.
Начальные данные
У нас имеется компьютер под управлением linux, выступающий в роли маршрутизатора с одним внешним интерфейсом enp0s3 для доступа в Интернет (80.81.82.83) и внутренним enp0s8 интерфейсом Локальной сети (10.0.7.1). Требуется пробросить tcp порт (2121) с белого ip-адреса на серый ip-адрес Локальной сети порт (21).
Чаще всего проброс трафика используется, если мы находимся в локальной сети и от внешнего мира отделены шлюзом. Для того, чтобы открыть доступ для локальных служб (ssh, web, ftp и т.д.), нам необходимо пробросить порты. Поскольку в качестве шлюза мы будем использовать сервер на Linux, то осуществлять данные действия будем с помощью утилиты iptables.
Алгоритм проброса портов в iptables.
В принципе все довольно просто, необходимо добавить всего два правила в таблицу маршрутизации iptables. Но для начала нам нужно включить форвардинг пакетов на нашем сервере:
sudo echo 1 > /proc/sys/net/ipv4/ip_forward
Для автоматического включения открываем файл /etc/sysctl.conf и ищем там строку #net.ipv4.ip_forward=1 , убираем знак комментария.
Настройка port forwarding на Linux
Итак, приступим. Для выполнения поставленной задачи, перенаправление порта 2222 на порт 22 другой машины, необходимо добавить следующие правила iptables:
sudo iptables -A FORWARD -i enp0s3 -o enp0s8 -j ACCEPT
Это правило разрешает прохождение входящих пакетов внутрь сети.
Теперь опишем форвардинг (forwarding) пакетов:
sudo iptables -t nat -A PREROUTING -p tcp -d 80.81.82.83 --dport 2222 -j DNAT --to-destination 10.0.7.2:22 sudo iptables -t nat -A POSTROUTING -p tcp --sport 22 --dst 10.0.7.2 -j SNAT --to-source 80.81.82.83:2222
- Первая строка подменяет IP адрес приемника (белый IP) на внутренний (серый IP)
- Вторая адрес отправителя (серый IP) на внешний (белый IP).
- 10.0.7.2 — IP адрес машины в локальной сети, на который перенаправляет трафик.
- 80.81.82.83 — внешний IP адрес нашего сервера.
Перенаправления всего трафика
iptables -t nat -A PREROUTING -p tcp -d 80.81.82.83 -j DNAT --to-destination 10.0.7.2 iptables -t nat -A POSTROUTING -p tcp --dst 10.0.7.2 -j SNAT --to-source 80.81.82.83
Для сохранения наших правил необходимо создать файл и подгружать его при каждой перезагрузки системы, иначе правила iptables которые мы написали слетять. Для этого набираем в терминале следующее:
Содержимое файла по первому примеру:
#!/bin/sh # Перенаправляем ssh с 2222 на 22 IP-10.0.7.2 iptables -t nat -A PREROUTING -p tcp -d 80.81.82.83 --dport 2222 -j DNAT --to-destination 10.0.7.2:22 iptables -t nat -A POSTROUTING -p tcp -dst 10.0.7.2 --sport 22 -j SNAT --to-source 80.81.82.83:2222
Далее открываем файл interfaces
sudo nano /etc/network/interfaces
И добавляем в конце следующую строчку:
Данное выражение подгрузить правила iptables после перезагрузки системы.
Как посмотреть правила iptables
Посмотреть текущие правила iptables можно с помощью команды:
Chain PREROUTING (policy ACCEPT) target prot opt source destination DNAT tcp -- anywhere 80.81.82.83 tcp dpt:2222 to:10.0.7.2:22 Chain POSTROUTING (policy ACCEPT) SNAT tcp -- 10.0.7.2 anywhere tcp spt:ssh to:80.81.82.83:2222
Вот и все, на этом рассмотрение проброса портов в операционных системах под управлением Linux с помощью iptables завершено.