Προσθέτεις έναν κανόνα για κίνηση VPN στην αλυσίδα FORWARD, εκτελείς το αίτημα από το ίδιο μηχάνημα Linux και ο μετρητής μένει στο μηδέν. Ο κανόνας μάλλον είναι σωστός. Το πακέτο δεν πήρε ποτέ αυτή τη διαδρομή, γιατί ένα αίτημα που δημιουργείται στο ίδιο το μηχάνημα δεν προωθείται από αυτό. Η πορεία του πακέτου από το socket ως το καλώδιο εξηγεί γιατί, και πού ανήκει ο κανόνας αντ’ αυτού.

Βρες πού γεννήθηκε το πακέτο

Η σειρά των hook του Netfilter χωρίζει τρεις περιπτώσεις, και μόνο μία από αυτές αφορά το FORWARD:

OriginPathHook that sees it
Local processOUTPUT then POSTROUTINGOUTPUT, POSTROUTING
Addressed to a local servicePREROUTING then INPUTPREROUTING, INPUT
Received for another hostPREROUTING, FORWARD, POSTROUTINGFORWARD

Μια τοπική εφαρμογή ξεκινά στη διαδρομή OUTPUT, γιατί ο πυρήνας έχει ήδη διαπιστώσει ότι το πακέτο προέρχεται εδώ και δεν είναι ποτέ υποψήφιο για προώθηση. Η δημιουργία ενός tunnel δεν αλλάζει αυτή την κατάταξη· το tunnel είναι μια συσκευή από την οποία το πακέτο μπορεί να βγει, όχι ένα στάδιο που μετατρέπει την τοπική έξοδο σε διέλευση.

Δύο πακέτα, μία ιστορία

Μόλις το tunnel σηκωθεί, το εσωτερικό πακέτο της εφαρμογής και το κρυπτογραφημένο εξωτερικό πακέτο είναι διαφορετικά αντικείμενα. Το εσωτερικό πακέτο μεταφέρει τον προορισμό και το ωφέλιμο φορτίο που διάλεξε η εφαρμογή. Το εξωτερικό πακέτο μεταφέρει κρυπτοκείμενο στη διεύθυνση και τη θύρα του peer, και αυτό είναι που περνά στην πραγματικότητα τη φυσική διεπαφή.

Η πολιτική σου αφορά ένα από τα δύο, και η επιλογή του λάθους είναι συχνός λόγος να φαίνεται ότι ένας κανόνας δεν κάνει τίποτα. Ένας κανόνας που ταιριάζει με την εξωτερική διεύθυνση του peer βλέπει κάθε πακέτο του tunnel το ίδιο, ό,τι κι αν κάνει η εφαρμογή μέσα. Ένας κανόνας που ταιριάζει με έναν εσωτερικό προορισμό βλέπει την κίνηση που σε ενδιαφέρει, και θα ενεργοποιηθεί μόνο αν αυτό το πακέτο φτάσει στο hook όπου εγκατέστησες τον κανόνα.

Οι namespace μετακινούν το όριο

Ένα container το κάνει δυσκολότερο χωρίς να αλλάζει την αρχή. Το αίτημα της εφαρμογής είναι τοπική έξοδος μέσα στον network namespace του container. Ο host λαμβάνει αυτή την κίνηση σε μια εικονική διεπαφή Ethernet και μπορεί να την προωθήσει, οπότε ένας κανόνας FORWARD στον host μπορεί να έχει νόημα παρόλο που η διεργασία που δημιούργησε το αίτημα δεν άγγιξε ποτέ την αλυσίδα OUTPUT του host.

Πριν διαλέξεις hook, καθόρισε πού ζουν πραγματικά το σύνολο κανόνων και το tunnel. Ένα tunnel μέσα στο container, ένα tunnel στον host με το container να δρομολογείται μέσα από αυτό, και ένα tunnel σε ξεχωριστό namespace είναι τρεις διαφορετικές τοπολογίες με τρεις διαφορετικές τοποθετήσεις κανόνων. Διάβασε τους κανόνες μέσα στον namespace που κατέχει τη συσκευή, όχι μόνο στον προεπιλεγμένο.

Ρώτησε αν χρειάζεσαι καθόλου σημάδι

Αν ο στόχος είναι να σταλεί ένα πρόθεμα προορισμού μέσα από το tunnel, μια διαδρομή για αυτό το πρόθεμα μπορεί να αρκεί. Έλεγξε πρώτα τις ενεργές διαδρομές, μαζί με ό,τι έσπρωξε ο διακομιστής: μια ανακατευθυνόμενη προεπιλεγμένη διαδρομή στέλνει πολύ περισσότερη κίνηση μέσα από το VPN από τη στενή πολιτική που είχες στο μυαλό σου, και καμία ποσότητα σημαδέματος δεν θα κάνει το αποτέλεσμα να ταιριάξει με την πρόθεση.

Η ταξινόμηση χρειάζεται όταν η απόφαση εξαρτάται από κάτι που μια διαδρομή δεν μπορεί να εκφράσει, όπως η πηγή, ο χρήστης ή η διεργασία. Για την εισερχόμενη κίνηση, το σημάδεμα στο PREROUTING δουλεύει. Για την τοπική κίνηση, το σημάδεμα πρέπει να γίνει σε ένα στάδιο εξόδου που μπορεί να προκαλέσει νέα αναζήτηση διαδρομής αφού τεθεί το σημάδι. Με nftables αυτό είναι μια αλυσίδα τύπου route στο hook εξόδου· μια συνηθισμένη αλυσίδα φίλτρου εξόδου θα θέσει την τιμή και θα αφήσει τη διαδρομή αμετάβλητη.

Με iptables, το ισοδύναμο ζει στη διάταξη mangle OUTPUT, και ισχύει η ίδια απαίτηση: η απόφαση δρομολόγησης πρέπει να επανεξεταστεί αφού υπάρξει το σημάδι. Έπειτα ένας κανόνας πολιτικής πρέπει να καταναλώσει το σημάδι και να δείξει σε έναν πίνακα που περιέχει μια χρησιμοποιήσιμη διαδρομή. Το να θέσεις ένα σημάδι conntrack είναι μια τρίτη, ξεχωριστή πράξη· αποθηκεύει μια τιμή στη ροή και δεν βάζει από μόνο του αυτή την τιμή στο τρέχον πακέτο για να τη διαβάσει η δρομολόγηση.

Επαλήθευσε την αναζήτηση και τον μετρητή μαζί

nft list ruleset
ip route get 198.51.100.25
ip route get 198.51.100.25 mark 0x1

Η διεύθυνση και το σημάδι είναι ενδεικτικά, και τα δύο ερωτήματα διαδρομής απαντούν σε διαφορετικά ερωτήματα. Το δεύτερο ρωτά τι θα έκανε ο πυρήνας αν ένα πακέτο έφερε αυτό το σημάδι· δεν δείχνει ότι το σύνολο κανόνων σου ορίζει κάποιο. Αντιμετώπισέ το ως έλεγχο υπόθεσης, όχι ως απόδειξη ότι η πολιτική δουλεύει.

Έπειτα εκτέλεσε ένα ακίνδυνο αίτημα και παρατήρησε δύο πράγματα ταυτόχρονα: τον μετρητή στο hook που διάλεξες και την έξοδο που πήρε πραγματικά το πακέτο. Αν ο μετρητής κινείται και το πακέτο φεύγει αλλού, το σημάδι ή ο πίνακας είναι λάθος. Αν δεν κινείται κανένα από τα δύο, το πακέτο δεν φτάνει καθόλου σε αυτό το hook, και το επόμενο ερώτημα είναι ο namespace ή η διαδρομή.

Τέλος, περιόρισε το τεστ σε ό,τι μπορεί να εκφράσει ο μηχανισμός. Μια διαδρομή για μια διεύθυνση δεν γίνεται μόνιμη πολιτική για μια υπηρεσία της οποίας οι διευθύνσεις εναλλάσσονται. Απόφασισε πρώτα το εύρος των πακέτων, μετά έλεγξε αν ο σχεδιασμός δρομολόγησης και σημαδέματος μπορεί να κρατήσει αυτό το εύρος μετά από επανασύνδεση.

Σχετικά άρθρα