Dejte VPN klienta do kontejneru a získáte jeden jmenný prostor s tunelem uvnitř, ne hostitele, který veškerý svůj provoz směruje přes VPN. To jsou oddělené projekty a právě jejich slévání do jednoho vede k tomu, že kontejnery omylem skončí privilegované. Tato příručka pokrývá jen první případ: jeden prověřený obraz, jeden chráněný profil a klientský proces omezený na vlastní síťový jmenný prostor.

Začněte artefaktem, který už někdo schválil. Kroky níže předpokládají obraz, který obsahuje spustitelný soubor openvpn a úplný klientský profil s certifikátem a klíčovým materiálem už vyřešeným uvnitř připojení. Nevytvářejí software, nevydávají přihlašovací údaje a nepokrývají prostředí bez rootu ani nativní kontejnery Windows, z nichž každé mění odpověď.

Co kontejner dostane a co ne

Udržujte profil a vše, na co odkazuje, v místním adresáři s omezenými právy, připojeném pouze pro čtení. Relativní cesty uvnitř profilu se musí vyřešit v rámci tohoto připojení; to je detail, který lidé přehlédnou, když certifikát leží o adresář výš než profil a kontejner ho nikdy nevidí.

services:
  vpn:
    image: ${VPN_CLIENT_IMAGE:?set the reviewed image reference}
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    volumes:
      - ./vpn:/vpn:ro
    working_dir: /vpn
    entrypoint: ["openvpn"]
    command: ["--config", "/vpn/client.ovpn"]

Tento soubor dává tři věci a nevyžaduje nic dalšího. Odkaz na obraz by měl být připnut digestem, pokud to vaše zásada nasazení vyžaduje, a profilem by měl být prověřený, ne kopie, kterou někdo upravil přímo na hostiteli.

Pouze pro čtení zde znamená, že kontejner nemůže měnit vaše soubory na hostiteli; neznamená to, že nemůže přečíst soukromý klíč, který jste připojili. To je celý smysl připojení a také důvod, proč práva k souborům, vlastnictví a způsob, jak se tajemství dostalo na hostitele, stále hrají roli. Nikdy nepředávejte heslo na příkazovém řádku a nepečte ho do vrstvy obrazu, protože obojí přežívá na místech, která později nemůžete uklidit.

Schopnosti, entrypoint a past mezi nimi

Jsou potřeba dvě nastavení a dělají nesouvisející věci. NET_ADMIN umožňuje manipulaci s rozhraními a trasami ve jmenném prostoru kontejneru. Záznam zařízení /dev/net/tun umožňuje procesu vůbec otevřít tunelové zařízení. Udělení jednoho bez druhého vede k jasnému selhání, což je výhodné: chybějící zařízení TUN selhává při otevření, zatímco chybějící schopnost selhává, když se klient pokusí nakonfigurovat rozhraní.

Ani jedno z toho neospravedlňuje privileged: true. Privilegovaný kontejner dostane všechny schopnosti plus přístup k zařízením, a to je mnohem větší udělení, než tato úloha potřebuje. reference o oprávněních a schopnostech běhového prostředí vysvětluje, kam až toto udělení sahá. Pokud o to žádá chart nebo blogový příspěvek, nejprve zkontrolujte, zda požadavkem nebyla ve skutečnosti chybějící cesta k zařízení nebo chybějící schopnost.

Přepsání entrypoint je ta část, která kouše. Přímé volání openvpn je správné pro obyčejný obraz a špatné pro každý produktový obraz, jehož startovní skript připravuje pravidla firewallu, soubory resolveru nebo přihlašovací údaje před spuštěním démona. Přepsání tohoto skriptu přeskočí přípravu a nechá vás ladit tunel, který vznikl v napůl nakonfigurovaném jmenném prostoru.

Spouštějte klienta na popředí a nechte ho být hlavním procesem kontejneru. Proces, který se daemonizuje, okamžitě skončí, kontejner se restartuje ve smyčce a protokoly, které potřebujete, jsou rozesety mezi restarty, které všechny vypadají stejně.

Ověřujte zevnitř jmenného prostoru, ne z hostitele

Zvedněte stack, potvrďte v logu, že klient dosáhl připojeného stavu, a potom prohlédněte jmenný prostor, který tunel skutečně drží.

docker compose up -d
docker compose logs --tail 40 vpn
docker compose exec vpn ip -br addr
docker compose exec vpn ip route

Seznam adres by měl ukázat tunelové rozhraní s adresou z poolu a směrovací tabulka by měla ukázat posílané destinace mířící na něj. Pokud rozhraní chybí, klient se nikdy nedostal k jeho vytvoření. Pokud existuje, ale žádná trasa ho nepoužívá, hledejte v push nebo v možnostech tras.

Potom otestujte destinaci, na které vám záleží, ze jmenného prostoru, který má tunel používat, pomocí aplikace, ne jen pingem. Překlad jmen je samostatné selhání, které stojí za výslovné otestování: posílaná adresa DNS sama neaktualizuje resolver kontejneru a samostatný klient, který push ignoruje, bude překládat jména přes to, co obraz nakonfiguroval.

Odpojený stav je součástí smlouvy

Chování při opětovném připojení potřebuje vlastní kontrolu, protože zásada restartu dokazuje, že se proces restartuje, a neříká nic o tom, co dělá provoz mezitím. Zastavte tunel, zkuste zamýšlenou destinaci a sledujte, zda je spojení odmítnuto, visí, nebo tiše uspěje přes běžnou trasu kontejneru. Poslední výsledek je ten, na kterém záleží, a je neviditelný ve zdravém logu.

Pokud úloha nikdy nesmí použít běžnou cestu, navrhněte to výslovně pomocí pravidel firewallu a signálu připravenosti ve jmenném prostoru. Kill switch je zásada, kterou píšete a testujete, ne vlastnost, kterou zdědíte tím, že spustíte klienta v kontejneru.

Nakonec pamatujte na hranici: tyto trasy žijí ve jmenném prostoru kontejneru a nenahrazují směrovací tabulku hostitele. Pravidla přeposílání, překladu a firewallu v Dockeru zůstávají součástí vnější cesty a publikovaný port není rozhraní VPN.

Související články