Linux

SSH Port Forwarding HOWTO

09/11/2010 01:02 μμ | apoikos από apoikos


Εισαγωγή στο SSH Tunneling

(ή αλλιώς «Κόλπα τρελλά και έξαλλα με το OpenSSH»)

 

Οι περισσότεροι χρήστες *ΝΙΧ συστημάτων θα έχουν χρησιμοποιήσει έστω και μια φορά το ssh για να χειριστούν ένα απομακρυσμένο μηχάνημα. Ενώ όμως η πλειοψηφία των χρηστών αντιμετωπίζει το ssh ως απλά ένα πρόγραμμα για απομακρυσμένο έλεγχο ένος *NIX μηχανήματος, στην πραγματικότητα το OpenSSH προσφέρει πολλά παραπάνω, μεταξύ των οποίων και τη δυνατότητα δημιουργίας κρυπογραφημένων tunnels για την προώθηση τυχαίας κίνησης από ένα μηχάνημα σε ένα άλλο.

 

Το SSH Tunneling είναι ένα πολύ δυνατό εργαλείο και μπορεί να χρησιμοποιηθεί σε πολλές περιπτώσεις, μεταξύ των οποίων:

  • Κρυπτογράφιση εγγενώς ανασφαλών πρωτοκόλλων, αφού το ssh tunnel περνάει μέσα από το κανονικό, κρυπτογραφημένο SSH session
  • Παροχή υπηρεσιών μόνο σε χρήστες με τοπικούς λογαριασμούς σε συγκεκριμένα μηχανήματα
  • Παράκαμψη διάφορων περιορισμών firewalls
  • NAT traversal
  • X Forwarding

Ο παρών οδηγός αποσκοπεί στο να δώσει κάποιες εισαγωγικές γνώσεις πάνω στο θέμα του SSH tunneling. Δυστυχώς λόγω έλλειψης χρόνου δεν είναι τόσο καλογραμμένος όσο θα ήθελα, γι' αυτό και θα κάνω ό,τι μπορώ για να καλύψω οποιεσδήποτε απορίες δημιουργηθούν, καθώς και για να συμπληρώσω τον οδηγό με νέο υλικό.

 

Ας ξεκινήσουμε λοιπόν ρίχνοντας μια ματιά στις διαφορετικές λειτουργίες tunneling που παρέχονται από το Openssh:

  • Local port forwarding: Η λειτουργία αυτή επιτρέπει την προώθηση μιας θύρας του τοπικού μηχανήματος (1) σε ένα άλλο μηχάνημα (2), μέσω ενός τρίτου μηχανήματος (3). Η κίνηση μεταξύ του 1 και του 3 είναι κρυπτογραφημένη, ενώ η σύνδεση ανάμεσα στον 1 και στον 2 φαίνεται σα να προέρχεται από τον 3.
  • Remote port forwarding: Η λειτουργία αυτή επιτρέπει την προώθηση μιας θύρας του απομακρυσμένου μηχανήματος (2) στο οποίο συνδεόμαστε μέσω SSH, μέσω του τοπικού μηχανήματος (1), σε ένα τρίτο μηχάνημα (3). Και πάλι όλη η κίνηση μεταξύ του 2 και του 1 είναι κρυπτογραφημένη, ενώ η σύνδεση του 2 στον 3 φαίνεται σα να προέρχεται από τον 1.
  • X Forwarding: Ειδική λειτουργία για remote Χ μέσα από το κρυπτογραφημένο κανάλι.
  • SOCKS proxy: Το ssh λειτουργεί σαν SOCKS proxy, διοχετεύοντας όλες τις συνδέσεις προς τρίτους υπολογιστές μέσω του υπολογιστή στον οποίο συνδέεται.

Στη συνέχεια θα εξετάσουμε κάποια σενάρια εφαρμογής του κάθε τρόπου tunneling, ώστε να γίνουν καλύτερα αντιληπτές οι ανάγκες που αυτός εξυπηρετεί.

 

 

Local port forwarding

Σενάριο 1

Είμαστε στο μηχάνημα Α και θέλουμε να συνδεθούμε σε ένα service του μηχανήματος Β (π.χ. στη θύρα 12345), όμως το εταιρικό/πανεπιστημιακό/whatever firewall κόβει τη συγκεκριμένη θύρα, ενώ αφήνει ssh. Και τα 2 μηχανήματα τρέχουν Linux. Στην περίπτωση αυτή μπορούμε να τρέξουμε:

>ssh -L 12345:localhost:12345 μηχάνημα_Β

Το ενδιαφέρον στην εντολή αυτή είναι - προφανώς - το -L 12345:localhost:12345, το οποίο μεταφράζεται ως local_port:hostname:port. Κάνει δηλαδή forward τη θύρα local_port του τοπικού μηχανήματος στην port του hostname. Προσοχή θέλει εδώ το γεγονός ότι το hostname είναι σχετικό ως προς το μηχάνημα στο οποίο συνδεόμαστε, επομένως το "localhost" αναφέρεται στο μηχάνημα εκείνο. Αφού τρέξουμε την παραπάνω εντολή, μπορούμε να στρέψουμε τον client μας στο localhost:12345 και να χρησιμοποιήσουμε την υπηρεσία του απομακρυσμένου υπολογιστή.

Στην παρακάτω εικόνα φαίνεται σχηματικά η διαδικασία που ακολουθείται. Με πράσινο χρώμα απεικονίζεται η σύνδεση SSH μεταξύ Α και Β, ενώ με μπλε διακεκομμένο η πορεία που ακολουθεί η forwarded σύνδεση.

ssh-local.png

 

Σενάριο 2

Είμαστε στο μηχάνημα Α και θέλουμε να συνδεθούμε σε ένα service του μηχανήματος B (π.χ. web), το οποίο όμως βρίσκεται πίσω από NAT. Έχουμε όμως πρόσβαση από το internet στο μηχάνημα Γ που τρέχει OpenSSH, και το οποίο βρίσκεται στο ίδιο δίκτυο με το B. Στην περίπτωση αυτή αρκεί να δώσουμε:

>ssh -L 2000:μηχάνημα_B:80 μηχάνημα Γ

Και μετά να κατευθύνουμε τον browser μας στη διεύθυνση localhost:2000, η οποία οδηγείται μέσα από το κρυπτογραφημένο κανάλι (πράσινο) στον Γ και από 'κει στο Β. Τονίζεται πάλι ότι ο Β βλέπει τη σύνδεση σα να προέρχεται από τον Γ.

 

ssh-local2.png

 

Παρατηρήστε ότι εδώ χρησιμοποιήσαμε τη θύρα 2000 στο τοπικό μηχάνημα, και όχι την 80. Ο βασικός λόγος είναι ότι για να χρησιμοποιήσει κανείς τις θύρες 0-1023 (να κάνει bind σε αυτές δηλαδή), θα πρέπει να έχει root privileges, κάτι το οποίο γενικά δεν ισχύει. Η εντολή ssh -L 80:remote_host:80 another_host δηλαδή θα λειτουργήσει μόνο για τον root και όχι για έναν κοινό χρήστη.

 

 

Remote port forwarding

H λογική του remote port forwarding είναι ακριβώς η αντίστροφη από αυτή του local port forwarding:

>ssh -R port:remote_host:remote_port host

Η εντολή αυτή κάνει forward τη θύρα port του host στην remote_host:remote_port μέσα από το τοπικό μηχάνημα (αυτό απ' το οποίο συνδεόμαστε). Χωρίς να πειράξει κανείς το /etc/ssh/sshd_config, η port θα κάνει πάντα listen στην 127.0.0.1, δηλαδή το tunnel θα είναι προσβάσιμο μόνο από τον host και από κανέναν άλλο.

Σενάριο:

Έστω ότι δουλεύουμε σε ένα workstation μέσα σε ένα τοπικό δίκτυο που βγαίνει στο internet μέσω NAT. Θέλουμε να κάνουμε μια δουλειά στο απομακρυσμένο μηχάνημα_Α, κατά την οποία θα χρειαστούμε δεδομένα από το μηχάνημα_Β, που βρίσκεται στο ίδιο δίκτυο με το workstation μας και τρέχει Windows (φερ ειπείν). Εφόσον το μηχάνημα Β είναι πίσω από ΝΑΤ, το μηχάνημα_Α εν γένει δεν έχει απευθείας πρόσβαση στα services του. Συνδεόμαστε λοιπόν στο μηχάνημα_Α με την εξής εντολή:

> ssh -R 2000:μηχάνημα_Β:80 μηχάνημα_Α 

Αφού συνδεθούμε, μπορούμε να χρησιμοποιήσουμε τη θύρα 2000 του μηχάνημα_Α για να βγούμε διαφανώς στο μηχάνημα_Β και να πάρουμε τα δεδομένα που θέλουμε (κρυπτογραφημένα πάντα).

 

ssh-remote.png

 

Παρατηρήστε τη διαφορά σε σχέση με το προηγούμενο σχήμα του local port forwarding: το μόνο που έχει αλλάξει είναι ότι τώρα ο σταθμός εργασίας μας βρίσκεται στη μέση της «αλυσίδας», ενώ στην περίπτωση του local port forwarding βρισκόταν στην άκρη.

 

 

X Forwarding

Τo X-Windowing system λειτουργεί σε ένα μοντέλο client-server: server είναι το process που αναλαμβάνει να απεικονίσει τα παράθυρα στην οθόνη, ενώ clients είναι όλες οι εφαρμογές. Εφ' όσον λοιπόν λειτουργεί «δικτυακά», εξυπακούεται ότι δεν υπάρχει απαίτηση οι clients και ο server να είναι στο ίδιο μηχάνημα. Με άλλα λόγια, μπορούμε να τρέχουμε εφαρμογές σε ένα remote μηχάνημα, και τα παράθυρά τους να ανοίγουν κανονικά στο τοπικό μας μηχάνημα σα να τις τρέχαμε εδώ. Ο απλούστερος και ασφαλέστερος τρόπος για να επιτύχουμε το παραπάνω, είναι να ενεργοποιήσουμε την επιλογή "X11Forwarding" στο /etc/ssh/sshd_config του απομακρυσμένου μηχανήματος και μετά να συνδεθούμε τρέχοντας:

>ssh -X remote_host

ή

>ssh -Y remote_host

Στη συνέχεια αρκεί απλά να τρέξουμε μια εφαρμογή στο shell που θα εμφανιστεί, και το παράθυρό της θα απεικονιστεί στην οθόνη μας. Προσοχή ωστόσο, το X Forwarding θέλει αρκετό bandwidth. Για αργές γραμμές (= DSL και κάτω), συνιστάται η χρήση VNC.

 

 

Socks Proxy

Ας επανέλθουμε στο «σενάριο 1» του local port forwarding:

Είμαστε σε ένα workstation με openssh client πίσω απο ένα firewall που επιτρέπει μόνο τις θύρες 22 και 80, και θέλουμε να χρησιμοποιήσουμε services σε διαφορετικά μηχανήματα και διαφορετικές θύρες. Τυχαίνει να έχουμε πρόσβαση σε ένα *NIX box (p.x. μηχάνημα_Α) με openssh server (π.χ. το pc στο σπίτι ή κάποιο άλλο μηχάνημα εκτός του firewall), το οποίο και θα χρησιμοποιήσουμε ως SOCKS proxy:

>ssh -D 8080 μηχάνημα_Α

Αυτό ήταν! Τώρα απλά χρειάζεται να δηλώσουμε στο browser μας ή σε οποιαδήποτε άλλη εφαρμογή θέλουμε, την 127.0.0.1:8080 ως SOCKS proxy και να το χρησιμοποιήσουμε κανονικά όπως αν ήταν συνδεδεμένο απευθείας στο internet χωρίς τους περιορισμούς του firewall. Όλες οι συνδέσεις που περνάνε από τον proxy θα φαίνονται σα να ξεκινάνε από το μηχάνημα_Α, ενώ από το workstation μας μέχρι το μηχάνημα_Α θα περνάνε κρυπτογραφημένες :-)

 

 

Tips & Tricks

Δυναμική προσθήκη tunnels:

Είναι δυνατή η προσθήκη tunnels σε μια τρέχουσα συνεδρία ssh. Η προσθήκη γίνεται χρησιμοποιώντας το command mode του ssh, στο οποίο βγαίνουμε πατώντας <Enter>~C. Το prompt θα αλλάξει σε ssh>, οπότε μπορούμε να προσθέσουμε tunnels χρησιμοποιώντας τη σύνταξη της γραμμής εντολών, π.χ.

>ssh> -L2000:remote_host:80

 

PuTTY

Το PuTTY (ο καλύτερος SSH client για Windows κατά τη γνώμη του γράφοντος) υποστηρίζει όλες τις λειτουργίες tunneling του OpenSSH.

 

 

Σημειώσεις

Από την έκδοση 4.3p1 και μετά, το OpenSSH παρέχει δυνατότητα κανονικού VPN, χρησιμοποιώντας τον TUN/TAP driver του Linux. Ωστόσο το στήσιμο αυτής της υπηρεσίας ξεφεύγει από το σκοπό του παρόντος οδηγού, που είναι μια εισαγωγή στο SSH tunneling. :-)