Проброс (forwarding) портов на FreeBSD

()

Проброс портов (он же "port forwarding" и "traffic redirection") - достаточно популярная технология, позволяющая сделать доступными сервисы, "спрятанные" в локальной сети. Доступ осуществляется при помощи перенаправления трафика этих сервисов с внешнего адреса маршрутизатора в локальную сеть, к серверу, который и будет отвечать на запросы.

Кроме того, при помощи проброса портов можно сделать доступным сервер не имеющий реального IP-адреса, подключив его внешнему VPN-серверу и настроив на нём проброс портов. Далее будет показано как настроить проброс портов на OpenVPN-сервере под управлением FreeBSD.

За основу возьмём описанный ранее OpenVPN-сервер. На нём необходимо пробросить порты tcp/80, tcp/443 и udp/53 на компьютер, подключенный к серверу с логином "webserver". Примерная схема показана на рисунке:

Port forwarding

Для начала нужно связать IP-адреса и пользователей (чтобы пользователи всегда получали один и тот же адрес). Для этого нужно в директории, указанной в опции "client-config-dir" OpenVPN-сервера создать для каждого логина по файлу, описывающему настройки для этого пользователя. В качестве имён файлов используются логины пользователей (Так как указана опция "username-as-common-name").

Для примера создадим файл для пользователя "webserver" (в данном случае его имя будет "/usr/local/etc/openvpn/ccd/webserver"), следующего содержания:

ifconfig-push 172.16.251.134 172.16.251.133

Здесь "172.16.251.134" - IP-адрес клиента, а "172.16.251.133" - адрес, который у клиента будет маршрутом по умолчанию.

Общая методика расчёта этих адресов такая: указанная у OpenVPN в параметре "server" подсеть разбивается на подсети с маской 255.255.255.252 и в кажой полученной подсети:

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

Пользуясь данной методикой надо написать конфигурацию для кажого логина. Теоретически можно этого не делать, но тогда клиенты клиенты, не имеющие постоянного адреса, будут получать его динамически и случайно могут получить чужой (OpenVPN это никак не контролирует).

Закончив конфигурацию OpenVPN на всякий случай стоит перезапустить OpenVPN-сервер:

/usr/local/etc/rc.d/openvpn restart

Приступаем к настройке проброса портов. Открываем файл "/etc/pf.rules" и приводим к виду:

set limit { states 20000, frags 5000 }
set timeout { adaptive.start 6000, adaptive.end 12000 }
set skip on { lo0 }


if_ext = "vtnet0"
if_int = "tun0"
net_int = "172.16.251.128/27"
# На этот IP будем пробрасывать порты
forward_to = "172.16.251.134"
# Порты TCP для проброса
forward_ports_tcp = "{ 80, 443 }"
# Порты UDP для проброса
forward_ports_udp = "{ 53 }"

set block-policy drop
set state-policy if-bound

scrub in


# NAT
nat pass on $if_ext from $net_int -> ($if_ext) static-port

# Собственно проброс портов
rdr on $if_ext inet proto tcp from any to $if_ext port $forward_ports_tcp -> $forward_to
rdr on $if_ext inet proto udp from any to $if_ext port $forward_ports_udp -> $forward_to

# Разрешаем весь трафик на loopback-интерфейсе
pass quick on lo0 all


# Разрешаем серверу его собственный исходящий трафик
pass out quick on $if_ext inet proto tcp from ($if_ext) to any flags S/SA keep state
pass out quick on $if_ext inet proto { udp, icmp } from ($if_ext) to any keep state

# Разрешаем доступ к серверу по SSH
pass in quick on $if_ext inet proto tcp from any to ($if_ext) port 22 flags S/SA keep state

# Разрешаем доступ к нашему OpenVPN-серверу
pass in quick on $if_ext inet proto udp from any to ($if_ext) port 443

# Разрешаем ICMP
pass in quick on $if_ext inet proto icmp from any to ($if_ext)

# Разрешаем всё клиентам нашего сервреа
pass in quick on $if_int from $net_int to any keep state

# Разрешаем обращения с внешних адресов к нашему внутреннему серверу
# Входящие пакеты на внешнем интерфейсе
pass in quick on $if_ext proto tcp from any to $forward_to port $forward_ports_tcp
pass in quick on $if_ext proto udp from any to $forward_to port $forward_ports_udp
# Исходящие пакеты на внутреннем интерфейсе
pass out quick on $if_int proto tcp from any to $forward_to port $forward_ports_tcp
pass out quick on $if_int proto udp from any to $forward_to port $forward_ports_udp


# Блокируем весь остальной трафик
block drop all

Логика здесь такая:

  1. Правила, начинающиеся с "rdr" модифицируют входящие пакеты, меняя в них адрес получателя.
  2. Правила вида "pass in quick on $if_ext proto tcp from any to $forward_to..." разрешают таким модифицированным пакетам "входить" во внешний интерфейс.
  3. Правила "pass out quick on $if_int proto tcp from any to $forward_to..." разрешают таким модифицированным пакетам "выходить" из внутреннего интерфейса в сторону клиента.

Применяем правила:

pfctl -f /etc/pf.rules

Посмотреть текущие правила перенаправления можно командой:

pfctl -s nat|grep rdr

Проверить что всё работает можно просто обратившиесь браузером к IP-адресу вашего OpenVPN-сервера. Если всё работает то должен открыться сайт, расположенный на вашем внутреннем веб-сервере. В случае проблем первым делом надо проверить подключен ли пользователь "webserver" к вашему серверу:)

На этом всё. Приятной работы!

Ключевые слова: freebsd, openvpn, проброс портов, port forwarding, pf.

Комментарии:

Новый комментарий



© 2006-2017 Вадим Калинников aka MooSE