Το αίτημα είναι πάντα μια παραλλαγή της ίδιας φράσης: κράτησε το VPN για περιήγηση, αλλά άφησε το SSH ή μια εργασία αντιγράφων ασφαλείας να χρησιμοποιεί την κανονική σύνδεση. Η συμβουλή που κυκλοφορεί γι' αυτό, δηλαδή να προωθήσεις τη θύρα με κανόνες NAT του iptables, δεν το κάνει. Ένας κανόνας NAT ξαναγράφει διευθύνσεις και θύρες μέσα σε μια ροή· ποτέ δεν επιλέγει από ποια διεπαφή φεύγει το πακέτο. Αυτή η απόφαση ανήκει στην αναζήτηση δρομολόγησης, και η αναζήτηση δρομολόγησης χρειάζεται βοήθεια για να δει μια θύρα.

Γιατί ένα απλό δρομολόγιο δεν μπορεί να ταιριάξει με θύρα

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

Τα σύγχρονα iproute2 και οι πυρήνες διευρύνουν τον επιλογέα του κανόνα: ipproto, sport και dport γίνονται δεκτά, άρα το ip rule add ipproto tcp dport 22 table 100 εκφράζει την πρόθεση σε μία γραμμή. Εκτελέστε ip rule add help στον πραγματικό κεντρικό υπολογιστή για να δείτε αν η έκδοσή σας εμφανίζει dport. Αν το κάνει, τελειώσατε με μία εντολή· αν όχι, η διαδρομή μέσω σημαδιού παρακάτω είναι το ισοδύναμο.

Όπως και να έχει, ο κανόνας είναι μόνο δείκτης. Ο πίνακας 100 χρειάζεται ακόμη δρομολόγιο, και αυτό είναι το κομμάτι που ξεχνούν οι άνθρωποι.

Τρία κομμάτια, ή ένα

Η σύγχρονη μορφή είναι ο μεμονωμένος κανόνας παραπάνω συν ένα δρομολόγιο στον εναλλακτικό πίνακα. Η κλασική μορφή προσθέτει το netfilter στη μέση: σημαδέψτε το πακέτο και μετά ταιριάξτε το σημάδι σε έναν κανόνα. Και οι δύο καταλήγουν στην ίδια αναζήτηση· διαφέρουν στο πού διαβάζεται η θύρα.

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

Τα τρία κομμάτια με σειρά

Πρώτα, σημαδέψτε τις ροές που θέλετε να εκτρέψετε, σε μια αλυσίδα που εκτελείται αρκετά νωρίς ώστε το σημάδι να υπάρχει πριν από την απόφαση δρομολόγησης:

nft add table inet vpnexempt
nft 'add chain inet vpnexempt out { type route hook output priority mangle; }'
nft add rule inet vpnexempt out tcp dport 22 meta mark set 0x1

Δεύτερο, στείλτε τα σημαδεμένα πακέτα σε ξεχωριστό πίνακα:

ip rule add fwmark 0x1/0x1 table 100

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

ip route add default via 192.168.1.1 dev wlan0 table 100

Παραλείψτε το τρίτο βήμα και το σημαδεμένο πακέτο δεν βρίσκει δρομολόγιο στον πίνακα 100, οπότε αποτυγχάνει. Το σύμπτωμα μοιάζει σαν ο κανόνας να χάλασε το δίκτυο, ενώ στην πραγματικότητα αφαίρεσε τη μόνη διαδρομή που είχε απομείνει στο πακέτο.

Τι το κρατά να δουλεύει μετά το πρώτο πακέτο

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

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

Μη σημαδεύετε τη μεταφορά της ίδιας της σήραγγας. Μια σήραγγα WireGuard ή UDP OpenVPN δεν είναι TCP 22, άρα η συνταγή παραπάνω είναι ασφαλής, αλλά μια εξαίρεση γραμμένη ως όλα εκτός από τον προορισμό της σήραγγας μπορεί να πιάσει τα κρυπτογραφημένα πακέτα και να σπάσει τη σήραγγα με τρόπο που μοιάζει με βρόχο δρομολόγησης.

Ελέγξτε το αντί να υποθέσετε

Ρωτήστε τον πυρήνα ποια διαδρομή θα ακολουθούσε, για τον προορισμό και για τη θύρα, και μετά εκτελέστε την πραγματική μεταφορά:

ip route get 203.0.113.10
ip rule show
nft list ruleset

Αν το σημάδι υπάρχει αλλά οι μετρητές δεν κινούνται ποτέ, ο κανόνας δεν ταιριάζει. Οι μετρητές είναι η διαφορά ανάμεσα σε μια διαμόρφωση που γράψατε και σε μια πολιτική που εφαρμόζει ο πυρήνας.

Πότε αυτό είναι το λάθος εργαλείο

Οι εξαιρέσεις βάσει θύρας είναι εύθραυστες από τη φύση τους. Οι υπηρεσίες αλλάζουν θύρες, το HTTP/3 έρχεται ως UDP 443, και μία εφαρμογή μπορεί να ανοίξει πολλές ροές διαφορετικών ειδών. Αν η πραγματική απαίτηση είναι αυτό το πρόγραμμα να χρησιμοποιεί την κανονική ζεύξη, το επίπεδο δρομολόγησης είναι λάθος μέρος· ένας χώρος ονομάτων δικτύου ή ένας διαμεσολαβητής ανά εφαρμογή ταιριάζει καλύτερα.

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

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

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