Приложение във VPN пространство от имена е недостъпно от LAN
Мрежовото пространство от имена дава на една програма собствен тунел и собствен loopback. Публикувайте само неговия порт чрез socat-препращане или двойка veth, вместо през хоста.
Услугата ви работи на машината, тунелът е вдигнат, а браузърът на бюрото ви все още не получава отговор. Нищо не е счупено в обичайния смисъл: приложението слуша вътре в мрежово пространство от имена, и този стек е невидим за LAN. Неговият loopback принадлежи на пространството от имена, затова клиент на друга машина няма адрес, който да стига до порта. Един съзнателен прескок или една двойка veth оправя това, без да мести останалата част от хоста.
Защо нищо не отговаря на LAN адреса
Пространството от имена е пълен мрежов стек: интерфейси, маршрути, правила на защитната стена и частен loopback. Процес, стартиран през ip netns exec, вижда този стек и нищо друго, затова адресът, който той завързва, се разрешава само вътре в пространството от имена. Собственият 127.0.0.1 на хоста е напълно различен loopback.
Затова curl на хоста се проваля, докато същата команда вътре в пространството от имена успява. Приложението е здраво; адресът просто не съществува в стека на хоста.
Публикувайте един порт с прескок през socat
socat свързва двата стека в потребителско пространство, което е достатъчно, когато трябва да премине един-единствен TCP порт. Хост страната слуша на LAN и за всяка приета връзка стартира втори socat вътре в пространството от имена, който се свързва с loopback на приложението. Вътрешният процес достига до приложението точно както би го направил локален клиент. Нищо в маршрутизацията на пространството от имена не се променя, затова приложението продължава да използва тунела като единствен изход.
socat TCP-LISTEN:9100,reuseaddr,fork EXEC:'ip netns exec vpn socat STDIO tcp-connect:127.0.0.1:9100',nofork
Външният процес се нуждае от root или от възможността да влезе в пространството от имена. Ако VPN отпадне, приложението губи пътя си и публикуваният порт се затваря, а точно това поведение искате от затвор.
Използвайте двойка veth, когато преминава повече от един порт
Двойка veth е правилният отговор, когато трябва да преминат няколко порта или протокола, или когато други хостове трябва да започват връзки. Единият край остава в хоста, другият се премества в пространството от имена, а малка /30 дава на двете страни стабилен адрес. След това маршрут на хоста изпраща адреса на пространството от имена през двойката.
ip link add veth0 type veth peer name veth1
ip link set veth1 netns vpn
ip addr add 10.77.0.1/30 dev veth0
ip link set veth0 up
ip netns exec vpn ip addr add 10.77.0.2/30 dev veth1
ip netns exec vpn ip link set veth1 up
Не добавяйте маршрут по подразбиране през хоста, освен ако не възнамерявате да счупите затвора. Тунелът трябва да остане изходът, затова през двойката е достъпен само публикуваният адрес на услугата. Дайте на пространството от имена и собствен resolver файл, защото ip netns exec чете /etc/netns/vpn/resolv.conf и без него разрешаването на имена вътре в затвора е празно.
Тествайте от друга машина, не от хоста
Стартирайте теста от втора машина, защото хостът може да достигне локален слушател по пътища, които не казват нищо за LAN. Първо проверете към какво приложението действително се е завързало вътре в пространството от имена, след което се свържете с публикувания адрес отвън. Завързването към всеки адрес там не разширява затвора, защото wildcard пак принадлежи на пространството от имена и LAN не може да го види.
ip netns exec vpn ss -lntp
Ако връзката от хоста работи, а връзката от LAN не, липсващото звено е прескокът или маршрутът, а не адресът на завързване. Стартирайте OpenVPN вътре в пространството от имена, вместо да местите там работещо tun устройство, защото местенето на интерфейса го изключва и може да изчисти маршрути, които след това не можете да поправите отвън. Дръжте командите за възстановяване на конзолата, а не вътре в затвора.