Metu VPN-klienton en kontejneron kaj vi ricevas unu nomspacon kun tunelo interne, ne gastiganton, kiu plusendas sian tutan trafikon tra VPN. Tiuj estas apartaj projektoj, kaj trakti ilin kiel unu estas la maniero, kiel kontejneroj hazarde fariĝas privilegiaj. Ĉi tiu gvidlibro kovras nur la unuan: unu reviziitan bildon, unu protektitan profilon kaj klientan procezon limigitan al sia propra reta nomspaco.

Komencu per artefakto, kiun iu jam aprobis. La subaj paŝoj supozas bildon, kiu enhavas la plenumeblan dosieron openvpn kaj kompletan klientan profilon kun sia atestilo kaj ŝlosila materialo jam solvitaj ene de la muntado. Ili ne konstruas programaron, ne eldonas akreditaĵojn kaj ne kovras senradikajn plenummediojn nek denaskajn Windows-kontejnerojn, el kiuj ĉiu ŝanĝas la respondon.

Kion la kontejnero ricevas kaj kion ne

Tenu la profilon kaj ĉion, al kio ĝi referencas, en loka dosierujo kun limigitaj permesoj, muntita kiel nurlega. Relativaj vojoj ene de la profilo devas solviĝi ene de tiu muntado; tio estas detalo, kiun homoj maltrafas, kiam atestilo staras unu dosierujon super la profilo kaj la kontejnero neniam vidas ĝin.

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"]

Tiu dosiero donas tri aferojn kaj petas nenion alian. La bilda referenco estu fiksita per digesto, se via deploja politiko tion diras, kaj la profilo estu la reviziita, ne kopio, kiun iu redaktis surloke sur la gastiganto.

Nurlega ĉi tie signifas, ke la kontejnero ne povas modifi viajn dosierojn sur la gastiganto; ĝi ne signifas, ke la kontejnero ne povas legi la privatan ŝlosilon, kiun vi muntis. Tio estas la tuta senco de la muntado, kaj ankaŭ kial dosierpermesoj, posedo kaj la maniero, kiel la sekreto venis al la gastiganto, ankoraŭ gravas. Neniam transdonu pasvorton sur la komanda linio kaj neniam enbaku ĝin en bildan tavolon, ĉar ambaŭ postvivas en lokoj, kiujn vi ne povos poste purigi.

Kapabloj, entrypoint kaj la kaptilo inter ili

Du agordoj necesas kaj ili faras nesrilatajn laborojn. NET_ADMIN permesas manipuladon de interfacoj kaj itineroj ene de la nomspaco de la kontejnero. La aparata ero /dev/net/tun permesas al la procezo entute malfermi la tunelan aparaton. Doni unu sen la alia produktas klaran malsukceson, kio estas oportuna: mankanta TUN-aparato malsukcesas ĉe malfermo, dum mankanta kapablo malsukcesas, kiam la kliento provas agordi la interfacon.

Nek unu nek la alia pravigas privileged: true. Privilegia kontejnero ricevas ĉiun kapablon plus aparatan aliron, kaj tio estas multe pli granda dono ol tiu ĉi laborŝarĝo bezonas. La referenco pri plenumaj privilegioj kaj kapabloj klarigas, kiom malproksimen tiu dono etendiĝas. Se chart aŭ blogafiŝo petas ĝin, unue kontrolu, ĉu la postulo fakte estis mankanta aparatvojo aŭ mankanta kapablo.

La anstataŭigo de entrypoint estas la parto, kiu mordas. Rekte alvoki openvpn estas ĝuste por ordinara bildo kaj malĝuste por iu ajn produkta bildo, kies starta skripto preparas fajroŝirmilajn regulojn, solvilajn dosierojn aŭ akreditaĵojn antaŭ ol lanĉi la demonon. Anstataŭigi tiun skripton saltas la preparadon kaj lasas vin sencimigi tunelon, kiu leviĝis en duone agordita nomspaco.

Rulu la klienton en la malfono kaj lasu ĝin esti la ĉefa procezo de la kontejnero. Procezo, kiu demoniĝas, tuj eliras, la kontejnero restartas en buklo, kaj la protokoloj, kiujn vi bezonas, estas disigitaj tra restartoj, kiuj ĉiuj aspektas identaj.

Kontrolu de interne de la nomspaco, ne de la gastiganto

Levigu la stakon, konfirmu en la protokolo, ke la kliento atingis konektitan staton, kaj poste inspektu la nomspacon, kiu efektive tenas la tunelon.

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

La adreslisto devus montri tunelan interfacon kun adreso el la baseno, kaj la itinera tabelo devus montri la puŝitajn celojn montrantajn al ĝi. Se la interfaco mankas, la kliento neniam atingis la punkton krei ĝin. Se ĝi ekzistas sed neniu itinero uzas ĝin, la loko por serĉi estas la push aŭ la itinero-opcioj.

Poste testu la celon, kiu gravas al vi, el la nomspaco, kiu devus uzi la tunelon, per la aplikaĵo kaj ne nur per ping. Nomsolvado estas aparta malsukceso, kiun indas eksplicite testi: puŝita DNS-adreso ne ĝisdatigas la solvilon de kontejnero per si mem, kaj memstara kliento, kiu ignoras la push, solvos nomojn per tio, kion la bildo agordis.

La malkonektita stato estas parto de la kontrakto

Rekonekta konduto bezonas sian propran kontrolon, ĉar restartpolitiko pruvas, ke la procezo restartas, kaj diras nenion pri tio, kion la trafiko faras intertempe. Haltigu la tunelon, provu la celitan celon kaj observu, ĉu la konekto estas rifuzata, pendas aŭ silente sukcesas tra la ordinara itinero de la kontejnero. La lasta rezulto estas la grava, kaj ĝi estas nevidebla en sana protokolo.

Se la laborŝarĝo neniam rajtas uzi la ordinaran vojon, projektigu tion eksplicite per fajroŝirmilaj reguloj kaj pretecsignalo ene de la nomspaco. Kill switch estas politiko, kiun vi skribas kaj testas, ne eco, kiun vi heredas per rulado de kliento en kontejnero.

Fine, memoru la limon: ĉi tiuj itineroj vivas en la nomspaco de la kontejnero kaj ne anstataŭigas la enrutan tabelon de la gastiganto. La reguloj de plusendado, tradukado kaj fajroŝirmilo en Docker restas parto de la ekstera vojo, kaj publikigita pordo ne estas VPN-interfaco.

Rilataj artikoloj