· ~4 λεπτά ανάγνωσης

Ένα site-to-site IPsec VPN με strongSwan και δική μου PKI

Δύο LAN ενωμένα μέσα από ένα μη έμπιστο δίκτυο με ένα tunnel IKEv2, gateways που αυθεντικοποιούνται με πιστοποιητικά από ιδιωτική CA αντί για κοινό κλειδί, και απόδειξη στο Wireshark ότι στο καλώδιο περνά μόνο ESP.

Στόχος

Να συνδέσω δύο απομονωμένα LAN μέσα από ένα δίκτυο που δεν εμπιστεύομαι, ώστε οι hosts κάθε πλευράς να μιλούν μεταξύ τους σαν να ήταν τοπικοί, και όποιος παρακολουθεί τη σύνδεση στη μέση να μη βλέπει τίποτα χρήσιμο. Το lab τρέχει σε τέσσερα Linux VMs: δύο VPN gateways και έναν εσωτερικό host πίσω από το καθένα.

Τα configs και όλα τα βήματα είναι στο repository στο GitHub.

Τοπολογία

ΜηχάνημαΕξωτερικήΕσωτερική
Gateway 110.0.3.3192.168.1.1/24
Gateway 210.0.3.4192.168.2.1/24
Host 1192.168.1.10 (gateway 192.168.1.1)
Host 2192.168.2.10 (gateway 192.168.2.1)

Πριν από οποιοδήποτε tunnel, τα gateways χρειάζονται απλό routing: ενεργό IP forwarding και ένα static route σε κάθε gateway προς το LAN της άλλης πλευράς, μέσω της εξωτερικής διεύθυνσης του άλλου gateway. Αν το layer 3 είναι σωστό από την αρχή, κάθε αποτυχία αργότερα είναι πρόβλημα του IPsec και όχι του routing.

Πιστοποιητικά αντί για pre-shared key

Ο γρήγορος τρόπος να αυθεντικοποιήσεις δύο IPsec peers είναι ένα pre-shared key. Είναι και ο αδύναμος: ένα string κοινό ανάμεσα στα sites, συχνά μικρό, που σπάνια αλλάζει, και αν διαρρεύσει εκτίθεται κάθε tunnel που το χρησιμοποιεί. Αντί γι' αυτό έστησα μια μικρή ιδιωτική CA:

Έτσι κάθε gateway αποδεικνύει την ταυτότητά του με το δικό του ιδιωτικό κλειδί και ελέγχει το πιστοποιητικό της άλλης πλευράς απέναντι στην CA, μέχρι το ακριβές distinguished name.

Η ρύθμιση του strongSwan

Το tunnel ορίζεται στο swanctl.conf. Η πλευρά του Gateway 1, συντομευμένη:

connections {
   gw1-to-gw2 {
      remote_addrs = 10.0.3.4
      local {
         auth = pubkey
         certs = g1Cert.pem
      }
      remote {
         auth = pubkey
         id = "C=GR, O=Lab, CN=gateway2"
      }
      children {
         net {
            local_ts  = 192.168.1.0/24
            remote_ts = 192.168.2.0/24
            start_action = trap
         }
      }
   }
}

Δύο ρυθμίσεις μετράνε περισσότερο. Το auth = pubkey μαζί με το ακριβές id σημαίνει ότι ο peer πρέπει να έχει πιστοποιητικό υπογεγραμμένο από την CA για το gateway2, όχι απλώς οποιοδήποτε πιστοποιητικό της CA. Και το start_action = trap εγκαθιστά μια πολιτική στον kernel που ανεβάζει το tunnel όταν χρειαστεί: το πρώτο πακέτο που ταιριάζει στα δύο subnets ξεκινά τη διαπραγμάτευση IKEv2.

Η απόδειξη ότι δουλεύει

Μετά το swanctl --load-all, ένα ping από το ένα LAN στο άλλο ανέβασε το tunnel, και το swanctl --list-sas έδειξε τα security associations. Μετά ήρθε το κομμάτι που με ενδιαφέρει περισσότερο, μια καταγραφή στην εξωτερική διεπαφή του gateway:

Τι έμαθα

Κοιτώντας το ξανά, αυτά θα έκανα πιο αυστηρά.

Προσωπικό lab σε virtual machines.

Θέλεις τα configs ή τον κώδικα από αυτό το lab, ή έχεις κάποια ερώτηση; Στείλε μου email στο papas@viotnet.com

← όλα τα άρθρα