История изменений
Исправление 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, а то как лох.