Вопрос или проблема
У меня сервер Ubuntu 24.04.1 LTS, работающий под управлением Strongswan.
Я узнал, что он использует nftables вместо iptables для своего фаервола.
При настройке VPN я могу подключиться с клиентом, но не могу получить доступ к хостам в интернете по IP-адресу или разрешить имена.
Я думаю, что мне не хватает некоторых правил пересылки, но не уверен, как их перевести/применить в формате nft.
Какие правила мне нужно применить, чтобы IPV4 и IPV6 работали для клиентов?
Ниже представленная конфигурация началась с руководства по wireguard, и я изменил ее, чтобы включить другие службы на машине. Я нашел некоторые ссылки из openwrt и strongswan и попытался это перевести, но, похоже, не достиг результата. Я буду признателен за любые советы.
Спасибо.
Я добавил эти правила в попытке пропустить трафик ipsec.
цепочка prerouting
meta ipsec exists ip saddr $IKE_NETS counter accept
цепочка inbound_world
meta l4proto ah accept
meta l4proto esp accept
/etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
define DEV_WG = wg0
define DEV_OVPN = tun0
define DEV_VPN = { $DEV_WG, $DEV_OVPN }
define DEV_WORLD = eth0
define IP_OVPN = 10.8.0.0/24
define IP_WORLD_V4 = public_v4_ip
define IP_WORLD_V6 = public_v6_ip
define PORT_IKE = { 500, 4500 }
define PORT_WG = 51820
define PORT_OVPN = 1194
define PORT_VPN = { $PORT_IKE, $PORT_WG, $PORT_OVPN }
define DEV_LOCAL_NETS = { $DEV_VPN }
define DEV_OUT_NETS = { $DEV_WORLD }
#define IKE_NETS = { 172.16.252.0/24, fd5a:4c1f:8d73:f583::/64 } <- не понравился адрес Ipv6
define IKE_NETS = { 172.16.252.0/24 }
# `inet` применяется как к IPv4, так и к IPv6.
table inet global {
map port_forwards_tcp_ipv4 {
type ipv4_addr . inet_service : ipv4_addr . inet_service
# давайте перенаправим порт для нашего торрента. Наш 12345 на 12345 на 172.16.0.2
elements = { $IP_WORLD_V4 . 12345 : 172.16.0.2 . 12345 }
}
map port_forwards_tcp_ipv6 {
type ipv6_addr . inet_service : ipv6_addr . inet_service
# давайте перенаправим порт для нашего торрента. Наш 12345 на 12345 на fdf5:6028:947d:1234::2
elements = { $IP_WORLD_V6 . 12345 : [fdf5:6028:947d:1234::2] . 12345}
}
map port_forwards_udp_ipv4 {
type ipv4_addr . inet_service : ipv4_addr . inet_service
# давайте перенаправим порт для нашего торрента. Наш 12345 на 12345 на 172.16.0.2
elements = { $IP_WORLD_V4 . 12345 : 172.16.0.2 . 12345 }
}
map port_forwards_udp_ipv6 {
type ipv6_addr . inet_service : ipv6_addr . inet_service
# давайте перенаправим порт для нашего торрента. Наш 12345 на 12345 на fdf5:6028:947d:1234::2
elements = { $IP_WORLD_V6 . 12345 : [fdf5:6028:947d:1234::2] . 12345}
}
chain inbound_world {
# принимаем ping (icmp-echo-request) в диагностических целях.
# Тем не менее, это также позволяет проработкам обнаружить, что этот хост активен.
# Этот пример принимает их в пределах определенного ограничения скорости:
#
# icmp type echo-request limit rate 5/second accept
# Разрешить пакеты настройки IPv6
icmpv6 type {nd-neighbor-solicit,nd-neighbor-advert,nd-router-solicit,
nd-router-advert,mld-listener-query,destination-unreachable,
packet-too-big,time-exceeded,parameter-problem} accept
# разрешить SSH
tcp dport { 22 } accept
# http, https
tcp dport 80 accept
tcp dport 443 accept
# smtp, submission, smtps
tcp dport 25 accept
tcp dport 587 accept
tcp dport 465 accept
# pop3, pop3s
tcp dport 110 accept
tcp dport 995 accept
# imap, imaps
tcp dport 143 accept
tcp dport 993 accept
# разрешить VPN-соединение
udp dport { $PORT_VPN } accept
meta l4proto ah accept
meta l4proto esp accept
}
chain inbound_vpn {
# принимаем ping (icmp-echo-request) в диагностических целях.
icmp type echo-request limit rate 5/second accept
# Разрешить пакеты настройки IPv6
icmpv6 type {nd-neighbor-solicit,nd-neighbor-advert,nd-router-solicit,
nd-router-advert,mld-listener-query,destination-unreachable,
packet-too-big,time-exceeded,parameter-problem} accept
# разрешить DNS и SSH из частной сети
tcp dport { 22, 53 } accept
udp dport { 53 } accept
}
chain inbound {
# по умолчанию блокировать весь трафик
type filter hook input priority filter; policy drop;
# Разрешить трафик от установленных и связанных пакетов, блокировать недопустимые
ct state vmap { established : accept, related : accept, invalid : drop }
# Разрешить dnat (перенаправление портов)
ct status dnat accept
# разрешить трафик локальной петли, все остальное перейти к цепочке для дальнейшей оценки
iifname vmap { lo : accept, $DEV_WORLD : jump inbound_world, $DEV_VPN : jump inbound_vpn}
# остальное блокируется вышеуказанной политикой
}
chain forward {
type filter hook forward priority filter; policy drop;
# Разрешить трафик от установленных и связанных пакетов, блокировать недопустимые
ct state vmap { established : accept, related : accept, invalid : drop }
# Разрешить перенаправление портов
ct status dnat accept
# соединения из внутренних сетей в внешние сети разрешены
iifname $DEV_LOCAL_NETS oifname $DEV_OUT_NETS accept
# остальное блокируется вышеуказанной политикой
meta ipsec exists ip saddr $IKE_NETS counter accept
}
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
dnat ip addr . port to ip daddr . tcp dport map @port_forwards_tcp_ipv4
dnat ip6 addr . port to ip6 daddr . tcp dport map @port_forwards_tcp_ipv6
dnat ip addr . port to ip daddr . udp dport map @port_forwards_udp_ipv4
dnat ip6 addr . port to ip6 daddr . udp dport map @port_forwards_udp_ipv6
meta ipsec exists ip saddr $IKE_NETS counter accept
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
# Скрыть IP-адреса из локальных сетей в интернет.
# Мы используем SNAT, потому что у нас статический IP, и он будет работать быстрее, чем MASQUERADE
iifname $DEV_LOCAL_NETS oifname $DEV_WORLD snat ip to $IP_WORLD_V4
iifname $DEV_LOCAL_NETS oifname $DEV_WORLD snat ip6 to $IP_WORLD_V6
}
}
Пулы Strongswan:
pools {
primary-pool-ipv4 {
addrs = 172.16.252.0/24
dns = 172.16.252.1, 8.8.8.8, 9.9.9.9
split_exclude = 172.16.0.0/12
}
primary-pool-ipv6 {
addrs = fd5a:4c1f:8d73:f583::/64
dns = 2620:fe::fe, 2620:fe::9
}
Ответ или решение
Для решения вашей проблемы с доступом к интернету через VPN на основе StrongSwan и использования nftables, необходимо убедиться, что у вас настроены правильные правила маршрутизации и NAT. Зафиксируем основные правки и добавим необходимые правила, чтобы ваши клиенты могли выходить в интернет как по IPv4, так и по IPv6.
Шаги по настройке
-
Обновление правила NAT в цепочке
postrouting
: Необходимо убедиться, что у вас правильно указан интерфейс, который используется для выхода в интернет. Судя по вашему коду, вы используете$DEV_WORLD
. Убедитесь, что этот интерфейс действительно соответствует вашему внешнему сетевому интерфейсу. -
Добавление необходимых цепочек и правил:
- В цепочку
forward
нужно добавить правила, которые позволят трафику проходить от клиентов VPN к внешнему интернету и обратно. - Также важно добавить правила разрешения ICMP-трафика, чтобы клиенты могли проверять соединение.
- В цепочку
-
Пример полной конфигурации
nftables
:
Убедитесь, что ваш файл/etc/nftables.conf
выглядит примерно так:
#!/usr/sbin/nft -f
flush ruleset
define DEV_VPN = { wg0, tun0 }
define DEV_WORLD = eth0
define IP_WORLD_V4 = public_v4_ip
define IP_WORLD_V6 = public_v6_ip
define IKE_NETS = { 172.16.252.0/24, fd5a:4c1f:8d73:f583::/64 }
table inet global {
chain input {
type filter hook input priority 0; policy drop;
# разрешаем ICMP
ip protocol icmp accept
ipv6-icmp accept
# подключение SSH
tcp dport { 22 } accept
# разрешаем любой установленный трафик
ct state established accept
# разрешаем доступ из VPN
iifname $DEV_VPN accept
}
chain forward {
type filter hook forward priority 0; policy drop;
# разрешаем установленный и связанный трафик
ct state { established, related } accept
# разрешаем трафик из VPN в интернет
iifname $DEV_VPN oifname $DEV_WORLD accept
# разрешаем трафик обратно
iifname $DEV_WORLD oifname $DEV_VPN accept
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
# SNAT для клиентов, которые выходят в интернет
oifname $DEV_WORLD snat to $IP_WORLD_V4
oifname $DEV_WORLD snat to $IP_WORLD_V6
}
}
Примечания
- Убедитесь, что в строках с
snat to
в цепочкеpostrouting
указаны правильные публичные IP-адреса. - Параметр
$DEV_WORLD
должен быть заменен на реальный интерфейс, который отвечает за подключение к интернету (например,eth0
). - Firewall по умолчанию установлен на
drop
, чтобы ограничить доступ только для поддерживаемых соединений. - Вам также нужно убедиться, что на клиентских машинах правильно настроены DNS-серверы, чтобы они могли резолвить имена. Если используете DNS-серверы, указанные в настройках
strongswan
, убедитесь, что они доступны из вашей сети.
Проверка доступа
После применения новых правил проверьте, могут ли клиенты подключаться к интернету. Для диагностики выполните следующие команды на клиенте:
- Проверьте, можно ли пинговать IP-адреса (например,
ping 8.8.8.8
). - Попробуйте резолвить доменные имена (например,
ping google.com
). - Убедитесь, что ваши клиенты могут обращаться к описанным вами DNS-серверам.
Если возникают ошибки, вы можете просмотреть журналы StrongSwan и nftables для диагностики проблем с соединением.
Эти изменения должны помочь вам настроить доступ к интернету для клиентов VPN. Если у вас есть дополнительные вопросы или проблемы, не стесняйтесь задавать их.