Η φιλική πλευρά του SSH [2]




Νομίζετε ότι στο προηγούμενο μέρος εξαντλήσαμε όλες τις ευκολίες που παρέχει το SSH; Πιστεύετε ότι αυτό το πανίσχυρο εργαλείο δεν έχει τίποτε άλλο να μας προσφέρει; Μα, αν ίσχυε κάτι τέτοιο, το άρθρο που έχετε μπροστά σας δεν θα υπήρχε ;)

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

Φανταστείτε ένα σύνολο μηχανημάτων που βρίσκονται στο ίδιο τοπικό δίκτυο και βγαίνουν στο Internet μέσω ενός συγκεκριμένου μηχανήματος, που έχει το ρόλο router/gateway. Αυτή η τοπολογία δεν είναι καθόλου σπάνια κι ένα τέτοιο δίκτυο θα μπορούσε να βρίσκεται στο χώρο της δουλειάς, σε μια σχολή, σε κάποιο hacker space ή ακόμη και στο σπίτι μας. Αν υποθέσουμε ότι έχουμε πρόσβαση SSH σε όλα τα μηχανήματα του τοπικού δικτύου, πόσο εύκολο πιστεύετε ότι είναι να συνδεθούμε σε κάποιο από αυτά, ενώ είμαστε εκτός τοπικού δικτύου; Το συγκεκριμένο ερώτημα μοιάζει με εκείνο που απαντήσαμε στο τέλος του προηγούμενου άρθρου. Αυτή τη φορά όμως θα εξετάσουμε μια εντελώς διαφορετική λύση.

Προκειμένου να συνδεθούμε σε κάποιο μηχάνημα όταν είμαστε εκτός τοπικού δικτύου, λοιπόν, ένας τρόπος είναι να ακολουθήσουμε μια σχεδόν αυτονόητη διαδικασία δύο, τουλάχιστον, απλών βημάτων: α) να συνδεθούμε στη γραμμή εντολών του router και β) από εκεί να συνδεθούμε στο επιθυμητό μηχάνημα του τοπικού δικτύου. Αναρωτιέστε γιατί είπαμε ότι χρειάζονται τουλάχιστον δύο βήματα, τη στιγμή που θα μπορούσαν να υπάρχουν στον router μερικοί κανόνες port forwarding; Διότι αν το μηχάνημα στο οποίο θέλουμε να συνδεθούμε ανήκει σε κάποιο υποδίκτυο του τοπικού δικτύου, θα χρειαστεί να πραγματοποιήσουμε ένα πρόσθετο βήμα. Θα πρέπει να κάνουμε μια ενδιάμεση σύνδεση, προς το μηχάνημα που λειτουργεί ως gateway για το υποδίκτυο. Όπως αντιλαμβάνεστε, όσο αυξάνεται η πολυπλοκότητα του τοπικού δικτύου και το “βάθος” στο οποίο θέλουμε να φτάσουμε, αυξάνεται και το πλήθος των απαιτούμενων (ενδιάμεσων) συνδέσεων. Δεν χρειάζεται όμως να σκεφτόμαστε τόσο περίπλοκα σενάρια. Ακόμα και στην απλή περίπτωση των δύο βημάτων, είναι φανερό ότι η διαδικασία σύνδεσης θα καταντήσει εύκολα πολύ κουραστική. Ε, λοιπόν, το SSH μπορεί να απλοποιήσει μια τέτοια σύνδεση, απαλλάσσοντάς μας από την επανάληψη των ενδιάμεσων βημάτων *όσα* κι αν είναι αυτά. Κατά τα γνωστά, αρκεί να επέμβουμε στο αρχείο ρυθμίσεων (~/.ssh/config) και να προσθέσουμε λίγες γραμμές. Αν πιστεύετε ότι μας χτύπησε η καλοκαιρινή τεμπελιά και αναζητάμε μεθόδους για να πληκτρολογούμε λιγότερο, συνεχίστε να διαβάζετε και θα αλλάξετε γνώμη. Εκτός από άνεση και ταχύτητα, η τεχνική που θα περιγράψουμε προσφέρει και αυξημένη ασφάλεια.

Αλυσιδωτή διασύνδεση
Ας υποθέσουμε ότι θέλουμε να συνδεθούμε σ’ ένα μηχάνημα, που βρίσκεται στο τοπικό δίκτυο ενός εργαστηρίου της σχολής και έχει σαν hostname το lab-workstation3. Ας υποθέσουμε επίσης ότι το τοπικό δίκτυο του εν λόγω εργαστηρίου βγαίνει στον έξω κόσμο μέσω ενός server, στη δημόσια διεύθυνση του οποίου έχει αντιστοιχηθεί το informatics-lab.gr. Για να καταλήξουμε στη γραμμή εντολών του lab-workstation3, θα έπρεπε να συνδεθούμε πρώτα στον server του εργαστηρίου:


ssh informatics-lab.gr


Στη συνέχεια, από τη γραμμή εντολών του συγκεκριμένου μηχανήματος θα έπρεπε να δώσουμε:


ssh lab-workstation3


Φυσικά, για αυτές τις δύο συνδέσεις ενδέχεται να απαιτούνται διαφορετικά usernames, ενώ και οι SSH servers ενδέχεται ν’ ακούνε από διαφορετικές δικτυακές θύρες. Με άλλα λόγια, η διαδικασία σύνδεσης μπορεί να μην είναι τόσο απλή. Εξάλλου, ακόμη κι αν χρησιμοποιείται παντού η καθιερωμένη θύρα (port 22/TCP) κι έχουμε το ίδιο username σε όλα τα μηχανήματα (λέμε, τώρα), θα πρέπει να θυμόμαστε τα αντίστοιχα συνθηματικά. Πώς είπατε; Μπορούμε να χρησιμοποιήσουμε τη μέθοδο με το δημόσιο και το ιδιωτικό κλειδί; Αυτό θα μπορούσαμε να το κάνουμε για τη σύνδεση στο gateway, αλλά όχι και για τη σύνδεση στο μηχάνημα του τοπικού δικτύου. Για τη δεύτερη σύνδεση, βλέπετε, θα έπρεπε να αποθηκεύσουμε το ιδιωτικό μας κλειδί στον server της σχολής. Περιττό να πούμε ότι κάτι τέτοιο θα συνιστούσε τεράστιο σφάλμα! Όπως έχουμε ξαναπεί, τα ιδιωτικά κλειδιά πρέπει να φυλάσσονται πάντα με μεγάλη προσοχή και να μην κυκλοφορούν από εδώ κι από ‘κεί, για *κανένα* λόγο.



Ευτυχώς υπάρχει μια ασφαλέστερη λύση, που προσφέρει και μεγαλύτερη ευκολία. Αναφερόμαστε σε μια τεχνική που είναι γνωστή κι ως SSH chaining. Για την εφαρμογή της, αρκεί να ανοίξουμε το αρχείο ρυθμίσεων του SSH στον υπολογιστή μας (~/.ssh/config) και να προσθέσουμε τις ακόλουθες γραμμές:


Host lab-srv
HostName informatics-lab.gr
Port 34522
User pvar

Host lab-pc
ProxyCommand ssh -q lab-srv -W lab-workstation3:22
User spiral


Υποψιάζεστε τι πετυχαίνουμε με τα παραπάνω; Αρχικά δημιουργούμε ένα SSH alias, για την εύκολη σύνδεση στον server του εργαστηρίου της σχολής. Στη συνέχεια δημιουργούμε ένα ακόμα SSH alias, για τη σύνδεση στο μηχάνημα lab-workstation3. Το ενδιαφέρον εντοπίζεται στο δεύτερο alias, όπου αξιοποιούμε την επιλογή ProxyCommand. Με αυτή τη ρύθμιση ζητάμε από το SSH να μην πραγματοποιήσει τη σύνδεση αμέσως, αλλά αφού προηγουμένως εκτελέσει μια εντολή που καθορίζουμε εμείς. Όπως βλέπετε, η εντολή που επιλέξαμε είναι η ακόλουθη:


ssh -q lab-srv -W lab-workstation3:22


Με την εκτέλεση του παραπάνω πραγματοποιείται μια σύνδεση προς τον server της σχολής, μέσω της οποίας προωθούνται όλες οι επακόλουθες συνδέσεις στο μηχάνημα lab-workstation3. Τελικά, όταν χρησιμοποιούμε το δεύτερο SSH alias πραγματοποιείται αυτόματα μια βοηθητική σύνδεση προς τον server του εργαστηρίου, μέσω της οποίας προωθούμαστε στο μηχάνημα lab-workstation3. Έτσι, η σύνδεση SSH που επιχειρούμε μεταβιβάζεται αυτομάτως στο επιθυμητό μηχάνημα και χωρίς να χρειαστεί από μέρους μας κάποια πρόσθετη ενέργεια. Μετά από την προσθήκη των παραπάνω στο αρχείο ρυθμίσεων του SSH, η σύνδεσή μας στο μηχάνημα του εργαστηρίου θα μπορεί να επιτευχθεί με μία κίνηση:


ssh lab-pc


Αυτός ο τρόπος σύνδεσης είναι σαφέστατα πιο απλός και πιο γρήγορος. Όμως γιατί ισχυριστήκαμε ότι προσφέρει και περισσότερη ασφάλεια; Με τις ρυθμίσεις που παρουσιάσαμε, το σύστημά μας συνδέεται απευθείας στο μηχάνημα lab-workstation3. Μπορεί να μεσολαβεί μια βοηθητική σύνδεση, αλλά ο SSH client που τρέχει στο μηχάνημά μας, όπως και ο SSH server που εκτελείται στην άλλη άκρη, δεν το γνωρίζουν. Αυτό που πρέπει να κρατήσουμε εδώ είναι ότι η πιστοποίηση του χρήστη (authentication) πραγματοποιείται απευθείας ανάμεσα στα δύο συστήματα (το δικό μας και του εργαστηρίου). Επομένως, αρκεί να κατασκευάσουμε ένα ζεύγος κλειδιών και να εγκαταστήσουμε το δημόσιο στον server της σχολής καθώς και στο lab-workstation3. Το ιδιωτικό κλειδί θα βρίσκεται *μόνο* στο δικό μας μηχάνημα και η σύνδεση στα προαναφερθέντα συστήματα θα πραγματοποιείται κανονικότατα και με τη μέγιστη ασφάλεια.

Σημεία προσοχής
Στις ρυθμίσεις που παρουσιάσαμε προηγουμένως συνδυάσαμε τη λειτουργία ProxyCommand με μια άλλη λειτουργία του SSH, που ενεργοποιείται με την παράμετρο –W. Η σχετική γραμμή είχε ως εξής:


ProxyCommand ssh -q lab-srv -W lab-workstation3:22


Η παράμετρος –W εξασφαλίζει την προώθηση των επακόλουθων συνδέσεων και, στη συγκεκριμένη περίπτωση, το σημείο προορισμού είναι η θύρα 22 του συστήματος lab-workstation3. Αυτό βέβαια το είπαμε και προηγουμένως. Κάτι που δεν αναφέραμε είναι ότι η παράμετρος –W δεν διατίθεται στις παλιές εκδόσεις του OpenSSH, πριν από την 5.4. Επομένως, αν για κάποιο (απαράδεκτο) λόγο τα μηχανήματα διαθέτουν παλιές εκδόσεις του OpenSSH, η λύση που παρουσιάσαμε δεν θα λειτουργήσει. Στην περίπτωση που δεν είναι στο χέρι μας η αναβάθμισή τους, μπορούμε να πετύχουμε την προώθηση των επακόλουθων συνδέσεων με τη βοήθεια του netcat. Έτσι, η γραμμή με το ProxyCommand θα γίνει κάπως έτσι:


ProxyCommand ssh -q lab-srv nc –q0 lab-workstation3 22


Σημειώστε ότι η δικτυακή θύρα διακρίνεται πλέον με ένα χαρακτήρα κενού και όχι με την άνω-κάτω τελεία (colon). Παρεμπιπτόντως, η δικτυακή θύρα από την οποία ακούει ο SSH server του lab-workstation3 πρέπει να προσδιοριστεί ακριβώς εκεί όπου συμβαίνει η προώθηση και όχι σε ξεχωριστή γραμμή των ρυθμίσεων. Αν η προώθηση δεν γίνει σωστά, τότε όσες άλλες ρυθμίσεις κι αν συμπεριλάβουμε θα είναι περιττές. Για να μη σας κουράζουμε με άλλες περιγραφές, σκεφτείτε ότι αυτό θα δουλέψει κανονικά:


...
Host lab-pc
ProxyCommand ssh -q lab-srv -W lab-workstation3:32128
User spiral


Οι ακόλουθες ρυθμίσεις, όμως, θα αποτύγχαναν…


...
Host lab-pc
ProxyCommand ssh -q lab-srv -W lab-workstation3
User spiral
Port 32128


Η μέθοδος που παρουσιάσαμε θα μπορούσε να επεκταθεί πανεύκολα, για την αυτοματοποίηση περισσότερων συνδέσεων. Φανταστείτε την περίπτωση που θέλουμε να συνδεθούμε σ’ ένα μηχάνημα της δουλειάς, που βρίσκεται σε κάποιο υποδίκτυο, μέσα σε ένα άλλο υποδίκτυο του εταιρικού δικτύου. Χωρίς τον αυτοματισμό θα απαιτούνταν τέσσερις συνδέσεις: Μία προς το gateway ολόκληρου του δικτύου της δουλειάς, μία προς το gateway του πρώτου υποδικτύου, μία προς το gateway του “εμφωλευμένου” υποδικτύου και μία ακόμα προς το μηχάνημα-προορισμό. Όλα αυτά θα μπορούσαν να αυτοματοποιηθούν με ένα σύνολο ρυθμίσεων σαν το ακόλουθο:


Host work-gateway
HostName some-company-srv.gr
Port 34522
User pvar

Host rnd-subnet-gateway
ProxyCommand ssh -q work-gateway -W 192.168.1.100:32128
User pvar

Host devs-subnet-gateway
ProxyCommand ssh -q rnd-subnet-gateway -W 10.0.0.50:44156
User pvar

Host lab-pc
ProxyCommand ssh -q devs-subnet-gateway -W 192.168.1.27:2222
User spiral


Πριν προχωρήσουμε σε άλλα θέματα, αξίζει να αναφέρουμε μια ενδιαφέρουσα ιδέα. Μπορεί να σκεφτόσαστε ότι το σενάριο των αλλεπάλληλων συνδέσεων είναι αρκετά εξεζητημένο και ότι το τέχνασμα που παρουσιάσαμε είναι άχρηστο για εσάς. Ε, λοιπόν, υπάρχει ένας τρόπος να το αξιοποιήσουν σχεδόν όλοι, ακόμα κι αν δεν έχουν πρόσβαση σε εταιρικά δίκτυα, σε εργαστήρια κ.λπ. Σκεφτείτε την περίπτωση που συντηρείτε μερικά VPS, για διάφορες δουλειές ή και δοκιμές. Ένας ανορθόδοξος τρόπος να αυξήσετε την ασφάλειά τους θα ήταν να ρυθμίσετε κατάλληλα το firewall του καθενός, ώστε να δέχεται συνδέσεις SSH μόνον από ένα συγκεκριμένο VPS. Για παράδειγμα, αν έχετε τρεις servers με τα ονόματα VPS1, VPS2 και VPS3, θα μπορούσατε να τους ρυθμίσετε ώστε οι VPS2 και VPS3 να δέχονται συνδέσεις SSH μόνον από τον VPS1. Με αυτόν τον τρόπο, οι VPS2 και VPS3 θα είναι ελαφρώς πιο προστατευμένοι, ενώ εσείς θα μπορείτε να συνδεθείτε πανεύκολα, αξιοποιώντας την τεχνική που παρουσιάσαμε και το VPS1 ως ενδιάμεσο σκαλοπάτι. Ακόμα κι αν καταφέρει κανείς να εισβάλει στο VPS1, οι άλλοι δύο servers θα παραμείνουν ασφαλείς, αφού το ιδιωτικό κλειδί για τη σύνδεση θα βρίσκεται μόνο στο δικό σας μηχάνημα.

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

Το SSH προσφέρει μια αποδοτική λύση γι’ αυτό το πρόβλημα, που ακούει στο όνομα SSH multiplexing. Με απλά λόγια, πρόκειται για τη διατήρηση των συνδέσεών μας στο υπόβαθρο του συστήματος, ακόμα και όταν ζητάμε τον τερματισμό τους. Όταν επιχειρούμε μια σύνδεση που είχαμε πραγματοποιήσει νωρίτερα, η εγκαθίδρυσή της πραγματοποιείται σχεδόν ακαριαία! Στην πραγματικότητα δεν δημιουργείται νέα σύνδεση, αλλά ενεργοποιείται και επιστρέφει στο προσκήνιο η παλιά. Κι αν για κάποιο λόγο ζητήσουμε τη δημιουργία μιας πρόσθετης σύνδεσης με τα ίδια χαρακτηριστικά, το SSH θα αξιοποιήσει τα αποθηκευμένα δεδομένα ώστε να παρακάμψει αρκετά στάδια της αρχικοποίησης της σύνδεσης. Με αυτόν τον τρόπο, η δημιουργία συνδέσεων που είχαν πραγματοποιηθεί και νωρίτερα επιταχύνεται σε μεγάλο βαθμό. Προκειμένου να ενεργοποιήσουμε το σχετικό μηχανισμό, πρέπει πρώτα να δημιουργήσουμε έναν κατάλογο για την αποθήκευση των δεδομένων των συνδέσεων:


mkdir ~/.ssh/tmp
chmod 700 ~/.ssh/tmp


Αμέσως μετά τη δημιουργία είναι φρόνιμο να τροποποιήσουμε τα δικαιώματα πρόσβασης. Όπως βλέπετε, απαγορεύουμε κάθε ενέργεια στους υπόλοιπους χρήστες και επιτρέπουμε τα πάντα για το δικό μας λογαριασμό και μόνο. Αυτό το κάνουμε γιατί τα αρχεία που θα τοποθετούνται στο συγκεκριμένο κατάλογο θα περιλαμβάνουν κρίσιμα δεδομένα για τις συνδέσεις μας κι εν δυνάμει ευαίσθητα. Στη συνέχεια μπορούμε να ανοίξουμε το αρχείο ρυθμίσεων (~/.ssh/config) και να ενεργοποιήσουμε την “ανακύκλωση”, προσθέτοντας τις ακόλουθες γραμμές:


Host *
ControlMaster auto
ControlPath ~/.ssh/tmp/%h-%r-%p
ControlPersist 900


Το ControlPath προσδιορίζει τη θέση και τη μορφή των ονομάτων των αρχείων που δημιουργούνται για κάθε σύνδεση. Τα %h, %r και %p αντικαθίστανται αυτόματα από το όνομα του μηχανήματος στο οποίο έχουμε συνδεθεί, το username που χρησιμοποιήσαμε για τη σύνδεση και τη δικτυακή θύρα του απομακρυσμένου συστήματος. Έτσι, εξασφαλίζουμε ότι τα αρχεία που δημιουργούνται έχουν μοναδικά ονόματα, που προσδιορίζουν πλήρως την εκάστοτε σύνδεση. Το μέγεθος ControlPersist αποτελεί το χρονικό διάστημα κατά το οποίο θα διατηρείται στο δίσκο κάθε ανενεργή σύνδεση. Η μονάδα μέτρησης που υπονοείται είναι τα δευτερόλεπτα και κατ’ επέκταση, η τιμή που φαίνεται παραπάνω (900) αντιστοιχεί σε 15 λεπτά. Η επιλογή αυτής της τιμής πραγματοποιήθηκε αυθαίρετα και μπορείτε να την προσαρμόσετε ελεύθερα, ανάλογα με τη φύση των εργασιών σας. Πάντως, επειδή τα δεδομένα που αποθηκεύονται στο δίσκο είναι κρίσιμα, είναι φρόνιμο να μην τα διατηρούμε περισσότερο απ’ όσο χρειάζεται.

Αυτό ήταν όλο! Στο εξής, οι συνδέσεις SSH που πραγματοποιούμε συχνά –όπως και εκείνες που γίνονται σε τακτά χρονικά διαστήματα από τα σκριπτάκια μας–, θα μοιάζουν να εγκαθιδρύονται ακαριαία.

Έξυπνες ειδοποιήσεις
Στο ξεκίνημα του άρθρου κάναμε τη σιωπηρή παραδοχή ότι θα εργαστούμε στο Linux. Αν και όλες οι διανομές περιλαμβάνουν κάποιο παραθυρικό περιβάλλον, μέχρι στιγμής έχουμε εξετάσει κολπάκια και τεχνικές που εφαρμόζονται από τη γραμμή εντολών ενός τερματικού. Κάτι τέτοιο ήταν αναμενόμενο, αφού η κονσόλα προσφέρει μακράν περισσότερη ευελιξία. Αποφασίσαμε μολαταύτα να παρουσιάσουμε μια απλή τεχνική, που κατά κάποιον τρόπο φέρνει τις συνδέσεις SSH στο περιβάλλον γραφικών. Εντάξει, όχι τις ίδιες τις συνδέσεις, αλλά τις σχετικές ειδοποιήσεις (notifications). Για παράδειγμα, φανταστείτε την εμφάνιση μιας ειδοποίησης κάθε φορά που ένα script συνδέεται σε κάποιο μηχάνημα με σκοπό να δημιουργήσει αντίγραφα εφεδρείας. Για να πετύχουμε κάτι τέτοιο, θα επιστρατεύσουμε ένα εργαλείο της γραμμής εντολών που ονομάζεται notify-send. Στις διανομές που βασίζονται στο Debian, το εν λόγω πρόγραμμα βρίσκεται στο πακέτο libnotify-bin. Αν δεν υπάρχει ήδη στο σύστημά μας, μπορεί να εγκατασταθεί ως εξής:


sudo apt-get install libnotify-bin


Το ίδιο πρόγραμμα, στο openSUSE και στις συγγενικές διανομές βρίσκεται στο πακέτο libnotify-tools και η εγκατάστασή του πραγματοποιείται εξίσου εύκολα (sudo zypper install libnotify-tools). Αφού εξασφαλίσουμε ότι το notify-send λειτουργεί κανονικά, μπορούμε να προχωρήσουμε στην κατάλληλη ρύθμιση του SSH. Αφού ανοίξουμε και πάλι το αρχείο ρυθμίσεων (~/.ssh/config), αρκεί να προσθέσουμε τα εξής:


Host *
PermitLocalCommand yes
LocalCommand ~/bin/notify.sh %h %r


Σημειώστε ότι αν το αρχείο ρυθμίσεων περιλαμβάνει ήδη ένα μπλοκ για όλες τις συνδέσεις (Host *), δεν χρειάζεται να δημιουργήσετε και πρόσθετο (δεν θα ήταν κομψό). Αντίθετα, στο υπάρχον μπλοκ μπορείτε να προσθέσετε τις ρυθμίσεις που φαίνονται παραπάνω. Η λειτουργία LocalCommand προβλέπει την εκτέλεση μιας “εντολής” τοπικά (στο δικό μας μηχάνημα), κάθε φορά που πραγματοποιείται μια σύνδεση. Στη συγκεκριμένη περίπτωση η εντολή που καθορίσαμε είναι το script ονόματι notify.sh, που βρίσκεται μέσα στο home directory του λογαριασμού μας και στον κατάλογο bin. Τα μεγέθη %h και %r αντικαθίστανται αυτόματα από το όνομα του εκάστοτε server κι από το όνομα του user account στο απομακρυσμένο σύστημα. Τελικά, κάθε φορά που θα πραγματοποιείται μια σύνδεση SSH, θα εκτελείται αυτόματα το σκριπτάκι notify.sh με παραμέτρους το hostname του server και το username που χρησιμοποιήθηκε για τη σύνδεση.

Νομίζουμε ότι σ’ αυτό το στάδιο έχετε καταλάβει πώς λειτουργεί το συστηματάκι μας. Το notify.sh αποτελεί ένα script δικής μας κατασκευής, τα οποίο επιστρατεύει το πρόγραμμα notify-send για να εμφανίζει ειδοποιήσεις στην επιφάνεια εργασίας. Φυσικά, η εμφάνιση μιας ειδοποίησης για *κάθε* σύνδεση SSH θα ήταν περιττή και εκνευριστική. Επομένως, το notify.sh οφείλει να κάνει κάποιο φιλτράρισμα και να εμφανίζει ειδοποιήσεις μόνο για τις συνδέσεις που παρουσιάζουν ξεχωριστό ενδιαφέρον. Δείτε τη δική μας εκδοχή για το script, για να πάρετε μια ιδέα:


#!/bin/bash

hostname=$1;
username=$2;
title="SSH connection";
body="A new connection to $hostname as $username has been established";
level="low";
icon="/usr/share/icons/gnome/32x32/emblems/emblem-system.png";

[ ! $(tty -s) ] && notify-send -u "$level" -i "$icon" "$title" "$body";


Ο προγραμματισμός για το κέλυφος BASH ξεφεύγει από το σκοπό του άρθρου, όμως δεν θα δυσκολευτείτε να κατανοήσετε τι συμβαίνει. Οι μεταβλητές hostname και username παίρνουν τις τιμές τους από τις δύο παραμέτρους που παρέχονται στο script κατά την εκτέλεσή του (θυμηθείτε τα μεγέθη %h και %r, που επιστρατεύσαμε στον ορισμό του LocalCommand, μέσα στο αρχείο ρυθμίσεων του SSH). Στη συνέχεια ορίζουμε τέσσερις ακόμα μεταβλητές, που αργότερα χρησιμοποιούνται ως παράμετροι για την εκτέλεση του notify-send. Πιστεύουμε ότι η αποστολή καθεμίας από αυτές είναι αυτονόητη. Θα σας προτείναμε ωστόσο να ρίξετε μια ματιά στο manual page του notify-send, για να κατανοήσετε πλήρως τη λειτουργία του.

Ιδιαίτερο ενδιαφέρον παρουσιάζει η τελευταία γραμμή του κώδικα. Σκεφτείτε ότι το notify.sh εκτελείται στο ίδιο κέλυφος από το οποίο πραγματοποιήθηκε και η αντίστοιχη σύνδεση SSH. Αν αυτό το κέλυφος είναι διαδραστικό (interactive), συμπεραίνουμε ότι η σύνδεση πραγματοποιήθηκε χειροκίνητα (δηλαδή από το χρήστη). Αντίθετα, αν το κέλυφος δεν είναι διαδραστικό (non-interactive), συμπεραίνουμε ότι η σύνδεση πραγματοποιήθηκε από κάποιο script, στο υπόβαθρο. Ο έλεγχος με τον οποίο ξεκινά η τελευταία γραμμή του κώδικα, τσεκάρει ακριβώς αυτό: Αν το notify.sh εκτελείται μέσα σε διαδραστικό κέλυφος ή όχι. Ουσιαστικά, ελέγχουμε αν η αντίστοιχη σύνδεση πραγματοποιήθηκε από το χρήστη ή από κάποιο script. Ο έλεγχος πραγματοποιείται τσεκάροντας την τιμή που επιστρέφει το πρόγραμμα tty (η παράμετρος –s εξασφαλίζει ότι δεν θα τυπωθεί κανένα μήνυμα). Αν αυτή η τιμή είναι μηδέν, το κέλυφος είναι non-interactive. Αν η τιμή είναι μη μηδενική, το κέλυφος είναι interactive. Παρατηρείστε ότι το αποτέλεσμα του σχετικού ελέγχου αντιστρέφεται, με τη χρήση του τελεστή NOT (ο χαρακτήρας του θαυμαστικού). Τελικά, με αυτό το κολπάκι εξασφαλίζουμε ότι θα εμφανίζονται ειδοποιήσεις μόνο για τις συνδέσεις που πραγματοποιούνται από τα διάφορα scripts, στο background. Αν το καλοσκεφτείτε, κάτι τέτοιο είναι απόλυτα λογικό. Η εμφάνιση ειδοποιήσεων για τις συνδέσεις που πραγματοποιούμε μόνοι μας θα ήταν περιττή και ενοχλητική.

Ο κώδικάς που γράψαμε για το notify.sh απέχει από το να είναι ολοκληρωμένος. Καταρχάς, δεν πραγματοποιεί κανέναν έλεγχο για το πλήθος των παραμέτρων, ούτε τσεκάρει για την ύπαρξη του notify-send. Εξάλλου, θα μπορούσε να πραγματοποιεί και πιο έξυπνους ελέγχους (π.χ., σε ποιο μηχάνημα έγινε η σύνδεση και με ποιον λογαριασμό), ώστε να εμφανίζει πιο εύστοχες και κατατοπιστικές ειδοποιήσεις. Γενικότερα, ο κώδικας για το notify.sh είναι γραμμένος πρόχειρα και δεν θα πρέπει να τον χρησιμοποιήσετε ως έχει.



Προσωρινή διακοπή
Για το τέλος αφήσαμε κάτι εξαιρετικά απλό (και ταιριαστό). Μετά από τα περίπλοκα σενάρια δικτύωσης που μελετήσαμε, θυμηθήκαμε κάτι πεζό: Πώς μπορούμε να μεταφέρουμε μια σύνδεση SSH στο υπόβαθρο, ώστε να ελευθερώσουμε την κονσόλα και να την χρησιμοποιήσουμε για κάποια άλλη εργασία; Όπως θα γνωρίζετε, κάτι τέτοιο επιτυγχάνεται με το πάτημα του συνδυασμού [CTRL+Z]. Με αυτόν τον τρόπο, το πρόγραμμα που εκτελούμε μεταφέρεται στο υπόβαθρο και η λειτουργία του τίθεται σε αναστολή. Όταν θελήσουμε να επαναφέρουμε στο προσκήνιο το συγκεκριμένο πρόγραμμα, αρκεί να εκτελέσουμε την εντολή fg (από το foreground). Πολύ απλό, έτσι δεν είναι; Μόνο που αν το δοκιμάσετε μέσα σε μια σύνδεση SSH, θα διαπιστώσετε ότι δεν έχει το αναμενόμενο αποτέλεσμα. Το πάτημα των πλήκτρων, βλέπετε, θα προωθηθεί στο απομακρυσμένο μηχάνημα και δεν θα ληφθεί υπόψη από την κονσόλα του δικού μας μηχανήματος. Για να μη συμβεί αυτή η προώθηση, πρέπει να εισάγουμε μια αλληλουχία χαρακτήρων που πετυχαίνει το λεγόμενο escaping. Συγκεκριμένα, πρέπει να πατήσουμε το πλήκτρο [ENTER] κι αμέσως μετά το χαρακτήρα tilde (την περισπωμένη). Κάνοντας κάτι τέτοιο, θα παρατηρήσετε ότι δεν θα εμφανιστεί τίποτα στην οθόνη. Το SSH, όμως, θα έχει λάβει το μήνυμα κι οτιδήποτε πληκτρολογήσουμε αμέσως μετά, θα μεταβιβαστεί στην κονσόλα του δικού μας συστήματος. Με λίγα λόγια, για την αναστολή μιας σύνδεσης SSH και τη μεταφορά της στο υπόβαθρο, πρέπει να πατήσουμε το πλήκτρο [ENTER], αμέσως μετά τον χαρακτήρα tilde και στη συνέχεια το συνδυασμό πλήκτρων [CTRL+Z].

Πλέον, εκτός από τα διάφορα κόλπα για το χειρισμό των συνδέσεων SSH, γνωρίζετε και το πώς να τις αναστέλλετε. Πιστεύουμε ότι κάπου εδώ η αποστολή μας ολοκληρώθηκε — ή τουλάχιστον ολοκληρώθηκε προς το παρόν.
Σχόλια