[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Linux bridge + хочется странного



Доброго времени суток!

Имеем следующую задачу:

Хост A: удаленный сервер (в реальности, дешевая виртуальная машина в
облаке) с выделенным белым IP адресом A.A.A.A. На хосте запущен
openvpn сервер в режиме моста, т.е., предполагается тунеллирование
трафика канального уровня (ethernet трафика). Кроме openvpn на
сервере запущен еще sshd. Никаких других сервисов на А запускать на
предполагается.

Конфигурация сети на A:

# The bridged primary network interface
auto br0
iface br0 inet static
       bridge_ports eth0
       bridge_stp off
       address A.A.A.A
       netmask 255.255.255.0
       broadcast A.A.A.255
       gateway A.A.A.1
       
# The persistent tap interface
auto tap0
iface tap0 inet manual
       up openvpn --mktun --dev tap0
       up brctl addif br0 tap0
       up ip link set dev tap0 up
       up /etc/network/ebtables
       down openvpn --rmtun --dev tap0
       down /etc/network/ebtables 

Интерфейс eth0 смотрит в локалку облака. tap0 смотрит в openvpn
туннель.
       
Хост B: локальный хост с доступом в инет, на котором запущен openvpn
клиент. Целеполагается, что при поднятии VPN туннеля до А хост В будет
в основном ходить в интернет через туннель (за исключением того, что
до самого хоста A он должен, ессно, ходить через физический
интерфейс).

Настройки сети на В (упрощены для ясности):

# The primary network interface
iface eth0 inet dhcp
        metric 10

# The tunnel
iface tap0 inet static
	address A.A.A.A
	netmask 255.255.255.0
	broadcast A.A.A.255
	gateway A.A.A.1	
	dns-nameservers 208.67.222.222 208.67.220.220
	pre-up /etc/network/fix-routes-to-hosts 192.0.2.1
	pre-down /etc/network/fix-routes-to-hosts

Интерфейс eth0 - физический, смотрит в инет. Интерфейс tap0
поднимается при запуске openvpn на B и смотрит в туннель. Да, это не
опечатка, на хосте В интерфейсу tap0 присваивается _тот же_ IP адрес,
что и у br0 на A. Такой странности хочется, чтобы в результате
a) иметь на tap0 на B белый IP адрес и избежать IP NAT на A;
б) представляться в локалке облака неотличимым клоном A;
в) ну и на самом деле просто потому, что интересно.

Чтобы при такой настройке можно было на хосте B отличить А от
локального интерфейса, на В делается следующее:

Вывод iptables-save (часть)

-------------------------------------------------------------------------
*rawpost
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -d 192.0.2.1/32 -j RAWDNAT --to-destination A.A.A.A/32
COMMIT
*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A PREROUTING -s A.A.A.A/32 -j RAWSNAT --to-source 192.0.2.1/32
COMMIT
-------------------------------------------------------------------------

(RAWSNAT в prerouting и RAWDNAT в postrouting доступны с
xtables-addons; объяснять почему нужно именно так, а стандартные SNAT
и DNAT здесь не годятся, я не буду, оставлю как задачку на
сообразительность)

То есть, для хоста B хост A виден, как 192.0.2.1 (этот адрес из
зарезервированного в IANA диапазона, реальных хостов с такими адресами
не существует).

Скрипт /etc/network/fix-routes-to-hosts добавляет нужный маршрут до
192.0.2.1 в таблицу маршрутизации на В (маршрут идет через физический
интерфейс eth0; извне хоста В, dst ip = A.A.A.A). Это нужно, так как
при поднятии tap0 появляется дефолтовый маршрут c меньшей метрикой,
идущий через tap0, и все IP пакеты будут заворачивать туда, а не в
eth0.

Возвращаемся к настройкам сервера A. Необходимо сделать так, чтобы TCP
пакеты, идущие из инета на 22-ой порт на A.A.A.A, доставлялись
локальному (на А) sshd. Также, UDP пакеты, идущие на 443-й порт,
должны доставляться привязанному к этому порту локальному (на А)
openvpn-у. Весь остальной трафик, включая трафик канального уровня,
входящий в A через eth0, должен перенаправляться в openvpn туннель и
"выныривать" на tap0 на хосте В, так что хост B эффективно оказывается
в локальной сети облака. При этом, ethernet фреймы адресованные A,
должны выглядеть, как адресованные напрямую B.

Обратно, весь ethernet трафик, идущий по туннелю от B к A, должен
выйти из eth0 на A и выглядеть, как исходящий непосредственно от A.
Так мы не напоремся на antispoofing protection в облаке.

Делаем это с помощью ebtables:


-- 
Stanislav


Reply to: