Το Secure Shell ή απλά SSH είναι ένα πρωτόκολλο επικοινωνίας που κατοικεί στο Application Layer του TCP/IP stack. Μας επιτρέπει να συνδεόμαστε κρυπτογραφημένα σε απομακρυσμένα μηχανήματα, συνήθως για την απόκτηση πρόσβασης στη γραμμή εντολών. Το OpenSSH είναι μια εξαιρετικά δημοφιλής υλοποίηση Ανοικτού Λογισμικού του SSH, και θεωρούμε μάλλον απίθανο να μην το έχετε χρησιμοποιήσει έστω και μία φορά.

Δείχνουμε στη συνέχεια πώς οι ήδη ασφαλείς συνδέσεις SSH είναι δυνατόν να γίνονται ακόμα πιο ασφαλείς, και ταυτόχρονα ο χρήστης να διευκολύνεται ακόμα πιο πολύ. Καταλαβαίνουμε ότι αυτό που μόλις διαβάσατε δείχνει ν' αποτελεί ευθεία παραβίαση της αντιστρόφως ανάλογης σχέσης μεταξύ ευκολίας κι ασφάλειας. Σε λίγο, ωστόσο, θα διαπιστώσετε πως ό,τι κερδίζουμε σε ασφάλεια κι ευκολία, το πληρώνουμε με συνετές πρακτικές διαχείρισης. Για λόγους πληρότητας, αλλά και για να τραβήξουμε την προσοχή του 4,71% των αναγνωστών οι οποίοι για κάποιο μυστηριώδη λόγο δεν έχουν ακόμα αρχίσει να χαίρονται το OpenSSH, σημειώνουμε ότι το πρωτόκολλο δεν λύνει τα χέρια μόνον όσον αφορά στην ασφαλή πρόσβαση στις κονσόλες απομακρυσμένων hosts. Επιπρόσθετα, χάρη στο SSH μπορούμε να μεταφέρουμε αρχεία μεταξύ hosts μέσω κρυπτογραφημένων καναλιών, να στέλνουμε εντολές προς εκτέλεση σε απομακρυσμένα συστήματα, να ανακατευθύνουμε την έξοδο προγραμμάτων γραφικών που τρέχουν σε remote hosts στην οθόνη του δικού μας υπολογιστή, καθώς και να σερφάρουμε στο web χωρίς το φόβο της παρακολούθησης από άλλα μέλη του τοπικού δικτύου ή/και από τον ISP μας.

Η προβληματική ταυτοποίηση με password

Το SSH υποστηρίζει διάφορες μεθόδους για την ταυτοποίηση των χρηστών (authentication), με την πιο συνηθισμένη να απαιτεί πληκτρολόγηση username και password. Έχουμε, π.χ., έναν ωραιότατο server που τρέχει Linux κι έχει την υπηρεσία του OpenSSH ενεργοποιημένη, επομένως για ν' αποκτήσουμε πρόσβαση σε λογαριασμό του συστήματος καταφεύγουμε σ' έναν SSH client κι επιχειρούμε σύνδεση πληκτρολογώντας το κατάλληλο username μαζί, βεβαίως, με το αντίστοιχο password. Αν αυτά τα username και password αντιστοιχούν πράγματι σε υπαρκτό λογαριασμό χρήστη, τότε η σύνδεσή μας πετυχαίνει. Αν όχι, προσπαθούμε και πάλι. Η ταυτοποίηση με username και password αποτελεί συνηθισμένη, εύκολη και τελικά φυσιολογική διαδικασία, έχει όμως και μερικά σοβαρά μειονεκτήματα.

  • Για κάθε λογαριασμό χρειαζόμαστε ένα ισχυρό password, διαφορετικά είναι πιθανό να βρεθεί από κάποιο bruteforce script.
  • Σε κάθε λογαριασμό, σε οποιοδήποτε σύστημα, πρέπει να έχουμε διαφορετικό password. Διαφορετικά, αν για κάποιο λόγο βρεθεί το password συγκεκριμένου λογαριασμού τότε ο επιτιθέμενος πιθανώς ν' αποκτήσει πρόσβαση και σε άλλους λογαριασμούς μας.
  • Ακόμη κι αν το password ενός λογαριασμού είναι ισχυρότατο, αν στον client εγκατασταθεί keylogger τότε το συνθηματικό θα διαρρεύσει.
  • Ένα πραγματικά καλό password έχει μεγάλο μήκος, αποτελεί συνδυασμό πεζών, κεφαλαίων, αριθμών και ειδικών συμβόλων, είναι τυχαίο και συνεπώς αδύνατο να το θυμόμαστε. Τα προηγούμενα σημαίνουν α) κόπο για την προστασία του password (θα πρέπει, π.χ., να το διατηρούμε σε κάποιον password manager), β) κόπο για την πληκτρολόγησή του (στην καλύτερη περίπτωση μιλάμε για αντιγραφή από τον password manager, καθώς κι επικόλληση στο εκάστοτε password prompt).
  • Η πληκτρολόγηση password δυσκολεύει τη λειτουργία, π.χ., Ansible playbooks ή γενικότερα scripts που επιθυμούμε να εκτελούνται αυτόματα και, χωρίς καμία αλληλεπίδραση, να συνδέονται σε απομακρυσμένα hosts προκειμένου να εκτελούν συγκεκριμένες εργασίες. Μην πάει το μυαλό σας σε περίπλοκα σενάρια, αφού έτσι θα μπορούσε να λειτουργεί κι ένα απλό script για backup.

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

  • Τα bruteforce attacks παύουν να έχουν νόημα.
  • Δεν χρειάζεται να πληκτρολογούμε κάτι, προκειμένου να συνδεόμαστε.
  • Τα scripts είναι πλέον δυνατόν να επικοινωνούν αυτοματοποιημένα με απομακρυσμένα hosts μέσω SSH, χωρίς βεβαίως να απαιτείται κάτι από μέρους μας.
  • Σε κάθε μηχάνημα-πελάτη δεν είναι υποχρεωτικό να έχουμε το ίδιο ζεύγος ιδιωτικού/δημοσίου κλειδιού (βλ. συνέχεια).
  • Ακόμη κι αν χάσουμε το laptop μας ή κάποιος αποκτήσει φυσική πρόσβαση στον υπολογιστή μας, αν έχουμε φροντίσει να προστατεύσουμε το ιδιωτικό κλειδί με μυστικό passphrase τότε ο επιτιθέμενος δεν θα μπορέσει να συνδεθεί άμεσα στο απομακρυσμένο host – όχι πριν βρει το passphrase. Αυτό θα μας δώσει αρκετό χρόνο ώστε να συνδεθούμε από άλλο μηχάνημα (ή ακόμη κι από τη web console του cloud provider) και να διαγράψουμε το δημόσιο κλειδί του μηχανήματος που ελέγχει ο επιτιθέμενος. Έτσι, θα του στερήσουμε την όποια πιθανότητα είχε για επιτυχή σύνδεση.

Πώς δουλεύουν τα logins χωρίς password;

Για κάθε πελάτη, δηλαδή για κάθε συσκευή μας από την οποία σκοπεύουμε να συνδεόμαστε σε έναν απομακρυσμένο host μέσω SSH, χρειαζόμαστε ένα ζεύγος κλειδιών (keypair). Κάθε τέτοιο ζεύγος αποτελείται από δύο μαθηματικά συσχετιζόμενα κλειδιά: το ένα λέγεται δημόσιο κλειδί (public key) και το άλλο ιδιωτικό κλειδί (private key).

Το ιδιωτικό κλειδί πρέπει να μένει στον client που το παρήγαγε. Κατά περίπτωση, μάλιστα, είναι καλή ιδέα να προστατεύεται κι από κάποια συνθηματική φράση (passphrase) την οποία, περιττό να τονίσουμε, οφείλουμε να γνωρίζουμε εμείς και κανένας άλλος. Το δε δημόσιο κλειδί το μεταφέρουμε σε έναν ή σε περισσότερους λογαριασμούς απομακρυσμένων hosts, στους οποίους θέλουμε να συνδεόμαστε μέσω SSH και μάλιστα χωρίς να πληκτρολογούμε username και password. Η περίπτωση υποκλοπής ενός δημοσίου κλειδιού καθόλου δεν πρέπει να μας απασχολεί. Το πολύ πολύ ν' αποκτήσουμε δυνατότητα σύνδεσης σε κάποιο μηχάνημα του υποκλοπέα, δηλαδή. Να σημειώσουμε επίσης ότι όποιος έχει ένα δημόσιο κλειδί, είναι απλά αδύνατον να δημιουργήσει το αντίστοιχο ιδιωτικό.

Μια σημαντική ιδιότητα που έχουν τα κλειδιά ενός ζεύγους, είναι πως ό,τι κρυπτογραφείται με χρήση του δημοσίου κλειδιού μπορεί να αποκρυπτογραφείται μόνο με χρήση του αντίστοιχου ιδιωτικού κλειδιού (και ισχύει και το αντίστροφο). Έτσι, ένας host στον οποίο βρίσκεται ένα δημόσιο κλειδί μας είναι σε θέση να στέλνει δοκιμασίες σε όσους επιχειρούν να συνδεθούν μέσω SSH. Ας δούμε λίγο καλύτερα τι συμβαίνει.

  • Κατ' αρχάς, προκειμένου να συνδεθούμε με χρήση κλειδιών σε ένα απομακρυσμένο host, εννοείται πως θα έχουμε ήδη στον υπολογιστή μας ένα ζεύγος ιδιωτικού-δημοσίου κλειδιού. Το πώς δημιουργούνται αυτά τα ζεύγη θα το δούμε σε λίγο. Το δημόσιο κλειδί πρέπει να είναι στον απομακρυσμένο host, και συγκεκριμένα στο αρχείο ~/.ssh/authorized_keys του λογαριασμού που μας ενδιαφέρει. (Το authorized_keys επιτρέπεται να περιλαμβάνει περισσότερα από ένα δημόσια κλειδιά.)
  • Ξεκινάμε τη σύνδεση και το πρώτο πράγμα που κάνει ο client είναι να ενημερώσει τον SSH server ότι επιθυμούμε key-based authentication. Επίσης, του λέει ποιο είναι το δημόσιο κλειδί μας.
  • Ο server ελέγχει για την παρουσία του δημοσίου κλειδιού στο ~/.ssh/authorized_keys. Αν το βρει, παράγει ένα τυχαίο string κι αμέσως το κρυπτογραφεί με χρήση του δημοσίου κλειδιού. Προφανώς, το κρυπτογραφημένο αυτό μήνυμα μπορεί ν' αποκρυπτογραφηθεί μόνο με χρήση του σωστού ιδιωτικού κλειδιού, το οποίο υποτίθεται ότι κατέχουμε μόνον εμείς. Η πρόκληση από πλευράς SSH server, λοιπόν, είναι να μας στείλει το κρυπτογραφημένο αυτό μήνυμα.
  • Μόλις ο client λάβει το κρυπτογραφημένο μήνυμα, το αποκρυπτογραφεί με χρήση του αντίστοιχου ιδιωτικού κλειδιού. Την αποκρυπτογραφημένη εκδοχή τη συνδυάζει με το λεγόμενο session ID της σύνδεσης που επιχειρείται να εγκαθιδρυθεί. Παίρνει έτσι ένα νέο μήνυμα και υπολογίζει το hash του, το οποίο στέλνει στον απομακρυσμένο SSH server.
  • Εκείνος έχει το αρχικό (μη-κρυπτογραφημένο) μήνυμα, όπως επίσης και το session ID. Μπορεί, λοιπόν, να υπολογίσει το hash του συνδυασμένου μηνύματος και να το συγκρίνει μ' εκείνο που μόλις έλαβε από τον client. Αν τα δύο hashes ταυτίζονται, συμπεραίνει ότι ο πελάτης είναι ο κάτοχος του σωστού ιδιωτικού κλειδιού, επομένως του επιτρέπει την πρόσβαση.

Η παραπάνω διαδικασία γίνεται αυτοματοποιημένα μεταξύ SSH server και SSH client, κι εμείς από τη μεριά μας δεν πληκτρολογούμε κάτι. Το πολύ πολύ να χρειαστεί να δώσουμε το passphrase του ιδιωτικού μας κλειδιού, αν προστατεύεται από τέτοιο. Σε κάθε περίπτωση, κατά τη διάρκεια του authentication δεν μεταδίδονται ευαίσθητες πληροφορίες. Σημειώνουμε, τέλος, ότι αμέσως μετά την αποδοχή του client, τα δύο μηχανήματα επικοινωνούν μέσω ενός (ισχυρά) κρυπτογραφημένου καναλιού.

Στις επόμενες δύο ενότητες βλέπουμε πώς παράγουμε ζεύγη κλειδιών αλλά και πώς συνδεόμαστε χωρίς password σε απομακρυσμένα hosts, ξεκινώντας από Unixοειδές σύστημα.

Passwordless logins από Linux, OS X, *BSD

Κάνουμε την επίδειξή μας από ένα laptop με Linux Mint, υπογραμμίζουμε ωστόσο ότι εντελώς παρόμοιες διαδικασίες ισχύουν σε κάθε Unix-like OS. Για τη δημιουργία ενός ζεύγους κλειδιών χρησιμοποιούμε το εργαλείο ssh-keygen. Εξ ορισμού, το προγραμματάκι παράγει ζεύγη RSA μήκους 2048 bits και δεν έχουμε λόγο να μην τα προτιμήσουμε. Ανοίγουμε, λοιπόν, ένα παράθυρο τερματικού και πληκτρολογούμε:


ssh-keygen

Αποτέλεσμα:


Generating public/private rsa key pair.
Enter file in which to save the key (/home/sub0/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/sub0/.ssh/id_rsa.
Your public key has been saved in /home/sub0/.ssh/id_rsa.pub.
The key fingerprint is:

f2:a5:9c:53:94:2c:3a:fb:ed:02:b1:33:0d:27:87:85 sub0@blackbook

The key's randomart image is:

+--[ RSA 2048]----+
|       .         |
|      E .. .     |
|       o. +      |
|      =.oo       |
|      +OS o      |
|      =*.=       |
|      .+*        |
|       ..o       |
|        .oo      |
+-----------------+

Το ιδιωτικό κλειδί είναι στο αρχείο id_rsa, μέσα στον κατάλογο ~/.ssh. Το δε δημόσιο κλειδί είναι στο αρχείο id_rsa.pub, επίσης μέσα στον κατάλογο ~/.ssh. Παρατηρήστε ότι επιλέξαμε να μην προστατεύσουμε το ιδιωτικό κλειδί με κάποιο passphrase. Κάτι τέτοιο είναι επιθυμητό όταν επιδιώκουμε την αυτόματη εκτέλεση scripts, τα οποία συνδέονται σε απομακρυσμένα hosts μέσω SSH και χωρίς καμία αλληλεπίδραση με το χρήστη.

Σημείωση

Είπαμε πριν από λίγο ότι για το παράδειγμά μας χρησιμοποιούμε laptop, οπότε τώρα ίσως σκεφτείτε ότι τα laptops είναι σχετικά εύκολο να κλαπούν ή έστω να ξεχαστούν κάπου και να χαθούν. Σε μια τέτοια περίπτωση, ο νέος ιδιοκτήτης του laptop δεν θα αργήσει να βρει το ιδιωτικό μας κλειδί – ή τουλάχιστον είναι αρκετά πιθανό να το βρει. Από τη στιγμή που το κλειδί δεν προστατεύεται από passphrase, ο επιτιθέμενος δεν αποκλείεται να φτάσει στους server μας πριν προλάβουμε να συνδεθούμε και να διαγράψουμε το αντίστοιχο δημόσιο κλειδί. Κάπως έτσι έχουν τα πράγματα αλλά υπάρχει και κάτι που δεν αναφέραμε, αφού δεν αποτελεί αντικείμενο του παρόντος άρθρου: Αν έχουμε φροντίσει να κρυπτογραφήσουμε το δίσκο του laptop, τότε πριν φτάσει ο αντίπαλός μας στο ιδιωτικό κλειδί θα πρέπει να προσπεράσει την κρυπτογράφηση του δίσκου. Καλή του τύχη.

Ας δούμε πώς μεταφέρουμε το δημόσιο κλειδί (~/.ssh/id_rsa.pub) σε ένα απομακρυσμένο host. Εδώ διακρίνουμε δύο περιπτώσεις.

Περίπτωση 1: Το password-based authentication επιτρέπεται. Ο ευκολότερος τρόπος είναι να καταφύγουμε στο εργαλείο ssh-copy-id. Για τη χρήση του δεν έχουμε να πούμε πολλά. Δείτε, π.χ., τη μεταφορά του δημοσίου κλειδιού μας στο λογαριασμό pi ενός Raspberry Pi, με FQDN (Fully Qualified Domain Name) το icepi.parabing.net:


ssh-copy-id pi@icepi.parabing.net

Αποτέλεσμα:


The authenticity of host 'icepi.parabing.net (10.10.10.245)' can't be established.
ECDSA key fingerprint is 12:64:d9:52:d1:8f:41:70:d1:20:cb:b1:1d:df:1a:48.
Are you sure you want to continue connecting (yes/no)? yes

/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

pi@icepi.parabing.net's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'pi@icepi.parabing.net'"
and check to make sure that only the key(s) you wanted were added.

Επειδή το πρόγραμμα δεν μπορεί να γνωρίζει ότι το icepi είναι πράγματι αυτό που είναι (κι όχι, π.χ., κάποιος rogue host σε αποστολή MiTM), περιμένει από εμάς να επιβεβαιώσουμε τη σύνδεση. Το κάνουμε και στη συνέχεια μας ζητά να πληκτρολογήσουμε το password του χρήστη pi, στο icepi.parabing.net. Το πληκτρολογούμε και η μεταφορά ολοκληρώνεται επιτυχώς. Στο εξής μπορούμε να συνδεόμαστε στο icepi.parabing.net χωρίς να πληκτρολογούμε password.

Στην περίπτωση που το ssh-copy-id απουσιάζει από το σύστημά μας, μπορούμε να μεταφέρουμε το id_rsa.pub με τη βοήθεια ενός προγράμματος σαν το scp (εκτελεί μεταφορές αρχείων μέσω SSH). Δείτε:


scp /home/sub0/.ssh/id_rsa.pub pi@icepi.parabing.net:~/

Αποτέλεσμα:


pi@icepi.parabing.net's password:
id_rsa.pub	100%  396     0.4KB/s   00:00

Μετά τη μεταφορά, συνδεόμαστε στο icepi μέσω SSH:


ssh pi@icepi.parabing.net

Αν ο κατάλογος ~/.ssh δεν υπάρχει, τον δημιουργούμε:


mkdir ~/.ssh

Φροντίζουμε ώστε δικαιώματα πρόσβασης να έχει μόνον ο ιδιοκτήτης, δηλαδή στην περίπτωσή μας μόνον ο χρήστης pi:


chmod 700 .ssh

Στη συνέχεια φτιάχνουμε, αν δεν υπάρχει ήδη, το αρχείο ~/.ssh/authorized_keys, και μέσα του προσθέτουμε τα περιεχόμενα του αρχείου ~/id_pub.rsa:


touch ~/.ssh/authorized_keys
cat id_rsa.pub >> .ssh/authorized_keys

Αυτό ήταν. Στην επόμενη σύνδεση κατά SSH στο λογαριασμό pi του icepi.parabing.net, password δεν θα μας ζητηθεί.

Περίπτωση 2: Επιτρέπεται μόνο το key-based authentication. Είναι πιθανό να έχουμε φροντίσει από κάποιο άλλο μηχάνημα για passwordless logins και, επιπρόσθετα, για λόγους ασφαλείας να έχουμε απενεργοποιήσει το password-based authentication. Μ' άλλα λόγια, για τον απομακρυσμένο host που μας ενδιαφέρει ισχύει μόνο το key-based authentication, αλλά από το μηχάνημα που τώρα βρισκόμαστε είναι αδύνατον να το έχουμε: το δημόσιο κλειδί του λογαριασμού μας απουσιάζει από τον απομακρυσμένο λογαριασμό. Μοιάζει λίγο δύσκολη η κατάστασή μας, όμως στην πραγματικότητα δεν είναι. Πράγματι, μπορούμε να μεταφέρουμε το ~/.ssh/id_rsa.pub στον υπολογιστή από τον οποίο έχουμε πρόσβαση στο remote host, να συνδεθούμε και μετά να προσθέσουμε το περιεχόμενο του id_rsa.pub στο τέλος του αρχείου ~/.ssh/authorized_keys – ένα απλό copy/paste είναι αρκετό. Μετά λοιπόν την ενημέρωση του authorized_keys, θα έχουμε δυνατότητα για passwordless logins και από το άλλο μηχάνημα (π.χ., το laptop του παραδείγματός μας).

Ασφάλεια και ευκολία, αλλά με αντάλλαγμα

Χάρη στις τεχνικές της κρυπτογραφίας δημοσίου κλειδιού, με το SSH είναι δυνατό να έχουμε υψηλό επίπεδο ασφάλειας (ισχυρά κρυπτογραφημένες συνδέσεις) και την ίδια στιγμή μεγάλη ευκολία (passwordless logins). Υπάρχει όμως κι ένα τίμημα: Αν θέλουμε να χαρακτηριζόμαστε ως καλοί διαχειριστές και πράγματι να είμαστε, οφείλουμε να κρατάμε ενημερωμένα τα αρχεία authorized_keys στα διάφορα μηχανήματα ή/και (cloud) servers που συντηρούμε. Τα εν λόγω αρχεία καλό είναι να περιλαμβάνουν μόνο το ελάχιστο πλήθος δημοσίων κλειδιών, τα οποία προέρχονται από εν ενεργεία clients που είναι απαραίτητο να συνδέονται στον εκάστοτε remote host. Βεβαίως, σε περίπτωση που χάνουμε τον έλεγχο ενός ιδιωτικού κλειδιού, τότε αμέσως πρέπει να εξαφανίζουμε κάθε παρουσία του αντίστοιχου δημοσίου κλειδιού.

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

Αν πάλι έχουμε ασφαλίσει το ιδιωτικό κλειδί με passphrase, τότε και να πέσει σε ξένα χέρια δεν υπάρχει σοβαρός λόγος για ανησυχία – αρκεί βέβαια το passphrase να είναι ισχυρό. Το καλύτερο passphrase είναι ένα εντελώς τυχαίο string με μεγάλο μήκος, π.χ., τουλάχιστον 25 χαρακτήρες, που συνδυάζει πεζά και κεφαλαία, αριθμούς και ειδικούς χαρακτήρες. Για την παραγωγή ενός πραγματικά τυχαίου και ισχυρού passphrase, δεν είναι κακή ιδέα να καταφεύγουμε σε κάποιον password manager όπως, π.χ., είναι το BitWarden. Μεταξύ άλλων, το BitWarden επιτρέπει τη δημιουργία ασφαλών σημειώσεων, οπότε μπορούμε να έχουμε μία σημείωση με το passphrase ή τα passphrases που πρέπει να δίνουμε αλλά αδυνατούμε να θυμόμαστε.