L'host continua a rispondere in SSH dopo che una VPN a tunnel completo è attiva, mentre un servizio pubblicato con Docker sulla stessa macchina tace. Il listener non ha nulla di sbagliato: il container è in esecuzione, la mappatura della porta esiste e il pacchetto arriva. Il container è sano e la richiesta lo raggiunge davvero. Ciò che cambia è da dove parte la risposta quando Linux sceglie la sua rotta, e quella differenza decide quale dei due progetti qui sotto ti serve.

Segui la tupla attraverso il NAT di destinazione

Prendi un host a 192.0.2.10 che pubblica TCP 2222 verso un container a 172.30.240.5:22. Una richiesta da 198.51.100.25 viene tradotta prima di raggiungere il container, e il container risponde come se stesso.

WAN request:      198.51.100.25 -> 192.0.2.10:2222
after DNAT:       198.51.100.25 -> 172.30.240.5:22
container reply:  172.30.240.5:22 -> 198.51.100.25

Alla decisione di routing dell'host la risposta porta ancora l'indirizzo sorgente del container. La traduzione inversa ripristina più tardi la tupla pubblicata, ed è per questo che il pacchetto sembra sbagliato esattamente nel momento in cui viene scelta la rotta.

Perché una regola solo per l'host la manca

Una regola che seleziona la tabella WAN solo per i pacchetti provenienti da 192.0.2.10 copre i demoni dell'host e manca del tutto questa risposta inoltrata. L'indirizzo sorgente della risposta è 172.30.240.5, non l'host.

La sovracorrezione consiste nell'instradare tutto dal container attraverso il WAN, il che esenta dalla VPN anche le connessioni in uscita non correlate del container. È una politica diversa da quella richiesta, e di solito sorprende qualcuno più avanti.

La corrispondenza post-DNAT è un altro hook

La documentazione di Docker sui firewall osserva che il normale filtraggio utente vede la destinazione dopo il DNAT, quindi far corrispondere la porta pubblicata 2222 in una regola normale non equivale a far corrispondere la porta 22 del container. Se la tupla originale conta, usa il meccanismo di destinazione originale supportato invece di indovinare quale porta sia visibile.

Questa confusione di hook produce regole che sembrano corrette e non corrispondono mai. Controlla i contatori sulla regola stessa prima di riscrivere la politica. Una regola senza alcun riscontro ti dice che viene valutata in un punto in cui il pacchetto non arriva mai.

Progetto A: portare la decisione come stato della connessione

Un mark di connessione può portare la decisione di ingresso attraverso la traduzione, ma deve essere ripristinato sul pacchetto prima della ricerca di rotta che conta. Le fasi sono:

  1. Riserva un campo del mark e una priorità di regola che non entrino in collisione con Docker, la VPN o un altro proprietario di politica.
  2. Identifica solo la nuova connessione WAN prevista in un punto pre-DNAT in cui il tracciamento delle connessioni è disponibile.
  3. Registra la decisione sul mark di connessione, senza forzare la richiesta originale stessa nella tabella WAN.
  4. Nella direzione della risposta, ripristina solo i tuoi bit del mark sul pacchetto prima del routing.
  5. Seleziona una tabella WAN completa con sufficiente anticipo perché una regola VPN non possa vincere per prima.

Quella tabella ha bisogno delle rotte connesse reali e del gateway. Ha anche bisogno di un comportamento definito quando la rotta manca. Una caduta silenziosa nel tunnel è il risultato peggiore, perché la configurazione sembra ancora funzionare. Fallisci chiuso e registralo invece.

Progetto B: terminare sull'host

Un frontend configurato deliberatamente sul lato host, come un proxy TCP o un reverse proxy davanti al container, mantiene la risposta originata dall'indirizzo dell'host. Le regole scritte per l'host si comportano allora come previsto, e il container resta sulla sua rete privata.

Il costo è un'altra parte mobile con la propria configurazione, la gestione degli indirizzi sorgente e i controlli di accesso. Di solito è il confine supportato più semplice, ed è spesso la risposta giusta quando la politica di routing sarebbe mantenuta da una sola persona che potrebbe andarsene.

Verifica il cambiamento, non l'intenzione

Apri una nuova connessione autorizzata dal lato pubblico e conferma che la risposta esce dall'interfaccia prevista. Poi controlla che una richiesta non correlata avviata dal container segua ancora la VPN.

Non svuotare la tabella delle connessioni della macchina per testare una regola: le voci esistenti mantengono la loro mappatura precedente, e lo svuotamento rompe tutto il resto sull'host. Pubblicare una porta definisce la raggiungibilità. Non definisce il percorso della risposta. Scrivi il progetto scelto con i suoi nomi di tabella, così la persona successiva non debba riscoprirlo durante un incidente.

Articoli correlati