задача и цель
наличие пакетов часть WireGuard envelope (пакеты UDP, транспортирующие зашифрованные полезные данные), не подлежащие инкапсуляции туннеля сами несмотря на использование того же IP внутри туннеля как вне туннеля.
метод
поскольку стек маршрутизации (IP-маршрут, правило ip...) работает на уровне 3 (IP), а не на уровне 4 (UDP, используемый конвертом), это не может быть решено только со стеком маршрутизации без дополнительной помощи отличить пакеты конверта от пакетов" данных".
к счастью, можно пометить пакет меткой (чисто внутренне, на skbuff пакета, конечно, не на проводе). Затем тег можно повторно использовать в качестве fwmark для стека маршрутизации. Средства (я знаю), способные пометить пакеты, являются iptables, nftables ... и WireGuard себя.
в виду того что Wireguard однако может маркировать пакеты после заключения никакая потребность использовать iptables / nftables как дополнительная помощь для маршрутизации.
в настоящее время в wireguard есть раздражающее ограничение (которое, безусловно, существует по уважительным причинам, вероятно, связанным с его обработкой маршрутизации): я не мог найти способ установить два узла с одинаковыми значениями разрешенных IP-адресов. Так что это не возможно просто установить:
AllowedIps = 172.29.244.0/25,172.29.248.128/25
на каждой конечной точке. Попытка этого удалит позволенные IP-адреса на предыдущих оконечных точках с тем же значением. Установка любого другого перекрывающегося диапазона (например, изменение маска), будет принята, но не позволит некоторым из перекрывающихся узлов работать. Конечно, разрешение только 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",, }'|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 }'|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 }'|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,),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