Допустим, у нас есть машины с двумя интерфейсами: ens160 и wg0 .

Допустим, у нас есть маршруты, подобные приведенным ниже: 172.29.248.128/25 dev ens160 proto kernel scope link src 172.29.248.134 192.168.2.0/24 dev wg0 proto kernel scope link src 192.168.2.2 Наша первая машина имеет ips: 172.29.248.134, 192.168. 2,2

Есть вторая машина: endpoint: 172.29.244.20:51820 allowed ips: 192.168.2.1/32

Первая машина может подключаться ко второй машине по обоим IP-адресам, 172.29.244.20 и 192.168.2.1.

Теперь я хочу, чтобы, когда первая машина пыталась достичь 172.29.244.20, она должна проходить через интерфейс wg0 . Что-то вроде IP-адреса назначения для этого конкретного IP-адреса, с 172.29.244.20 до 192.168.2.1

Является ли это возможным? Если да, можем ли мы переписать его на второй машине, поэтому, если он получает что-либо на интерфейсе wg0 от 192.168.2.2, исходный ip должен быть изменен обратно на 172.29.248.134 и передан в ens160?

Можно ли это сделать исключительно с помощью ip route? Или нам нужны iptables?

@dirkt Спасибо, это бы нормально работало, и я попробовал, но, похоже, ситуация немного сложнее. На самом деле все сложнее, потому что я пытаюсь настроить шифрование между машинами для кластера Kubernetes, но из-за проблем с сетевым плагином (Calico), в некоторой степени более прозрачным, чем при непосредственном использовании 192.168.2.0/24. По сути, есть инкапсуляция IP-в-IP через VPN-туннель 3-го уровня и множество правил iptables. wg0 - это интерфейс Wireguard (VPN), он имеет подсеть 192.168.2.0/24. Я использую 192.168.2.1/32, чтобы указать один IP для VPN, потому что я хочу создать ячеистую сеть. Я не могу указать 192.168.2.0/24 для разрешенных IP-адресов, потому что wireguard не разрешает одну и ту же подсеть для нескольких пиров.

Теперь я вижу, что пересылка всего трафика на этот ip через wg0 может быть глупой идеей, потому что я вижу, что при использовании tcpdump на машине отправка ping работает правильно (запросы ICMP видны), но на принимающей машине wg0 ничего не отображается.

Я спросил об этом на IRC в Wireguard, и проблема, вероятно, заключается в следующем: The problem is that outgoing traffic to the other wireguard endpoint is no longer routed over ens160. But looped into the wireguard interface.

Хорошо, но здесь может быть решение, из документации проводника. FwMark — a 32-bit fwmark for outgoing packets. If set to 0 or "off", this option is disabled. May be specified in hexadecimal by prepending "0x". Optional.

Я нашел статью об этой "рекурсивной проблеме VPN", но мои сетевые навыки довольно плохие. Что я должен сделать для маршрутизации трафика на 172.29.244.20/32 via 192.168.2.2 dev wg0 за исключением пакетов, помеченных определенным fwmark?

2 ответа2

0

Вы пропустили полное описание вашей сети, поэтому я предполагаю, что хост A (первый) и хост B (второй) напрямую подключены к одному и тому же сегменту на wg0 на хосте A с 192.168.2.2/24 , и хост B с 92.168.2.1/?? (вероятно, ошибка /32 вас есть - каждый хост в сегменте должен иметь одинаковую маску сети, поэтому, скорее всего, вы имеете в виду /24). Если это не правильно, пожалуйста, отредактируйте свой вопрос с описанием вашей сети, сетевых масок и IP-адресов в конечных точках.

Далее, если вы хотите выполнить маршрутизацию, используйте функции маршрутизации ядра. Я не знаю, почему так много людей думают, что iptables для маршрутизации. Это неважно, что вы читаете в интернете. Если обычной маршрутизации недостаточно, используйте политику маршрутизации. Если политики маршрутизации недостаточно, вы можете подумать о том, чтобы делать забавные вещи с помощью iptables .

Функции маршрутизации ядра оптимизированы для быстрого принятия решений о маршрутизации. Это не верно для iptables .

(Извините за напыщенную речь, но это моя любимая мозоль).

Таким образом, в вашем случае все, что вам нужно сделать, это добавить маршрут на A, чтобы сообщить A, что он должен маршрутизировать через 192.168.2.2 при попытке связаться с 72.29.244.20:

ip route add 72.29.244.20/32 via 192.168.2.2 dev wg0

Затем пакеты с адресом назначения 72.29.244.20 будут отправлены на 192.168.2.2 , то есть на хост B. Когда хост B получит их, он обнаружит, что у него уже есть интерфейс с этим адресом, и примет их.

Вы можете даже подумать о расширении с 72.29.244.20/32 до 72.29.244.0/24 или чего-то еще, если в этом диапазоне есть другие хосты, к которым можно более удобно добраться по этому маршруту.

0

Проблема и цель

Наличие пакетов в конверте WireGuard (UDP-пакеты, транспортирующие зашифрованную полезную нагрузку) не подвергается туннельной инкапсуляции, несмотря на использование того же IP внутри туннеля, что и вне туннеля.

метод

Поскольку стек маршрутизации (ip route, ip rule ...) работает на уровне 3 (IP), а не на уровне 4 (UDP, используется конвертом), это невозможно решить только с помощью стека маршрутизации без дополнительной помощи. отличать пакеты конверта от пакетов данных.

К счастью, можно пометить пакет с пометкой (чисто внутри, на skbuff пакета, конечно, не на проводе). Затем тег можно повторно использовать в качестве fwmark для стека маршрутизации. Средства (я знаю), способные пометить пакеты, - это iptables, nftables ... и сам WireGuard.

Поскольку Wireguard, тем не менее, может маркировать пакеты после инкапсуляции, нет необходимости использовать iptables/nftables в качестве дополнительной помощи для маршрутизации.

В настоящее время существует раздражающее ограничение в wireguard (которое, безусловно, существует по уважительным причинам, связанным, вероятно, с обработкой маршрутизации): я не смог найти способ установить два одноранговых узла с одинаковыми значениями allow-ips. Так что невозможно просто установить:

AllowedIps = 172.29.244.0/25,172.29.248.128/25

на каждой конечной точке. Попытка этого удалит разрешенные ips на предыдущих конечных точках с тем же значением. Установка любого другого перекрывающегося диапазона (например, изменение маски) будет принята, но не позволит работать некоторым перекрывающимся узлам. Разумеется, работает только IP-адрес единственной удаленной конечной точки. Это единственный способ для правильной работы всей сетки.

Решение

Различают пакеты-конверты и туннелированные пакеты с пометкой. Нет даже необходимости указывать, каким UDP-портом он должен быть, WireGuard обрабатывает эту часть. Используйте эту отметку, чтобы сделать "исключение из исключения" для выбора маршрута.

Выбор сделан

Согласно комментарию OP, пересылка пакетов не требуется, поэтому пересылка не тестировалась.

Сделанный здесь выбор заключается в том, чтобы пометить пакеты, которые не будут входить в туннель, с помощью WireGuard (другое рабочее решение, использующее iptables вместо WireGuard для маркировки пакетов, могло бы сделать обратное и пометить пакеты, поступающие в туннель).

инструкции

Пример конфигурации:

# ip -4 -br addr show dev ens160
ens160@if7       UP             172.29.248.132/25 
# ip route
default via 10.0.3.1 dev eth0 
10.0.3.0/24 dev eth0 proto kernel scope link src 10.0.3.147 
172.29.244.0/25 via 172.29.248.129 dev ens160 
172.29.248.128/25 dev ens160 proto kernel scope link src 172.29.248.132 

# wg show wg0
interface: wg0
  public key: 7FsVTBuIDNQsWj9flHWwMt+kCaE8urEE9bCwcvz6CBM=
  private key: (hidden)
  listening port: 51820

peer: +NJdQr+piwid1iuC58rbnXFgGo/vZ9d8Gs3xvl3/TxI=
  endpoint: 172.29.248.134:51820
  allowed ips: (none)
  transfer: 14.74 KiB received, 34.35 KiB sent

peer: KrZWEupjHGoHTywwWhg4XXQSyFl/disav7/pyhOK/1Q=
  endpoint: 172.29.244.20:51820
  allowed ips: (none)
  transfer: 11.06 KiB received, 15.65 KiB sent

Поскольку, в конце концов, все может пройти через туннель, используя те же IP-адреса, сеть 192.168.2.0/24 больше не используется. Поскольку ни одно правило маршрутизации не будет ссылаться на эти IP-адреса, их даже можно удалить: у wg0 будет нулевой IP-адрес (все еще можно сохранить их при желании):

# ip addr flush dev wg0

Сконфигурируйте wg0 для маркировки пакетов конвертов с произвольно выбранным значением (здесь 9):

# wg set wg0 fwmark 9

Сконфигурируйте каждый хост WireGuard для принятия IP-адреса конечной точки в туннеле, вот цель:

# wg show wg0|awk 'BEGIN { RS="\n\n" } /^peer/ { printf "wg set wg0 peer %s allowed-ips %s\n",$2,$4 }'|cut -d: -f1 | sh

Который сейчас дает:

# wg show wg0
interface: wg0
  public key: 7FsVTBuIDNQsWj9flHWwMt+kCaE8urEE9bCwcvz6CBM=
  private key: (hidden)
  listening port: 51820
  fwmark: 0x9

peer: +NJdQr+piwid1iuC58rbnXFgGo/vZ9d8Gs3xvl3/TxI=
  endpoint: 172.29.248.134:51820
  allowed ips: 172.29.248.134/32
  transfer: 14.74 KiB received, 34.35 KiB sent

peer: KrZWEupjHGoHTywwWhg4XXQSyFl/disav7/pyhOK/1Q=
  endpoint: 172.29.244.20:51820
  allowed ips: 172.29.244.20/32
  transfer: 11.06 KiB received, 15.65 KiB sent

Добавьте маршруты в (произвольно выбранную) таблицу 200 маршрутизации, указав IP-адрес хоста в качестве источника (чтобы избежать, к сожалению, выбора IP-адреса из несвязанного интерфейса) ...

... или только один раз, маршруты для обеих локальных сетей, но для этого потребуется использование WireGuard для любого IP-трафика с любым узлом в локальных сетях:

# localip=$(ip -4 -br addr show dev ens160|awk '{ print $3 }'|cut -d/ -f1)
# ip route add 172.29.244.0/25   dev wg0 table 200 src $localip
# ip route add 172.29.248.128/25 dev wg0 table 200 src $localip

Который дает:

# ip route show table 200
172.29.244.0/25 dev wg0 scope link src 172.29.248.132 
172.29.248.128/25 dev wg0 scope link src 172.29.248.132 

... либо добавьте на одноранговые маршруты:

# localip=$(ip -4 -br addr show dev ens160|awk '{ print $3 }'|cut -d/ -f1)
# wg show wg0|awk 'BEGIN { RS="\n\n" } /^peer/ { printf "ip route add %s dev wg0 table 200 src %s\n",gensub(":.*$","",1,$4),localip }' localip=$localip | sh

Что дает вместо здесь:

# ip route show table 200
172.29.244.20 dev wg0 scope link src 172.29.248.132 
172.29.248.134 dev wg0 scope link src 172.29.248.132 

Заранее исправьте проблемы типа «курица и яйцо», которые будут введены правилом после этого, используя непосредственно основную таблицу маршрутизации для пакетов, помеченных WireGuard (эти пакеты 51820/UDP):

# ip rule add priority 32000 fwmark 9 lookup main

"Вставить" после просмотра таблицы 200. На самом деле будут совпадать только пакеты с маршрутами, указанными выше для WireGuard, и они будут использовать туннель через wg0, остальные пакеты продолжат (обычную) основную таблицу:

# ip rule add priority 32100 lookup 200

Это правило 32100 и таблица 200, которые заменяют обычную маршрутизацию, выполняемую внутри wg0, когда для него установлены IP-адреса.

Который сейчас дает:

# ip rule
0:  from all lookup local 
32000:  from all fwmark 0x9 lookup main 
32100:  from all lookup 200 
32766:  from all lookup main 
32767:  from all lookup default 

Увы, теперь фильтр обратного пути запускается для входящего трафика, отличного от WireGuard, поступающего из обычного интерфейса (здесь ens160), когда теперь ожидается wg0. Это включает пакеты ответа ARP, необходимые для нахождения одноранговых узлов в одной и той же локальной сети, а также шлюза в другую локальную сеть (у меня нет хорошего объяснения этому). Поэтому для обычного интерфейса rp_filter должен быть установлен в свободный режим (здесь ens160):

echo 2 > /proc/sys/net/ipv4/conf/ens160/rp_filter

С этими настройками, повторенными для других одноранговых узлов, теперь все одноранговые узлы могут обмениваться данными друг с другом, используя свой собственный IP, как если бы не было туннеля (в сетке, потенциально использующей до n * (n-1)/2 туннелей).

Пример: хост получает один пинг и отвечает:

# tcpdump -n -s0 -i wg0 -p
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wg0, link-type RAW (Raw IP), capture size 262144 bytes
05:22:51.553463 IP 172.29.244.20 > 172.29.248.132: ICMP echo request, id 2083, seq 1, length 64
05:22:51.553525 IP 172.29.248.132 > 172.29.244.20: ICMP echo reply, id 2083, seq 1, length 64

В то время как на маршрутизаторе зашифрованный трафик виден (с некоторыми издержками после, вероятно, потому что не было никакой недавней активности):

# tcpdump -n -s0 -i br248 -p
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br248, link-type EN10MB (Ethernet), capture size 262144 bytes
05:22:51.553317 ARP, Request who-has 172.29.248.132 tell 172.29.248.129, length 28
05:22:51.553358 ARP, Reply 172.29.248.132 is-at 2e:02:6e:cf:6d:4f, length 28
05:22:51.553383 IP 172.29.244.20.51820 > 172.29.248.132.51820: UDP, length 128
05:22:51.553583 IP 172.29.248.132.51820 > 172.29.244.20.51820: UDP, length 128
05:22:51.554112 IP 172.29.248.132.51820 > 172.29.244.20.51820: UDP, length 148
05:22:51.555198 IP 172.29.244.20.51820 > 172.29.248.132.51820: UDP, length 92
05:22:51.555748 IP 172.29.248.132.51820 > 172.29.244.20.51820: UDP, length 32

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .