Я пытаюсь соединить два гипервизора через Интернет. Оба гипервизора используют KVM для виртуализации, и я вручную создал мосты для сети виртуальных машин, которая в настоящее время работает.
Я хотел бы использовать Wireguard для подключения мостов виртуальных машин на обоих этих гипервизорах, чтобы виртуальные машины можно было переносить с одного гипервизора на другой без каких-либо изменений маршрутизации / сети в самой виртуальной машине.
Однако перед тем, как начать, я понял, что понятия не имею, как настроить Wireguard таким образом, чтобы мосты на обоих гипервизорах являются видимый для другого гипервизора, но сами гипервизоры не появляются в VPN, так что виртуальные машины не могут напрямую подключаться / атаковать гипервизоры.
Может ли Wireguard это сделать? Или это было бы невозможно из-за того, как Wireguard работает высоко в стеке OSI, а не на уровне кадра Ethernet?
Сможет ли кто-нибудь сказать, можно ли использовать Wireguard для «слепого» соединения двух сетей? Или хосты всегда будут отображаться в сети? Может ли это позволить какое-нибудь другое решение VPN? Или мне лучше использовать брандмауэр для блокировки хостов, к которым я не хочу получать доступ?
Заранее спасибо!
Wireguard работает на уровне 3 (маршрутизируемый IP-пакет), а мост работает на уровне 2 (коммутируемый кадр Ethernet). Так что Wireguard не может этого сделать. Этот вопрос уже был задан, и автор Wireguard дал ответ в списке рассылки Wireguard: Мост wg и нормальные интерфейсы?.
Таким образом, перед прохождением проволочной защиты необходим дополнительный герметизирующий слой. Я уверен, что есть несколько вариантов (среди них VXLAN также доступно на Linux).
Я сделал пример, используя ГРЕТАП и пространства имен (а не фактические гипервизоры и виртуальные машины). Я обнаружил, что для того, чтобы не заставлять локальный трафик виртуальных машин иметь более ограниченный размер пакета, чем это возможно, необходима обработка фрагментации, но GRETAP
имеет некоторые ограничения, как описано здесь: Мост GRE, IPsec и NFQUEUE. Я решил обойти это, используя искажение полезной нагрузки nftables а не NFQUEUE и пользовательское пространство.
Также обратите внимание, что RFC 6864 объясняет, что фрагментированные пакеты следует ограничивать большую часть времени до 6,4 Мбит / с из-за ограничений поля IP ID, которые в настоящее время работают медленно, но проходят через туннель с строгими проверками целостностирасслабляет его.
Здесь (поддельные) виртуальные машины связаны мостом и не имеют других возможностей подключения. Они не могут видеть ничего, кроме самих себя: они не могут видеть (поддельные) гипервизоры, соединяющие два моста с помощью gretap + wireguard. Просто запустите этот сценарий bash, который создает и настраивает несколько пространств имен. Протестировано с nftables 0.9.2 и ядром 5.2.x.
#!/bin/bash
if ip netns id | grep -qv '^ *$' ; then
printf 'ERROR: leave netns "%s" first\n' $(ip netns id) >&2
exit 1
fi
hosts='vm11 vm12 hyp1 router hyp2 vm21 vm22'
for ns in $hosts; do
ip netns del $ns 2>/dev/null || :
ip netns add $ns
ip netns exec $ns sysctl -q -w net.ipv6.conf.default.disable_ipv6=1
ip netns exec $ns sysctl -q -w net.ipv4.icmp_echo_ignore_broadcasts=0
done
for ns in $hosts; do
ip -n $ns link set lo up
done
link_ns () {
ip -n $1 link add name "$3" type veth peer netns $2 name "$4"
ip -n $1 link set dev "$3" up
ip -n $2 link set dev "$4" up
}
for h in 1 2; do
ip -n hyp$h link add bridge0 address 02:00:00:00:00:0$h type bridge
ip -n hyp$h link set bridge0 up
for n in 1 2; do
link_ns vm$h$n hyp$h eth0 port$n
ip -n hyp$h link set dev port$n master bridge0
ip -n vm$h$n address add 10.0.$h.$n/16 dev eth0
done
link_ns hyp$h router eth0 site$h
done
ip -n router address add 192.0.2.1/24 dev site1
ip -n router address add 198.51.100.1/24 dev site2
ip -n hyp1 address add 192.0.2.100/24 dev eth0
ip -n hyp1 route add default via 192.0.2.1
ip -n hyp2 address add 198.51.100.200/24 dev eth0
ip -n hyp2 route add default via 198.51.100.1
privkey1=$(wg genkey)
privkey2=$(wg genkey)
pubkey1=$(printf '%s' "$privkey1" | wg pubkey)
pubkey2=$(printf '%s' "$privkey2" | wg pubkey)
for h in 1 2; do
ip -n hyp$h link add name wg0 type wireguard
ip -n hyp$h address add 10.100.0.$h/24 dev wg0
ip -n hyp$h link set dev wg0 up
done
ip netns exec hyp1 wg set wg0 private-key <(printf '%s' "$privkey1") listen-port 11111 peer "$pubkey2" endpoint 198.51.100.200:22222 allowed-ips 10.100.0.2
ip netns exec hyp2 wg set wg0 private-key <(printf '%s' "$privkey2") listen-port 22222 peer "$pubkey1" endpoint 192.0.2.100:11111 allowed-ips 10.100.0.1
for h in 1 2; do
ip -n hyp$h link add name gt0 mtu 1500 type gretap remote 10.100.0.$((3-$h)) local 10.100.0.$h nopmtud
ip -n hyp$h link set gt0 master bridge0
ip -n hyp$h link set gt0 up
ip netns exec hyp$h nft -f /dev/stdin << EOF
table ip filter {
chain output {
type filter hook output priority 0; policy accept;
ip protocol gre ip saddr 10.100.0.$h ip daddr 10.100.0.$((3-$h)) ip frag-off set ip frag-off & 0xbfff counter
}
}
EOF
done
Пример (с большими задержками с удаленной стороны):
# ip netns exec vm11 ping -b 10.0.255.255
WARNING: pinging broadcast address
PING 10.0.255.255 (10.0.255.255) 56(84) bytes of data.
64 bytes from 10.0.1.1: icmp_seq=1 ttl=64 time=0.048 ms
64 bytes from 10.0.1.2: icmp_seq=1 ttl=64 time=0.194 ms (DUP!)
64 bytes from 10.0.2.2: icmp_seq=1 ttl=64 time=0.646 ms (DUP!)
64 bytes from 10.0.2.1: icmp_seq=1 ttl=64 time=0.685 ms (DUP!)
64 bytes from 10.0.1.1: icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from 10.0.1.2: icmp_seq=2 ttl=64 time=0.154 ms (DUP!)
64 bytes from 10.0.2.2: icmp_seq=2 ttl=64 time=0.476 ms (DUP!)
64 bytes from 10.0.2.1: icmp_seq=2 ttl=64 time=0.490 ms (DUP!)
^C
--- 10.0.255.255 ping statistics ---
2 packets transmitted, 2 received, +6 duplicates, 0% packet loss, time 1050ms
rtt min/avg/max/mdev = 0.048/0.344/0.685/0.243 ms