Проброс портов (он же "port forwarding" и "traffic redirection") - достаточно популярная технология, позволяющая сделать доступными сервисы, "спрятанные" в локальной сети. Доступ осуществляется при помощи перенаправления трафика этих сервисов с внешнего адреса маршрутизатора в локальную сеть, к серверу, который и будет отвечать на запросы.
Кроме того, при помощи проброса портов можно сделать доступным сервер не имеющий реального IP-адреса, подключив его внешнему VPN-серверу и настроив на нём проброс портов. Далее будет показано как настроить проброс портов на OpenVPN-сервере под управлением FreeBSD.
За основу возьмём описанный ранее OpenVPN-сервер. На нём необходимо пробросить порты tcp/80, tcp/443 и udp/53 на компьютер, подключенный к серверу с логином "webserver". Примерная схема показана на рисунке:
Для начала нужно связать 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
Логика здесь такая:
- Правила, начинающиеся с "rdr" модифицируют входящие пакеты, меняя в них адрес получателя.
- Правила вида "pass in quick on $if_ext proto tcp from any to $forward_to..." разрешают таким модифицированным пакетам "входить" во внешний интерфейс.
- Правила "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" к вашему серверу:)
На этом всё. Приятной работы!