Вот примерная картина того, что я пытаюсь сделать:
клиент -> | VPN | -> сервер A -> | VPN | -> сервер B -> Интернет.
Сервер A и сервер B находятся в общедоступном Интернете с общедоступными IP-адресами, также у меня есть root-доступ к обоим серверам. Клиент находится за брандмауэром, но может подключиться к серверу A. Клиент НЕ МОЖЕТ подключиться к серверу B напрямую. Сервер A может подключиться к серверу B. Сервер B - это то место, откуда я хочу, чтобы пакеты выходили в Интернет. Мне нужно зашифровать как сообщения от клиента к A, так и от A к B, поскольку A и B не находятся в общей локальной сети, поэтому трафик между A и B проходит через общедоступную инфраструктуру.
Мне удалось настроить сервер IPSec VPN на A и подключиться к нему. Но я не могу понять, как правильно установить другую VPN от A к B и перенаправить трафик, приходящий к A от клиента к B.
Подсказки?
p.s. изначально я думал об использовании туннелей SSH для соединения A и B, а затем маршрутизации соответствующего пакета от клиента, прибывающего в A, к B через такой туннель. Но, как люди отмечали в комментариях, это не очень хорошая идея. Так что я открыт для любых предложений. Спасибо!
РЕДАКТИРОВАТЬ # 1
Служба VPN на сервере A настроена с помощью strongswan, который обрабатывает любое соединение между клиентами и сервером A. Я сделал это через ipsec.conf
:
# ipsec.conf - strongSwan IPsec configuration file
# basic configuration
config setup
charondebug="ike 2, knl 2, cfg 2, net 2, esp 2, dmn 2, mgr 2"
strictcrlpolicy=no
uniqueids=yes
cachecrls=no
conn ipsec-ikev2-vpn
auto=add
compress=no
type=tunnel # defines the type of connection, tunnel.
keyexchange=ikev2
fragmentation=yes
forceencaps=yes
dpdaction=clear
dpddelay=300s
rekey=no
left=%any
leftid=47.112.200.xxx # if using IP, define it without the @ sign
leftcert=vpn-server.cert.pem # reads the VPN server cert in /etc/ipsec.d/certs
leftsendcert=always
leftsubnet=0.0.0.0/0
right=%any
rightid=%any
rightauth=eap-mschapv2
rightsourceip=10.10.10.0/24 # IP address Pool to be assigned to the clients
rightdns=1.1.1.1,8.8.8.8 # DNS to be assigned to clients
rightsendcert=never
eap_identity=%identity # defines the identity the client uses to reply to an EAP Identity request.
С участием ufw
(в руководстве, которому я следовал, использовался ufw, но я могу работать с базовыми iptables
правила) настройки в /etc/ufw/before.rules
; Я пропустил часть, автоматически сгенерированную ufw, также я вручную разрешил udp на порте 500/4500 и tcp на порту 22:
#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
# ufw-before-input
# ufw-before-output
# ufw-before-forward
#
# Don't delete these required lines, otherwise there will be errors
*nat
-A POSTROUTING -s 10.10.10.0/24 -o eth0 -m policy --pol ipsec --dir out -j ACCEPT
-A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE
COMMIT
*mangle
-A FORWARD --match policy --pol ipsec --dir in -s 10.10.10.0/24 -o eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360
COMMIT
*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]
# End required lines
-A ufw-before-forward --match policy --pol ipsec --dir in --proto esp -s 10.10.10.0/24 -j ACCEPT
-A ufw-before-forward --match policy --pol ipsec --dir out --proto esp -d 10.10.10.0/24 -j ACCEPT
Вот как далеко я зашел. Отдельная попытка настроить межсайтовый VPN через strongswan IPSec между A и B не удалась из-за того, что порты 500 и 4500 заблокированы / ограничены: клиент может связаться с A через 500/4500, A не может связаться с B через 500/4500 и Я выставил все порты B, чтобы открыть Интернет для тестирования.
На данный момент единственный туннель, который мне удалось проложить между A и B, - это SSH socks (ssh -N -f -4 -D 1080 [server B ip]
с сервера A). Я думаю о перенаправлении трафика, выходящего из A, чей пункт назначения не является моим клиентским устройством, на B через этот SSH-туннель.
Что-то вроде:-A OUTPUT -p tcp --dport 443 -j REDIRECT --to-ports 1080
в ufw / iptables. (на самом деле это не работает, IP-адрес сервера A все еще отображается в программе проверки IP, а заблокированные веб-сайты по-прежнему недоступны)
Если вы используете IPSec в Linux (StrongSwan), маршрутизация политики выполняется с использованием ip xfrm policy
: политики с dir out
используются, чтобы решить, в какой туннель пересылать пакеты, а политики с dir in
и dir fwd
используются, чтобы решить, разрешить или отбросить пакет.
Предполагать serverA
имеет публичный IP 192.0.2.1
и частный IP 10.0.10.1
(вы можете прикрепить его к петлевому устройству), serverB
имеет публичный IP 198.51.100.1
и частный IP 10.0.20.1
, а VPN-клиенты получают IP-адрес в сети 10.0.30.0/24
. Вы можете установить туннель, используя swanctl.conf
на serverA вот так:
connections {
serverB {
version = 2
local_addrs=192.0.2.1
remote_addrs=198.51.100.1
local {
# serverA auth parameters
}
# serverB auth parameters
}
children {
tunnel {
local_ts = 10.0.10.0/24
remote_ts = 10.0.20.0/24
start_action = start
reqid = 10
priority = 1000
}
}
}
}
а на serverB аналогичная конфигурация с local*
и remote*
перевернутый.
Обратите внимание, что reqid
и priority
параметры фиксированы, поэтому их можно использовать в политиках. Это невозможно сделать в ipsec.conf
.
Для настройки маршрутизации политики вам необходимо на serverA:
10.0.30.0/16
на любой IP. Это делается автоматически, если вы установите local_ts = 0.0.0.0/0
в конфигурации подключения VPN-клиентов.Разрешить зашифрованный трафик для 10.0.30.0/24
из туннеля с serverB:
ip xfrm policy add src 0/0 dst 10.0.30/24 \
dir fwd priority 2000 \
tmpl src 198.51.100.1 dst 192.0.2.1 \
proto esp reqid 10 mode tunnel
Это работает аналогично ACCEPT
править в FORWARD
цепочка IP.
Перенаправить трафик из 10.0.30.0/24
на serverB:
ip xfrm policy add src 10.0.30/24 dst 0/0 \
dir out priority 2000 \
tmpl src 192.0.2.1 dst 198.51.100.1 \
proto esp reqid 10 mode tunnel
Приоритеты выше, чем автоматически устанавливаемые StrongSwan, поэтому, если эти политики установлены, пересылка разрешена. Если вы удалите эти политики, установленные StrongSwan будут разрешать трафик только между 10.0.10.0/24
и 10.0.20.0/24
. На serverB вы можете использовать те же политики, просто замените dir out
с участием dir fwd
.
PS: Конечно, вам также нужны некоторые правила iptables, чтобы serverA и serverB разрешали трафик ESP и IKE:
iptables -I INPUT -p esp -j ACCEPT
iptables -I INPUT -p udp -m multiport --dports 500,4500 -m comment --comment "IKE" -j ACCEPT
и некоторые правила отбрасывания, чтобы пакеты не выходили незашифрованными, если туннель выходит из строя:
iptables -A OUTPUT -o <external_interface> -s 10.0.0.0/16 -m policy --dir out --policy ipsec -j ACCEPT
iptables -A OUTPUT -o <external_interface> -s 10.0.0.0/16 -j DROP
редактировать: Поскольку вы используете ipsec.conf и эквивалентная конфигурация для вышеупомянутого swanctl.conf
является:
conn servers {
left=192.0.2.1
right=198.51.100.1
# The appropriate authentication leftauth, leftid, ...
leftsubnet = 10.0.10.0/24
rightsubnet = 10.0.20.0/24
auto = start
reqid = 10
}
С уважением к swanctl.conf
он имеет то преимущество, что он работает без изменений на обоих хостах, но не позволяет устанавливать priority
политик, поэтому вам нужно будет проверить, что StrongSwan выбирает для установки более высокого приоритета.
Расширяю мою подсказку в комментарии.
Я знаю, как создавать туннели в OpenVPN, так как использую его для подключения к сети IPv6, но идея должна быть такой же для IPSec.
Я начну с того, с чем я знаком (это IPv6), и покажу, как его можно преобразовать в IPv4.
Хотя дружеский отказ от ответственности:
Я не экспериментировал с многодомной маршрутизацией на IPv4, поэтому ваш пробег может отличаться.
Сервер A - версия IPv6
На моем сервере сетевой интерфейс туннеля OpenVPN называется tun0
.
На Сервер А редактировать /etc/iproute2/rt_tables
, поэтому у вас есть следующая запись:
200 openvpn
Это создаст специальную таблицу маршрутизации, которую мы можем использовать для маршрутизации VPN. Таблица маршрутизации по умолчанию называется main
.
Таблица openvpn
будет обрабатывать все пакеты, которые отправляются восходящим потоком (вы -> Интернет), в то время как таблица маршрутизации main
будет обрабатывать весь нисходящий трафик (Интернет -> вы).
ip -6 rule add priority 32000 iif tun0 to 2000::/3 table openvpn
ip -6 route add default via <ipv6 address> dev tun1 table openvpn
Обратите внимание, что вам нужно будет добавить правила для любого диапазона IP-адресов, который принадлежит вам.
Предполагая, что диапазон IPv6 2001: db8: cafe :: / 48 принадлежит вам, и у вас есть следующие настройки:
ip -6 route add unreachable 2001:db8:cafe::/48 table main
ip -6 route add 2001:db8:cafe:100::/64 via 2001:db8:cafe:1::100 dev tun0
Сервер A - версия IPv4
Версия IPv4 будет:
Нам по-прежнему нужна выделенная таблица маршрутизации, потому что нам нужно маршрутизировать трафик на основе происхождения, поэтому /etc/iproute2/rt_tables
еще нужна запись:
200 openvpn
Предполагая, что правила IPv4 в значительной степени аналогичны IPv6, вы получаете следующие команды для таблицы маршрутизации openvpn:
ip rule add priority 32000 iif tun0 to 0.0.0.0/0 table openvpn
ip route add default via <ipv4 address> dev tun1 table openvpn
Теперь я не уверен, есть ли какие-либо диапазоны IPv4, которые нужно перехватить на этом этапе (например, адреса RFC1918), поскольку общая идея в основном заключается в том, чтобы пересылать все, что входит в интерфейс. tun0
и отправь это на tun1
на диаграмме выше.
Сервер B - версия IPv6
Вот два подхода к перенаправлению трафика IPv6 в Интернет:
Если вы получили маршрутизируемый пул IPv6 от интернет-провайдера, подключенного к Server B
, тогда молодец. Таблица маршрутизации по умолчанию main
вероятно, может сделать все за вас.
Если у вас есть блок IPv6 от, скажем, Hurricane Electric, вам в основном потребуется та же настройка, что и на Server A
со специальной таблицей маршрутизации для восходящего потока и с использованием таблицы маршрутизации по умолчанию для нисходящего.
Сервер B - версия IPv4
Здесь, наверное, проще всего лечить Server B
как NAT, поэтому вам необходимо замаскировать все пакеты, поступающие из вашей сети, перед их отправкой в Интернет.