LINUX.ORG.RU

История изменений

Исправление mradermaxlol, (текущая версия) :

Вроде разобрался. Что я понял из всей этой истории:

  • Самое главное: я изначально воевал не туда, бонусом ещё и не понял, как должна работать сеть в моём воображении.
    • Изначально я хотел, чтобы был сервер с виртуалками и туннелем WireGuard с машинами извне, и чтобы при этом можно было обращаться к виртуалкам как к полноценным системам со своим айпишником, и чтобы они по этим самым айпишникам могли сами пробрасывать туннели wg во внешний мир, с которыми потом работали бы внешние машины-клиенты.
    • Но для таких извращений нужны свободные айпишники от хостера, которых в моём случае нет (а к этим айпишником, как я понимаю, уже и прикручиваются bridge-соединения). Тогда задача изменилась: нужно с дефолтной NAT-сетью всего-то пробросить требуемый порт виртуалки на какой-нибудь свободный порт сервера-хоста, для чего нужно… Да, всего лишь прочитать туториал по iptables. Я обязательно выживу осилю парочку.
    • По итогу задача оказалась тривиальной. Максимально просто виртуалкам присваиваются нужные адреса, потом для нужных адресов и портов адаптируется хук - shell-надстройка над iptables. И… Всё. В моём случае с указанными ниже конфигами можно подключаться RDP-клиентом по serverip:32101 к ВМ win10n1 (при включённом в ней RDP), т.е. порт 3389 виртуалки пробрасывается в порт 32101 хоста.

Мини-гайд и по совместительству итог моих мучений:

  • Хитрых сетевых конфигов тут нет: в случае с systemd-networkd нужны рабочая сеть (у меня это ethernet без DHCP) и рабочий WireGuard через связку .netdev и .network. Шаблоны для wg, вдруг кому-то пригодятся:
# 99-wg0.netdev
[NetDev]
Name=wg0
Kind=wireguard
Description=WireGuard tunnel (wg0)

[WireGuard]
ListenPort=42069
PrivateKey=host_private_key

# client
[WireGuardPeer]
PublicKey=peer_public_key
AllowedIPs=10.69.0.1/32
# 99-wg0.network
[Match]
Name=wg0

# server wg address
[Network]
Address=10.228.0.1/32

# route for client
[Route]
Gateway=10.228.0.1
Destination=10.69.0.1/32

На клиенте нужно указать в свойствах интерфейса приватный ключ и адрес в wg-сети, после чего задать peer с публичным ключом, конечной точкой (public ip:listening port) и wg-адресом этого самого peer’а.

  • Для libvirt нужна дефолтная NAT-сеть с привязкой конкретных IP виртуальным машинам по их MAC’у;
  • Также для libvirt нужен qemu hook, суть которого описана здесь; конкретно в этом случае я адаптировал хук @frunobulax под свои нужды (ещё раз спасибо за помощь), chmod +x /etc/libvirt/hooks/qemu, перезапустить libvirtd и в общем-то всё:
#!/bin/bash

if [ "$1" = "win10n1" ]; then
	GUEST_IP=192.168.122.101
	GUEST_PORT=3389
	HOST_PORT=32101

	if [[ "$2" = "started" ]]; then
		iptables -I FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
		iptables -t nat -I PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
	fi
	if [[ "$2" = "stopped"  ]]; then
		iptables -D FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
		iptables -t nat -D PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
	fi
fi

if [ "$1" = "win10n2" ]; then
	GUEST_IP=192.168.122.102
	GUEST_PORT=3389
	HOST_PORT=32102

	if [[ "$2" = "started" ]]; then
		iptables -I FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
		iptables -t nat -I PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
	fi
	if [[ "$2" = "stopped"  ]]; then
		iptables -D FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
		iptables -t nat -D PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
	fi
fi
  • Этого достаточно для конфигурации, расписанной в начале этой простыни: подключение к вм по wg-адресу сервера с портом, который пробрасывается виртуалке.

TL;DR всё гениальное просто. А ещё надо осваивать iptables, а то как лох.

Исходная версия mradermaxlol, :

Вроде разобрался. Что я понял из всей этой истории:

  • Самое главное: я изначально воевал не туда, бонусом ещё и не понял, как должна работать сеть в моём воображении.
    • Изначально я хотел, чтобы был сервер с виртуалками и туннелем WireGuard с машинами извне, и чтобы при этом можно было обращаться к виртуалкам как к полноценным системам со своим айпишником, и чтобы они по этим самым айпишникам могли сами пробрасывать туннели wg во внешний мир, с которыми потом работали бы внешние машины-клиенты.
    • Но для таких извращений нужны свободные айпишники от хостера, которых в моём случае нет (а к этим айпишником, как я понимаю, уже и прикручиваются bridge-соединения). Тогда задача изменилась: нужно с дефолтной NAT-сетью всего-то пробросить требуемый порт виртуалки на какой-нибудь свободный порт сервера-хоста, для чего нужно… Да, всего лишь прочитать туториал по iptables. Я обязательно выживу осилю парочку.
    • По итогу задача оказалась тривиальной. Максимально просто виртуалкам присваиваются нужные адреса, потом для нужных адресов и портов адаптируется хук - shell-надстройка над iptables. И… Всё. В моём случае с указанными ниже конфигами можно подключаться RDP-клиентом по serverip:32101 к ВМ win10n1 (при включённом в ней RDP), т.е. порт 3389 виртуалки пробрасывается в порт 32101 хоста.

Мини-гайд и по совместительству итог моих мучений:

  • Хитрых сетевых конфигов тут нет: в случае с systemd-networkd нужны рабочая сеть (у меня это ethernet без DHCP) и рабочий WireGuard через связку .netdev и .network. Шаблоны для wg, вдруг кому-то пригодятся:
# 99-wg0.netdev
[NetDev]
Name=wg0
Kind=wireguard
Description=WireGuard tunnel (wg0)

[WireGuard]
ListenPort=42069
PrivateKey=host_private_key

# client
[WireGuardPeer]
PublicKey=peer_public_key
AllowedIPs=10.69.0.1/32
# 99-wg0.network
[Match]
Name=wg0

# server wg address
[Network]
Address=10.228.0.1/32

# route for client
[Route]
Gateway=10.228.0.1
Destination=10.69.0.1/32

На клиенте нужно указать в свойствах интерфейса приватный ключ и адрес в wg-сети, после чего задать peer с публичным ключом, конечной точкой (public ip:listening port) и wg-адресом этого самого peer’а.

  • Для libvirt нужна дефолтная NAT-сеть с привязкой конкретных IP виртуальным машинам по их MAC’у;
  • Также для libvirt нужен qemu hook, суть которого описана здесь; конкретно в этом случае я адаптировал хук @frunobulax под свои нужды (ещё раз спасибо за помощь), chmod +x /etc/libvirt/hooks/qemu, перезапустить libvirtd и в общем-то всё:
#!/bin/bash

if [ "$1" = "win10n1" ]; then
	GUEST_IP=192.168.122.101
	GUEST_PORT=3389
	HOST_PORT=32101

	if [[ "$2" = "started" ]]; then
		iptables -I FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
		iptables -t nat -I PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
	fi
	if [[ "$2" = "stopped"  ]]; then
		iptables -D FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
		iptables -t nat -D PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
	fi
fi

if [ "$1" = "win10n2" ]; then
	GUEST_IP=192.168.122.102
	GUEST_PORT=3389
	HOST_PORT=32102

	if [[ "$2" = "started" ]]; then
		iptables -I FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
		iptables -t nat -I PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
	fi
	if [[ "$2" = "stopped"  ]]; then
		iptables -D FORWARD -o virbr0 -p tcp -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
		iptables -t nat -D PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
	fi
fi
  • Этого достаточно для конфигурации, расписанной в начале этой простыни: подключение к вм по wg-адресу сервера с портом, который пробрасывается виртуалке. ` TL;DR всё гениальное просто. А ещё надо осваивать iptables, а то как лох.