Η μετάβαση από το boringtun στο sanstun
Κατά την ανάπτυξη του Firezone, η ομάδα βασίστηκε αρχικά στο boringtun της Cloudflare ως υλοποίηση του πρωτοκόλλου WireGuard. Ωστόσο, η εξέλιξη των απαιτήσεων του προϊόντος οδήγησε σε πάνω από 70 PRs και τροποποιήσεις στοfork τους. Η διατήρηση της 100% συμβατότητας με το upstream API αποδείχθηκε ανασταλτικός παράγοντας. Προβλήματα όπως η αυτόματη εσωτερική αποθήκευση σε buffer (internal buffering), η μη διαισθητική διαχείριση κενών datagrams και οι περιορισμοί στη διαχείριση χρόνου οδήγησαν στη δημιουργία του sanstun.
Το sanstun ακολουθεί αυστηρά την αρχιτεκτονική sans-IO. Αυτό σημαίνει ότι το I/O, ο χρόνος και η παραγωγή τυχαιότητας αποκόπτονται πλήρως από την εσωτερική επιχειρησιακή λογική. Το αποτέλεσμα είναι η αποφυγή προβλημάτων όπως το function coloring και η απλοποίηση των δοκιμών (testing) μέσω ακριβών προσομοιώσεων ολόκληρου του συστήματος.
Αρχιτεκτονική API και αποφυγή σφαλμάτων σε επίπεδο τύπων
Στο WireGuard, η έκθεση ενός endpoint σε μη επαληθευμένα πακέτα UDP μπορεί εύκολα να οδηγήσει σε DoS επιθέσεις μέσω ψευδών handshake initiations. Το sanstun επιλύει αυτό το ζήτημα ενσωματώνοντας το rate limiting απευθείας στη ροή δεδομένων της διασύνδεσης (Interface::receive).
Οι κατασκευστές (constructors) κρίσιμων δομών όπως το HandshakeInitiation είναι ορατοί αποκλειστικά εντός του crate (crate-private). Ο μόνος τρόπος για να παραχθούν είναι η διέλευση του raw datagram μέσα από το Interface::receive, διασφαλίζοντας ότι καμία εισερχόμενη σύνδεση δεν παρακάμπτει τους μηχανισμούς προστασίας.
Παράλληλη κρυπτογράφηση χωρίς locks
Ένα από τα σημαντικότερα τεχνικά επιτεύγματα του sanstun είναι η υποστήριξη παραλληλισμού σε επίπεδο τούνελ. Δεδομένου ότι τα δεδομένα στο WireGuard απαιτούν μονοτονικά αυξανόμενους μετρητές πακέτων ανά σύgetSession για την αποφυγή replay attacks, η παράλληλη πρόσβαση από πολλαπλά threads κανονικά θα απαιτούσε πολύπλοκο συγχρονισμό με mutexes ή atomic counters.
Το sanstun διαχωρίζει τη διαδικασία σε δύο φάσεις:
- Bookkeeping: Η κλήση της
Tunnel::begin_encapsulateεκτελείται σε ένα μονονήματο thread διαχείρισης. Ελέγχει την κατάσταση, δεσμεύει τον μετρητή πακέτων και επιστρέφει έναPendingEncapsulate. - Κρυπτογράφηση: Το αντικείμενο
PendingEncapsulateυλοποιεί το traitSend, επιτρέποντας τη μεταφορά του σε ξεχωριστό thread εργασίας για την εκτέλεση του βαριού αλγορίθμου ChaCha20-Poly1305.
Τα benchmarks δείχνουν ότι το overhead του bookkeeping για πακέτα μεγέθους 1280 bytes ανέρχεται μόλις στο 2% του συνολικού χρόνου, απελευθερώνοντας σημαντικούς πόρους CPU και βελτιώνοντας δραστικά το συνολικό throughput.