Η κίνηση των κοντέινερ Docker παρακάμπτει το VPN του host: πώς να το ελέγξετε
Ένα VPN host καλύπτει μόνο τον χώρο ονομάτων δικτύου του host. Χρησιμοποιήστε αυτούς τους ελέγχους για να δείτε αν η κίνηση των κοντέινερ στη γέφυρα μπαίνει στη σήραγγα ή βγαίνει απευθείας.
Το πρόγραμμα περιήγησης στον host δείχνει τη διεύθυνση εξόδου του VPN, το κοντέινερ αναφέρει τη σύνδεση του σπιτιού σας και κάποιος το αποκαλεί διαρροή. Δεν διέρρευσε τίποτα. Η σήραγγα του host είναι ένα σύνολο διεπαφών, διαδρομών και κανόνων που ανήκουν στον χώρο ονομάτων δικτύου του host, και ένα κοντέινερ σε γέφυρα είναι ένας διαφορετικός χώρος ονομάτων με τη δική του προεπιλεγμένη διαδρομή. Έχω καθίσει σε ένα stack Compose όπου ο πελάτης VPN ήταν συνδεδεμένος για εβδομάδες και ούτε ένα πακέτο κοντέινερ δεν είχε μπει ποτέ σε αυτόν.
Ελέγξτε τον χώρο ονομάτων πριν από το εικονίδιο στη γραμμή
Οι χώροι ονομάτων είναι όλο το επιχείρημα. Όταν το Docker ξεκινά ένα κοντέινερ σε δίκτυο γέφυρας, δημιουργεί έναν χώρο ονομάτων δικτύου, συνδέει το ένα άκρο ενός ζεύγους veth μέσα του και δίνει σε αυτόν τον χώρο ονομάτων μια διεύθυνση και μια προεπιλεγμένη διαδρομή. Η διεπαφή της σήραγγας, όπως κι αν ονομάζεται, ζει στον χώρο ονομάτων του host. Η κίνηση μέσα στο κοντέινερ δεν μπορεί να τη δει, και καμία ρύθμιση πελάτη δεν το αλλάζει αυτό από έξω.
Δύο υποστηριζόμενες κινήσεις σας βγάζουν από την απομόνωση. Το --network host τοποθετεί το κοντέινερ μέσα στον χώρο ονομάτων του host, ώστε να κληρονομεί τις διαδρομές του host και επομένως τη σήραγγα. Το --network container:vpn μοιράζεται τον χώρο ονομάτων ενός άλλου κοντέινερ, και έτσι τα περισσότερα σχέδια sidecar στέλνουν ένα φόρτο εργασίας μέσα από κοντέινερ VPN. Και τα δύο είναι ρητές επιλογές· συνήθως μόνο μία από αυτές είναι αυτό που εννοούσε το άτομο που κάνει την ανάπτυξη.
Η λειτουργία host δεν είναι δωρεάν αναβάθμιση. Το κοντέινερ παύει να έχει δική του διεύθυνση, η δημοσίευση θυρών παύει να ισχύει, και μια διεργασία που κρατά το NET_ADMIN εκεί μπορεί να ξαναγράψει τη δρομολόγηση του host. Το να το αποδεχτείτε μπορεί να είναι η σωστή απόφαση. Το να υποθέσετε ότι είναι ήδη ενεργό είναι ο τρόπος με τον οποίο οι άνθρωποι περνούν ένα βράδυ αποσφαλματώνοντας μια σήραγγα που δεν ήταν ποτέ στη διαδρομή.
Ακολουθήστε το πακέτο έξω από τη γέφυρα
Ένα κοντέινερ σε γέφυρα στέλνει το πακέτο του στην προεπιλεγμένη πύλη του, που είναι η διεπαφή της γέφυρας στον host. Στη συνέχεια ο host προωθεί το πακέτο και, στην προεπιλεγμένη διαμόρφωση, μεταφράζει τη διεύθυνση προέλευσης στη δική του πριν το πακέτο φύγει. Αυτό το βήμα μετάφρασης είναι που ακυρώνει αθόρυβα την πολιτική.
Όταν το πακέτο φτάσει στο τελικό σημείο της σήραγγας, φέρει τη διεύθυνση του host. Οποιοσδήποτε κανόνας, διαδρομή πολιτικής ή απόφαση διαχωρισμένης σήραγγας που βασίζεται στην αρχική διεύθυνση του κοντέινερ παύει να ταιριάζει, και δύο κοντέινερ που προορίζονται να βγουν από διαφορετικές εξόδους δεν μπορούν να διακριθούν μόνο από την προέλευση. Αν χρειάζεστε δρομολόγηση ανά κοντέινερ, η απόφαση πρέπει να λαμβάνεται πριν από τη μετάφραση ή μέσα σε έναν χώρο ονομάτων που ελέγχετε.
Το Docker συντηρεί αυτούς τους κανόνες μόνο του, μέσω όποιου backend τείχους προστασίας έχει ρυθμιστεί ο δαίμονας. Χειρόγραφοι κανόνες έξω από το υποστηριζόμενο άγκιστρο για προωθούμενη κίνηση, DOCKER-USER, μπορεί να αναδιαταχθούν ή να απορριφθούν όταν ο δαίμονας επανεκκινήσει ή ο host αναβαθμιστεί. Η τεκμηρίωση του Docker για το φιλτράρισμα πακέτων δείχνει τη σειρά των αλυσίδων· το πρακτικό σημείο είναι ότι κάθε κανόνας χρειάζεται ιδιοκτήτη και μια διαδρομή επαναφόρτωσης που έχετε πραγματικά δοκιμάσει.
Δοκιμάστε τα δύο συστήματα χωριστά
Τα στοιχεία από έναν χώρο ονομάτων δεν λένε τίποτα για τον άλλο. Ένα αίτημα που εκτελείται μέσα στο κοντέινερ VPN αποδεικνύει ότι η σήραγγα λειτουργεί για αυτό το κοντέινερ. Δεν είναι στοιχείο για τον host, και η ίδια εντολή από κοντέινερ --network host δεν είναι στοιχείο για τη γέφυρα.
# host namespace
ip route get 1.1.1.1
ip -brief addr show
# a fresh container on the same bridge network
docker run --rm --network appnet alpine sh -c 'ip route; cat /etc/resolv.conf; ip -6 route'
Στη συνέχεια επαναλάβετε τη δοκιμή μέσα στο πραγματικό κοντέινερ της εφαρμογής και όχι σε ένα παρόμοιο image. Η εφαρμογή μπορεί να φέρει μια επιπλέον διαδρομή, μια μεταβλητή περιβάλλοντος για διαμεσολαβητή ή διαφορετικό resolver, και καθένα από αυτά αλλάζει την απάντηση. Ελέγχετε την επίλυση ονομάτων και τη δεύτερη οικογένεια διευθύνσεων κάθε φορά: τα κοντέινερ σε γέφυρες ορισμένες από τον χρήστη επιλύονται μέσω του ενσωματωμένου resolver του Docker στη διεύθυνση 127.0.0.11, και μια προεπιλεγμένη διαδρομή IPv6 στη γέφυρα μπορεί να βγάλει κίνηση έξω ενώ εσείς ασχολείστε με τη δοκιμή σήραγγας μόνο IPv4.
Διαβάστε το μοτίβο πριν αγγίξετε διαπιστευτήρια
Όταν ο host λειτουργεί και το κοντέινερ όχι, η αιτία είναι σχεδόν πάντα δομική, και η εναλλαγή κλειδιών ή η επανεγκατάσταση του πελάτη σπαταλά ένα απόγευμα. Ταξινομήστε πρώτα το σύμπτωμα και η διόρθωση συνήθως ονομάζει τον εαυτό της.
| What you see | Usual cause | First check |
|---|---|---|
| Host exits through the VPN, container shows the ISP address | The container never entered the tunnel | Default route inside the container |
| Container works until the daemon restarts, then stops | Rules outside the supported hook, or a changed backend | Daemon's reported firewall backend and DOCKER-USER |
| Container loses internal hosts after the tunnel comes up | VPN prefix overlaps the Docker bridge subnet | ip route on the host, then docker network inspect |
| Small replies arrive, large ones hang | Tunnel MTU or missing MSS clamping | Link MTU on both ends of the tunnel |
| Container falls back to the ISP address when the tunnel drops | Nothing enforces the kill switch for forwarded traffic | Stop the tunnel with a request in flight |
Η γραμμή της επικάλυψης αξίζει δική της πρόταση. Ένα προφίλ VPN που σπρώχνει διαδρομή για το 172.17.0.0/16, ή για ένα 10.0.0.0/8 που τυχαίνει να περιέχει το πρόθεμα της γέφυρας σας, κάνει τη σήραγγα να διεκδικεί το υποδίκτυο των κοντέινερ, και οι απαντήσεις σε μεταφρασμένες διευθύνσεις θα πάνε προς λάθος κατεύθυνση ή θα εξαφανιστούν. Η επαναρίθμηση του δικτύου Docker είναι συνήθως καθαρότερη από τη συσσώρευση εξαιρέσεων.
Κάντε την κάλυψη ρητή και μετά σπάστε την επίτηδες
Δύο σχέδια αντέχουν σε έλεγχο. Μοιραστείτε τον χώρο ονομάτων του κοντέινερ VPN και κάθε καλυμμένος φόρτος εργασίας χρησιμοποιεί μία σήραγγα με ένα όριο επανεκκίνησης, κάτι που είναι απλό μέχρι μια υπηρεσία να χρειαστεί διαφορετική έξοδο ή τη δική της διαδρομή DNS. Ή δρομολογήστε το δίκτυο των κοντέινερ σε πύλη VPN στον host: προώθηση ενεργοποιημένη, το πρόθεμα της γέφυρας στραμμένο στη σήραγγα, η κίνηση επιστροφής χειρισμένη ρητά. Αυτό αγοράζει έλεγχο ανά δίκτυο και σας κοστίζει ένα σύνολο κανόνων που πρέπει να συντηρείτε σε αναβαθμίσεις δαίμονα και πελάτη.
Όπως και να έχει, η δοκιμή που μετράει είναι η περίπτωση αποτυχίας. Σταματήστε τη σήραγγα με ένα αίτημα κοντέινερ σε εξέλιξη και δείτε πού πάει το πακέτο. Αν πέσει πίσω στην άμεση διαδρομή, η κάλυψη δεν επιβλήθηκε ποτέ, γιατί ένα kill switch πελάτη διέπει την κίνηση του ίδιου του πελάτη και όχι τα προωθούμενα πακέτα από μια γέφυρα. Επανεκκινήστε μετά τον δαίμονα και τον host και επιβεβαιώστε το αποτέλεσμα δεύτερη φορά· εκείνη είναι η στιγμή που οι χειρόγραφοι κανόνες εξαφανίζονται.
Πριν το θεωρήσετε ολοκληρωμένο, επιβεβαιώστε τέσσερα πράγματα: η διεπαφή της σήραγγας βρίσκεται στον ίδιο χώρο ονομάτων με την κίνηση, η δοκιμή του κοντέινερ έγινε μέσα στο πραγματικό κοντέινερ, ελέγχθηκαν η επίλυση ονομάτων και οι δύο οικογένειες διευθύνσεων, και η δοκιμή αποτυχίας της σήραγγας εξακολουθεί να αποτυγχάνει κλειστά. Στη συνέχεια καταγράψτε το backend του τείχους προστασίας, την έκδοση του πελάτη και τον ιδιοκτήτη κάθε κανόνα. Αυτό το αρχείο είναι που εμποδίζει την επόμενη αναβάθμιση να αφήσει ένα ατεκμηρίωτο μείγμα παλιών παραδοχών.