= Ασφάλεια Δικτύων και Επικοινωνιών
Ρούσου Αντρέι - 711171075 - cs171075@uniwa.gr
:toc: left

== Εισαγωγή και Περιγραφή
[INFO]
Τα παρακάτω ζητούμενα υλοποιούνται σε Ubuntu 20.04.1 LTS Virtual Machine. Τα λογισμικά που απαιτήθηκαν για το περιβάλλον εργασίας είναι Docker και το swarmlab-sec για την δημιουργία ενός swarm cluster.

=== Docker 
Το Docker είναι λογισμικό ανοιχτό κώδικα που επιτρέπει εικονικοποίηση σε επίπεδο λειτουργικού συστήματος, ώστε να μπορεί να γίνει ανάπτυξη και δοκιμή εφαρμογών σε απομονωμένες περιοχές χρήστη που ονομάζονται docker containers. Μέσω χρήσης τεχνολογιών του πυρήνα των Linux αποφεύγεται η χρήση επιπλέον υπολογιστικών πόρων που θα απαιτούσε μια κανονική εικονική μηχανή (Virtual Machine).

=== Swarm mode
Η χρήση του Docker σε swarm mode επιτρέπει την δημιουργία ενός cluster από μηχανές Docker που ονομάζονται κόμβοι (nodes) οι οποίοι μπορούν να είναι είτε masters είτε workers. Ένας κόμβος μπορεί να έχει και τους δυο ρόλους. Οι workers λαμβάνουν και εκτελούν εργασίες που τους αναθέτουν οι masters. Αυτό δεν εμποδίζει και τους masters από το να εκτελούν οι ίδιοι εργασίες. Πέρα από αυτό, η σημαντικότερη εργασία των master είναι η διαχείριση και ο συντονισμός ολόκληρου του cluster έτσι ώστε να εμφανίζεται ομαλή λειτουργία.

=== Swarmlab-sec

TIP: Με την χρήση του swarmlab-sec μπορούμε να δημιουργήσουμε με μεγαλύτερη ευκολία Docker swarm clusters και προσφέρει επιπλέον δυνατότητες διαχείρισης του cluster. http://docs.swarmlab.io/SwarmLab-HowTos/labs/sec/sec.adoc.html[Εδώ] υπάρχουν οδηγίες σχετικά  με την εγκατάσταση.

== Προσομοίωση DoS/DDoS Attack

Σε αυτό το ζητούμενο θα γίνει μια προσομοίωση μιας επίθεσης DoS/DDoS σε έναν από τους κόμβους του cluster που θα δημιουργήσουμε. Πραγματοποιείτε συνήθως σε servers οι οποίοι υπερφορτώνονται με συνδέσεις από ένα δίκτυο υπολογιστών το οποίο μπορεί να είναι από ένας έως και εκατομμύριοι υπολογιστές και ονομάζεται botnet.

Ο επιτιθέμενος μπορεί να χρησιμοποιήσει περισσότερες τεχνικές για να αποκτήσει πρόσβαση σε πολλούς υπολογιστές και να έχει τον έλεγχο τελικά ενός botnet που στην συνέχεια θα χρησιμοποιήσει για την επίθεση του βάζοντας όλους τους υπολογιστές που έχει υπό τον έλεγχο του να κάνουν ταυτόχρονες συνδέσεις σε έναν server με αποτέλεσμα να μην αντέξει ο server το σύνολο των συνδέσεων και να βγει εκτός λειτουργίας και να μην μπορέσει να παρέχει υπηρεσίες. Μια επίθεση χαρακτηρίζεται ως DoS όταν χρησιμοποιείται ένας υπολογιστής ενώ DDoS όταν χρησιμοποιείται ένα δίκτυο υπολογιστών.

=== Χρήση του hping3 για πραγματοποίηση της επίθεσης
Το εργαλείο hping3 μπορεί να χρησιμοποιηθεί για την διεξαγωγή της επίθεσης. 

Εγκατάσταση του hping3.
```
sudo apt update
sudo apt install hping3
```
Εφόσον είμαστε μέσα στον master μέσα στο swarm, μπορούμε βρίσκοντας την IP του, με την χρήση του nmap να δούμε και τις IP διευθύνσεις των υπόλοιπων κόμβων του cluster με τις παρακάτω εντολές:
```
ifconfig 				# Διέυθυνση IP του master node
nmap -sP 172.19.0.* 	# Εμφάνιση των IP διευθύσεων των υπόλοιπων κόμβων
```
Για να επιτεθούμε χρειαζόμαστε μια ανοιχτή πόρτα (port). Ανοιχνέυουμε τις ανοιχτές πόρτες με την εντολή:
```
nmap -p 1-100 <ip-addr>
```
NOTE: H εντολή ελέγχει ποιές πόρτες από την πόρτα 1 εώς την πόρτα 100 είναι ανοιχτές για την διεύθυνση που θέλουμε να χτυπήσουμε. Περισσότερες πληροφορίες για την χρήση του nmap για ανίχνευση ανοιχτών ports υπάρχουν http://docs.swarmlab.io/SwarmLab-HowTos/labs/sec/ex-1_iptables.adoc.html#_scan_ports[εδώ].

Αφού βρούμε ποιά πόρτα είναι ανοιχτή, μπορούμε να μπούμε σε όσους workers θέλουμε να χρησιμοποιήσουμε για την επίθεση με την εντολη:
```
ssh docker@<worker-IP>
```
Σε κάθε worker πρέπει να γίνει εγκατάσταση του hping3. Αφού γίνει η εγκατάσταση, ο worker είναι έτοιμος να αρχίσει την επίθεση. Έαν η επίθεση γίνει από έναν worker τότε έχουμε DoS επίθεση, αν γίνει από περισσότερους, έχουμε DDoS επίθεση. Παρακάτω θα γίνει σύντομη περιγραφή για το πώς μπορεί να γίνει μια https://en.wikipedia.org/wiki/SYN_flood[*SYN flood*] επίθεση.

TIP: H *SYN flood DDoS* επίθεση εκμεταλλεύεται το https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_establishment[3-way handshake] του πρωτοκόλλου TCP για την έναρξη μιας σύνδεσης μεταξύ client-server. Στην περίπτωση μιας SYN flood DDoS επίθεση, ο επιτιθέμενος στέλνει επαναλμβανόμενα πάρα πολλά SYN πακέτα, χωρίς να περιμένει για SYN-ACK από την μεριά του θύματος ώστε να γίνει η σύνδεση και τα SYN-ACK πακέτα που στέλνει το θύμα δεν φτάνουν ποτέ στον επιτιθέμενο.

Αφού έχουμε έτοιμο το hping3 στους workers που θα χρησιμοποιήσουμε, μπορεί να αρχίσει η επίθεση, με την παρακάτω εντολή:
```
sudo hping3 <target-IP> -p <target-port> -S --flood
```
Όπου αναλυτικά:

<target-IP>:: Η IP διεύθυνση του θύματος.
-p <target-port>:: Η ανοιχτή πόρτα που θα χρησιμοποιηθεί.
-S:: Ορισμός τύπου πακέτου SYN.
--flood:: Flood mode, στέλνουμε επαναλαμβανόμενα χωρίς να περιμένουμε απάντηση.

Με την εκτέλεση της παραπάνω εντολής σε πολλούς κόμβους κατά ενός κόμβου μπορεί να αρχίσει η DDoS επίθεση και το θύμα λαμβάνει μεγάλο όγκο SYN πακέτων.

TIP: Μπορούν να χρησιμοποιηθούν περισσότεροι παράμετροι στην εντολή για να κάνουν την ανίχνευση και την αντιμετώπιση από το θύμα πιο δύσκολη, όπως για παράδειγμα της παραμέτρου *--rand-source* που θα άλλαζε την source-IP διεύθυνση των πακέτων για κάθε πακέτο. Περισσότερα στο https://linux.die.net/man/8/hping3[hping3-man].

=== Εντωπισμός και παρουσίαση επίθεσης με tcpdump, netstat
Για να εντωπίσουμε μια επίθεση DDoS υπάρχουν πολλά χρήσιμα εργαλεία με τα βασικά να είναι το *tcpdump* και το *netstat.*

TIP: Το https://en.wikipedia.org/wiki/Tcpdump[tcpdump] είναι command-line packet analyser, το οποίο εμφανίζει όλα τα πακέτα που στέλνονται και λαμβάνονται σε ένα δίκτυο ή σε μια διεπαφή. Το https://en.wikipedia.org/wiki/Netstat[netstat] είναι ένα command-line εργαλείο το οποίο εμφανίζει συνδέσεις δικτύου, πίνακες δρομολόγησεις, στατιστικά κ.α. Μπορούν να χρησιμοποιήθουν μαζί για ανάλυση και εντωπισμό DDoS επιθέσεων.

Για την παρουσίαση όλων των πακέτων που λαμβάνουμε μπορούμε να χρησιμοποιήσουμε την εντολη:
```
sudo tcpdump -i eth0 -n
```
Η οποία εμφανίζει όλα τα πακέτα που στέλνονται και λαμβάνονται στην διεπαφή eth0 με τις IP διευθύνσεις αυτών που στέλνουν και λαμβάνουν. Μπορεί να παρατηρηθεί να παρατηρηθεί για παράδειγμα ότι από ορισμένες διευθύνσεις ο host δέχεται υπερβολικά πολλά πακέτα SYN σε λίγο χρόνο από τις διευθύνσεις των worker nodes που χρησιμοποιούμε για την επίθεση. Μπορεί να αναλυθεί η κίνηση μάλιστα που υπάρχει σε συγκεκριμένες θύρες μέσω της εντολής:
```
sudo tcpdump port <port-no> -n
```
NOTE: Εάν τρέξουμε την εντολή *netstat* δεν παρατήρουμε κάτι το ιδιαίτερο αν δεν έχει γίνει σύνδεση μεταξύ του επιτιθέμενου και του θύματος και στην περίπτωση ενός SYN flood δεν γίνεται ποτέ σύνδεση παρά μόνο προσπάθεια σύνδεσης!

Εάν καταλαβαίνουμε ότι πρόκειται για SYN flood επίθεση, τότε μπορούμε να εμφανίσουμε μόνο τα SYN πακέτα μέσω τις εντολής:
```
sudo tcpdump 'tcp[tcpflags] == tcp-syn' -n
```
TIP: Με μια τέτοια απλή ανάλυση μπορούμε να καταλάβουμε τον τύπο της επίθεσης και την πήγη από την οποία προέρχεται. Φυσικά η διαδικασία μπορεί να γίνει πιο δύσκολη όταν έχουμε χιλιάδες άλλα πακέτα να στέλνονται και να λαμβάνονται, όπως επίσης και αν ο επιτιθέμενος κάνει την επίθεση με τύχαιες source IP διευθύνσεις καθε φορα.

=== Χρήση iptables rules για αντιμετώπιση μιας επίθεσης

Η αντιμετώπιση μιας DDoS επίθεσης μπορεί να γίνει μέσω iptables rules.

TIP: To https://en.wikipedia.org/wiki/Iptables[ip tables]  είναι ένα command-line πρόγραμμα το οποίο επιτρέπει την διαχείρηση του firewall του πυρίνα των linux, με το οποίο μπορούμε να φιλτράρουμε και να εμποδίσουμε ή να στείλουμε σε άλλον δρομολογητή πακέτα απο συγκεκριμένες διευθύνσεις ή συγκεκριμένου τύπου, το οποίο το κάνει το τέλειο εργαλείο για την αντιμετώπιση μιας DDoS επίθεσης!

Στην περίπτωση της επίθεσης SYN flood που περιγράφουμε, μπορούμε να πάρουμε κάποια βασικά αντίμετρα. Εφόσον η επίθεση γίνεται με την πραγματική διεύθυνση του επιτιθέμενου, η επίθεση μπορεί να σταματήσει πολύ εύκολα, με έναν απλό κανόνα, τον οποίο μπορούμε να ορίσουμε με την εντολή:
```
sudo iptables -A INPUT -s <source-IP> -j DROP
```
NOTE: Η παραπάνω εντολή κάνει alter, αλλάζει δηλαδή τον πίνακα για τα πακέτα που δεχόμαστε (-Α INPUT) και τα πακέτα που δεχόμαστε από την διεύθυνση IP (-s <source-IP>) τα πετάει και δεν τα δέχεται (-j DROP). Αν γίνει αυτό για όλες τις διευθύνσεις IP που στέλνουν επαναλαμβανόμενα πολλά πακέτα SYN, τότε η επίθεση σταματάει!

Οι πίνακες INPUT, FOWARD και OUTPUT μπορούν να εμφανιστούν με την χρήση της εντολής:
```
sudo iptables -L
```
Όπου θα πρέπει να φαίνονται οι κανόνες που ορίζουμε για τις διευθύνσεις από τις οποίες δεχόμαστε επίθεση. Επιπλέον πληροφορίες όπως τα πακέτα που εμπόδισε ο κανόνας μας και το μέγεθως τους μπορούν να παρουσιαστούν με την εντολή:
```
sudo iptables -nvL
```
TIP: Στην περίπτωση που αναλύουμε, οι κάνονες που ορίσαμε δούλεψαν και η επίθεση σταματάει διότι ηταν πολύ απλή προσωμοίωση. Φυσικά σε περίπτωση που ο επιτιθέμενος χρησιμοποιεί πάρα πολλούς κόμβους για την επίθεση, με κάθε πακέτο να έχει ψεύτικη διαφορετική διεύθυνση, τα πράγματα είνα διαφορετικά, καθώς θα ήταν δύσκολο να φτίαξουμε έναν κανόνα για κάθε μια από τις εκατοντάδες ή και χιλιάδες διευθύνσεις του επιτιθέμενου. Θα μπορούσαμε όμως να φιλτράρουμε τον αριθμό των SYN πακέτων που μπορούν να σταλούν για παράδειγμα που θα ήταν πολύ πιο αποτελεσματικό. 

=== Στιγμιότυπα οθόνης από προσομοίωση της επίθεσης

Παρακάτω εμφανίζονται στιγμιότυπα οθόνης από προσομοίωση μιας SYN flood DDoS επίθεσης με τον τρόπου που περιγράψαμε. Η επίθεση γίνεται από δυο workers, τον worker 2 (172.19.0.4) και τον worker 3 (172.19.0.5) κατά του worker 1 (172.19.0.3).

== SSH Brute Force

Σε αυτό το ζητούμενο θα γίνει προσομοίωση και ανάλυση μιας επίθεσης SSH Brute Force. To SSH είναι δικτυακό πρωτόκολλο που προσφέρει μεταφορά δεδομένων μεταξύ υπολογιστών. Προσφέρει ασφαλής μεταφορά δεδομένων καθώς και κρυπτογράφήση τους. Δουλεύει σε μοντέλο client-server, με τον client να ζητάει την σύνδεση και να την επαληθεύει με κωδικό η ιδιωτικό κλειδί Μια επίθεση SSH brute force έχει ως σκοπό την απόκτηση πρόσβασης σε τέτοιους SSH servers. Ο επιτιθέμενος κάνει συνεχόμενες απόπειρες σύνδεσης με χρήση πολλών συνδυασμών πιθανών κωδικών μέχρι να μπορέσει να αποκτήσει πρόσβαση. 

=== Χρήση του Hydra για την επίθεση

Για την προσομοίωση της επίθεσης, θα γίνει χρήση του εργαλείου Hydra. Ένας worker θα είναι ο SSH client που προσπαθεί να αποκτήσει πρόσβαση και ένας άλλος θα είναι ο SSH server. Για την επίθεση μπορούν να χρησιμοποιήθουν παράλληλα περισσότεροι clients (workers).

TIP: Το *Hydra* είναι εργαλείο με δυνατότητες παράλληλου υπολογισμού το οποίο προσεγγίζει πολλούς τρόπους για την πραγματοποίηση brute force επιθέσεων. Περισσότερα για το Hydra https://tools.kali.org/password-attacks/hydra[εδώ].

Η εγκατάσταση του Hydra 7.5 γίνεται με την παρακάτω εντολή:
```
sudo apt-get install hydra hydra-gtk
```
Το Hydra μπορεί να λειτουργήσει παράλληλα με άλλα προγράμματα τα οποία κάνουν generate συνδυασμούς ονομάτων χρήστη και κωδικών εισόδου. Στις οδηγίες της προσομοίωσης που θα κάνουμε για λόγους απλότητας θα χρησιμοποιήσουμε δύο αρχεία, users.txt και pass.txt τα οποία περιέχουν τυχαία συχνά ονόματα και τυχαίους συχνούς κωδικούς πρόσβασης. Έτσι η επίθεση θα γίνει πολύ γρήγορα καθώς δεν θα χρειαστεί να γίνουν υπερβολικά πολλές δοκιμές. Σε μια πραγματική επίθεση, το πρόγραμμα μπορει να δοκιμάζει κωδικούς για πολύ μεγαλύτερο χρονικό διάστημα μέχρι να μπορεί να τους πετύχει και να αποκτήσουμε πρόσβαση.

Πριν αρχίσει η επίθεση, αρκεί να γνωρίζουμε την IP του server που θέλουμε να χτυπήσουμε. Ελέγχουμε αρχικά αν τρέχει SSH service και αν έχει την default SSH πόρτα ανοιχτή με την εντολή:
```
nmap -p 22 <target-IP>
```
NOTE: Η πόρτα (port) μπορεί να είναι διαφορετική, σε αυτή την περίπτωση, θα κάναμε έλεγχο να δούμε ποιές πόρτες είναι ανοιχτές. Η default port του SSH όμως, την οποία και θα χρησιμοποιήσουμε για την επίθεση είναι η 22.

Αφου βεβαιωθούμε ότι η πόρτα είναι ανοιχτή, το μόνο που απομένει είναι να αρχίσει η επίθεση. Η εντολή του εργαλείου Hydra που θα χρησιμοποιήθει σε αυτή την περίπτωση είναι η παρακάτω:
```
hydra -L <user-file-path> -P <password-file-path> ssh://<target-ip> -t 6
```
Όπου αναλυτικά:

-L <user-file-path>:: Παράμετρος για path αρχείου με όνοματα χρήστη που θα δοκιμαστούν.
-P <password-file-path>:: Παράμετρος για path αρχείου με κωδικούς χρήστη που θα δοκιμαστούν.
ssh://<target-ip>:: Πρωτόκολλο (SSH) και IP διεύθυνση του server που προσπαθούμε να αποκτήσουμε πρόσβαση.
-t 6:: Ο αριθμός διεργασιών που θα χρησιμοποιήθουν (όσο πιο πολλές, τόσο πιο γρήγορο το αποτέλεσμα).

Με την εκτέλεση της παραπάνω εντολής μπορεί να αρχίσει η επίθεση. Για σχετικά μικρό αριθμό ονομάτων και κωδικών που θα δοκιμαστούν, όπως στα στιγμιότυπα οθόνης στο παράδειγμα που υπάρχει παρακάτων η διαδικασία δεν παίρνει πάνω από λίγα λεπτά και άν έχουμε το σωστό όνομα και το σωστό κωδικό στα αρχεία μας, η επίθεση θα είναι επιτυχής!

=== Εύρεση και αντιμετώπιση της επίθεσης με Fail2Ban

Οι brute force επιθέσεις μπορούν να είναι καταστροφικές αν γίνουν με επιτυχία, για αυτό έχει μεγάλη σημασία η πρόληψη και η γρήγορη ανίχνευση και αντιμετώπιση των επιθέσεψω ώστε να είναι ασφαλής ο server μας. Ένα εργαλείο που μπορούμε να χρησιμοποιήσουμε για να το καταφέρουμε αυτό είναι το *Fail2Ban*.

TIP: Το https://www.fail2ban.org/wiki/index.php/Main_Page[Fail2Ban] είναι framework που βοηθάει στην πρόληψη και την αντιμετώπιση brute force επιθέσεψων βάζοντας, για παράδειγμα σε SSH επιθέσεις, κανόνες σε iptables κάνοντας ban δίευθύνσεις που κάνουν πολλές απόπειρες σύνδεσης.

Η εγκατάσταση του Fail2Ban γίνεται με την παρακάτω εντολή:
```
sudo apt-get install fail2ban
```
Δοκιμάζουμε σε έναν από τους workers, στον οποίο θα το εγκαταστήσουμε και θα χρησιμοποιήσουμε ως server που θα δέχεται την επίθεση να εκκινήσουμε το Fail2Ban service ως εξής:
```
sudo service fail2ban start
```
Θα δεχτούμε ένα error τύπου:
```
* Starting authentication failure monitor fail2ban                                                                                                                                                         No file(s) found for glob /var/log/auth.log
 Failed during configuration: Have not found any log file for sshd jail
```

Αυτό διότι δεν υπάρχει auth.log αρχείο που να καταγράφει όλες τις απόπειρες σύνδεσης στον server μας μέσω SSH. Θα χρειαστούμε πρόγραμμα που κάνει ακριβώς αυτή τη δουλειά, στην περίπτωση μας θα εγκαταστήσουμε το https://www.rsyslog.com/[*rsyslog*] και θα το εκτελέσουμε με τις παρακάτω εντολές:
```
sudo apt-get install rsyslog
sudo rsyslogd
```
Πλέον μπορούμε να εκκινήσουμε κανονικά το Fail2Ban service κανονικά!

TIP: 'Εαν θέλουμε να δούμε ότι το logging των μη επιτυχημένων εισόδων γίνεται κανονικά μπορούμε να το δούμε με την εντολή: *sudo grep "Failed password" /var/log/auth.log*.

NOTE: Οι ρυθμίσεις για το πως δουλεύει το Fail2Ban βρίσκονται στο αρχείο */etc/fail2ban/jail.conf*, είναι προτεινόμενο όμως να βάζουμε τις ρυθμίσεις σε άλλο αρχείο */etc/fail2ban/jail.local*.

Δημιουργούμε το jail.local.
```
sudo vim /etc/fail2ban/jail.local
```
Ανοίγουμε το jail.local και προσθέτουμε τις παρακάτω γραμμές:
```
[sshd]
# Ενεργοποίηση του jail
enabled  = true
# SSH πόρτα
port     = 22
# SSHD Fail2Ban φίλτρο
filter   = sshd
# Path του αρχείου auth.log
logpath  = /var/log/auth.log
# Αριθμός επιτρέπόμενων απόπειρων σύνδεσης
maxretry = 4
# Χρόνος του ban (seconds)
bantime = 7200
```

Αφού αποθηκεύσουμε το αρχείο, κάνουμε επανεκκίνηση το fail2ban service ώστε να δουλέψει με το configuration μας ως εξής:
```
sudo service fail2ban restart
```
Πλέον θα πρέπει να λειτουργεί σωστά με το configuration μας. Δοκιμάζουμε επίθεση με Hydra από οποιονδήποτε worker θέλουμε να χρησιμοποήσουμε. Μπορούμε να δούμε αν το fail2ban έχει ενεργό το sshd jail και αν ανίχνευσε και σταμάτησε την brute force επίθεση με ban στην IP με την εντολή:
```
sudo fail2ban-client status
sudo fail2ban-client status sshd
```
Στις πληροφορίες που θα εμφανιστούν θα πρέπει να φαίνεται η IP του worker που έκανε την επιθέση στις banned IPs. Μπορούμε να δούμε και των κανόνα για REJECT που δημιούργησε το fail2ban με την χρήση των iptables με την εντολή:
```
sudo iptables -L -n
```
Εάν η IP του επιτιθέμενου είναι banned και υπάρχει και ο κανόνας σε iptables τότε σε απόπειρα σύνδεσεις ο επιτιθέμενος θα πρέπει να λαμβάνει μήνυμα *Connection Refused* και για το χρονικό διάστημα που είναι banned, δεν θα μπορεί να συνδεθεί. Για να μπορεί να έχει πρόσβαση πάλι κάποιος από την συγκεκριμένη IP πρέπει να γίνει unban με την εντολή:
```
sudo fail2ban-client unban <IP-address>
```

=== Eίσοδος αποκλειστικά με key
Ένας δυνατός κωδικός θα μπορούσε να προστατέψει τον server μας αρκετά από brute force επιθέσεις, όμως μπορεί να γίνει χρήση και της εισόδου με κλειδί (public key authentication), που προσφέρει και πολλά άλλα πλεονεκτήματα

NOTE: Τα https://el.wikipedia.org/wiki/RSA[RSA] κλειδία έρχονται σε ζευγάρια, ένα δημόσιο κλειδί και ένα ιδιωτικό κλειδί. Το δημόσιο κλειδί είναι γνωστό σε όλους ενώ το ιδιωτικό είναι γνωστό μόνο στον κάτοχο του. Για την σύνδεση αρκεί να αποδείξει ο client ότι κατέχει το ιδιωτικό κλειδί που αντιστοιχεί στο δημόσιο κλειδί, το οποίο γίνεται χωρίς να χρειαστεί να εμφανίσει το ιδιωτικό του κλειδί. Μάλιστα στο *SFTP* (SSH FILE TRANSFER PROTOCOL) δημόσια κλειδία χρησιμοποιούνται για την κρύπτογράφηση αρχείων τα οποία μπορούν να αποκρυπτογραφηθούν μόνο με το ιδιωτικό κλειδί.

Για αρχή θα πρέπει να γίνει το key generation στον client, το οποίο γίνεται με την εντολή:
```
ssh-keygen
```
Θα ακολουθήσει η επιλογή του path όπου θα αποθηκεύονται τα κλειδιά και επιλογή κωδικού για την χρήση του ιδιωτικού κλειδιού, το οποίο αυξάνει ακόμα περισσότερο την ασφάλεια. Αφού γίνουν οι επιλογές, θα δημιουργηθούν δύο κλειδία σε 2 αρχεία, το *id_rsa* που είναι το ιδιωτικό κλειδί και το *id_rsa.pub* που είναι το δημόσιο κλειδί. Τώρα έχει δημιουργηθεί το ζεύγος των κλειδιών μας.

Για να λειτουργήσει το public key authentication πρέπει ο server να έχει το δημόσιο κλειδί. Η αντιγραφή του δημόσιου κλειδιού στον server (ένας worker του swarm μας) γίνετε με την παρακάτω εντολή:
```
ssh-copy-id docker@<worker-IP>
```
Τώρα ο worker που έχει το δημόσιο κλειδί, μπορεί να γίνει η σύνδεση μέσω public key authentication. Μένει να τροποποιήσουμε τον server ώστε να δέχεται μόνο εισόδους μέσω κλειδιού και όχι μέσω κωδικού πρόσβασης. Θα πρέπει να γίνουν οι παρακάτω τροποποιήσεις στο αρχείο του server */etc/ssh/sshd_config*:
```
# Authentication:

#LoginGraceTime 2m
PermitRootLogin without-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#PubkeyAuthentication yes									
```
```
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no 									
#PermitEmptyPasswords no
```
Κάνουμε επανεκκίνηση του ssh με την εντολή:
```
sudo service ssh restart
```
Πλέον η είσοδος γίνεται μόνο με *public key authentication*. Σε περίπτωση που δοκιμάσουμε σύνδεση από worker για οποίο ο server δεν έχει public key θα εμφανιστεί μήνυμα της παρακάτω μορφής:
```
docker@<IP-address>: Permission denied (publickey).
```

TIP: Όλα τα δημόσια κλειδιά είναι αποθηκευμένα στον SSH server στο αρχείο *~/.ssh/authorized_keys* όπου μπορούν να προστεθούν manually κλειδιά.

=== Στιγμιότυπα οθόνης από προσομοίωση επίθεσης SSH Brute Force

Παρακάτω εμφανίζονται στιγμιότυπα οθόνης απο μια προσομοίωση επίθεσης με βάση την παραπάνω ανάλυση. Ο worker 1 (172.19.0.3) λειτουργεί ως server, ενώ άλλοι workers χρήσιμοποιούνται ως clients.

== Local/Remote SSH Fowarding

Σε αυτό το ερώτημα θα γίνει Local και Remote SSH Fowarding για την επίτευξη SSH Tunneling. Το Tunneling δημιουργεί μια σύνδεση που προσφέρει ασφαλή και κρυπτογραφημένη επικοινωνία μεταξύ του client και server. Μπορεί να χρησιμοποιήθει για πολλούς σκοπούς, μιας και με το tunneling γίνεται ασφαλής ανταλλαγή δεδομένων μεταξύ δύο αποκρυνσμένων υπολογιστών/δικτύων.

Στην παρακάτω ανάλυση θα μετατρέψουμε το μηχάνημα μας σε SSH Server που θα προσφέρει υπηρεσίες στο swarm. Θα πρέπει να γίνει εγκατάσταση του *openssh-server* με την παρακάτω εντολή, ώστε να μπορούν οι workers του swarm να συνδέονται μέσω του SSH.
```
sudo apt-get install openssh-server
```
'Επειτα θα εγκαταστήσουμε τον Apache Web Server. Το μηχάνημα μας θα δουλεύει ως Web Server. Η εγκατάστση γίνεται με την εντολή:
```
sudo apt install apache2
```
TIP: Το https://httpd.apache.org/[Apache HTTP Server Project] είναι ένα από τα πιο γνωστά εργαλεία που χρησιμοποιούνται για το στήσιμο, την ανάπτυξη και την διατήρηση ενός *HTTP Server*. Με την χρήση του μπορούμε να φιλοξενήσουμε στο μηχάνημα μας μια ιστοσελίδα που θα είναι και η υπηρεσία που θα προσφέρουμε στο swarm μας.

Πλέον εάν χρησιμοποιήσουμε τον browser μας, και πάμε στο localhost:80 θα δούμε την default ιστοσελίδα του Apache. Θα κάνουμε μερικές αλλαγές ώστε να εμφανίζει δικό μας περιεχόμενο, εκτελούμε την εντολή:
```
sudo vim /var/www/html/index.html
```
Και μέσα στο αρχείο *index.html* βάζουμε δικό μας περιεχόμενο η μπορούμε να βάλουμε αρχεία δικιά μας ιστοσελίδας. Για το παράδειγμα θα χρησιμοποιήσουμε μια πολύ απλή ιστοσελίδα με το παρακάτω περιεχόμενο.
```
<!DOCTYPE html>
<html>
  <head>
    <title>Super Webpage</title>
  </head>
  <body>
    <center>
      <h>WELCOME</h>
      <p>If you see this, it works</p>
    </center>
  </body>
</html>
```
Για την προβολή του περιεχομένου μπορεί να χρησιμοποιήθει η εντολή *curl* ενώ για την προβολή μπορούμε να χρησιμοποιήσουμε και έναν command-line browser όπως τον *lynx*. Η εγκατάσταση του *lynx* γίνεται με την παρακάτω εντολή:
```
sudo apt-get install lynx
```

TIP: O https://lynx.browser.org/[lynx] είναι command-line text based browser με πολλές δυνατότες που επιτρέπει την πλοήγηση στο διαδίκτυο από terminal.

=== Local SSH Port Fowarding
Local SSH Port Fowarding κάνουμε όταν θέλουμε να έχουμε πρόσβαση σε δεδομένα/υπηρεσίες που βρίσκονται σε έναν server και υπό κανονικές συνθήκες δεν θα είχα πρόσβαση. Σε αυτό το παράδειγμα θα κάνουμε Local SSH Port Fowarding, που θα επιτρέπει οποιοδήποτε μήχανημα του swarm που έχουμε στην διάθεση μας να επισκευτεί την ιστοσελίδα μας, σαν να τρέχει στο ίδιο το μηχάνημα του. Η εντολή που θα χρησιμοποιήσουμε, αφού συνδεθούμε στον worker που επιθυμούμε, είναι η παρακάτω:
```
ssh -nNT -L 8081:<IP-address>:80 user@<IP-address>
```

Με την παραπάνω εντολή ανοίγει ένα tunnel, ο worker μας ακούει στην πύλη 8081 για την υπηρεσία που τρέχει στον WebServer μας (<IP-address>:80) και θα αποκτήσω πρόσβαση μέσω του user@<IP-address> που έχει πρόσβαση. Αυτό έχει ως αποτέλεσμα να μπορέσουμε να πάρουμε η να προβάλουμε τα δεδομένα του index.html του WebServer μας για παράδειγμα με τις εντολές:
```
curl localhost:8081
```
ή αντίστοιχα:
```
lynx localhost:8081
```
Άρα πλέον είναι σαν η υπηρεσία του Apache να τρέχει στον worker της επιλογής μας στην πύλη της επιλογής μας, 8081 στο παράδειγμα μας.

NOTE: Έαν έχουμε IPv6 διεύθυνση στον server μας, μπορούμε να χρησιμοποιήσουμε την παράμετρο *-4* στην *ssh* εντολή που δώσαμε ώστε να δουλέψει με την IPv4 διεύθυνση, αλλίως μπορεί να εμφανιστεί error *bind: Cannot assign requested address*.

=== Remote SSH Port Fowarding
Πρόκειται για την αντίστροφη ακριβώς διαδικασία. Κάνουμε Remote SSH Port Fowarding όταν έχουμε πρόσβαση σε δεδομένα/υπηρεσία και θέλουμε να την μοιράσουμε με άλλους. Στην περίπτωση μας θα πάμε στον Web Server μας και θα εκτελέσουμε την παρακάτω εντολή:
```
ssh -nNT -R 8081:localhost:80 user@<IP-address>
```

Με την παραπάνω εντολή λέμε ότι έχουμε πρόσβαση στην υπηρεσία (localhost:80) και όποιος επιθυμεί να έχει πρόσβαση να έρθει σε εμένα (user@<IP-address>) μέσω της πόρτας 8081. Αυτό επιτρέπει σε οποιονδήποτε να έχει πρόσβαση στην υπηρεσία μέσω της 8081 του Web Server μας, που σε αυτή την περίπτωση φιλοξενεί και την ιστοσελίδα.

Πρέπει όμως και να έχουμε ανοιχτή την πύλη 8081 για να μπορέσουμε να λάβουμε τα requests. Το SSH προσφέρει την δυνατότητα να ακούμε από έξω στις πύλες που ορίζουμε με το Remote SSH Port Fowarding. Για να μπορεί να λειτουργήσει σωστά το remote fowarding, πρέπει να ανοίξουμε το αρχείο *sshd_config*:
```
sudo vim /etc/ssh/sshd_config
```
Και να κάνουμε την παρακάτω αλλαγή:
```
GatewayPorts yes
```
Τώρα θα μπορούμε να λάβουμε συνδέσεις στην πύλη 8081. Σε κάθε worker του swarm μπορουμε  να εκτελέσουμε τις εντολές:
```
curl <IP-address>:8081
```
ή
```
lynx <IP-address>:8081
```
Και τελικά με τις παραπάνω εντολές παίρνουμε το περιεχόμενο του index.html από τον Web Server μας.

TIP: Για μεγαλύτερη ασφάλεια μπορούμε να ορίσουμε GatewayPorts *clientspecified* ώστε να μπορούμε να δεχόμαστε συνδέσεις σε μια θύρα μόνο από συγκεκριμένες διευθύνσεις και βάζοντας την IP του client που θέλουμε πρίν το port στο οποίο ακούμε, για παράδειγμα *ssh -nNT -R <safe-IP>:8081:localhost:80 user@<IP-address>*.

== Δημιουργία VPN
Η δημιουργία VPN (Virtual Private Network) επιτρέπει την σύνδεση απομακρυσμένων δικτύων σε ένα εικονικό δίκτυο. Αυτό προσφέρει ασφάλεια στην επικοινωνία ανάμεσα των δυο δικτύων. Χρησιμοποιείται πολύ εκτός από την ασφάλεια από πολλούς βασικούς χρήστες για ανωνυμία και προστασία των προσωπικών τους δεδομένων. Η σύνδεση γίνεται πάνω στον VPN Server. Στο παρακάτω ζητούμενο θα αναλυθεί η δημιουργία του VPN Server πάνω στον υπολογιστή μας καθώς και πως μπορούν χρήστες που βρίσκονται σε άλλα δίκτυα, στην περίπτωση μας οι κόμβοι του swarm να συνδεθούν και να εμφανίζονται σαν μέλη του δικτύου μας.

NOTE: Τα VPN δουλεύουν με μοντέλο client-server, ο server είναι που ενώνει τα δίκτυα και από τον οποίο περνάει όλη η κίνηση από τα δίκτυα πρός τα έξω. Στο παρακάτω παράδειγμα, ο υπολογιστής μας θα είναι VPN Server και θα συνδέσουμε τον master του Swarm ως client.

=== Δημιουργία OpenVPN Server σε Docker container

Αρχικά θα δημιουργήσουμε στον υπολογιστή μας ένα αρχείο *create-vpn.sh* στο οποίο βάζουμε το παρακάτω περιεχόμενο:
```
#!/bin/bash
IP=127.0.0.1                                            # Server IP       
P=1194                                                  # Server Port     
OVPN_SERVER='10.80.0.0/16'                              # VPN Network     

#vpn_data=/var/lib/swarmlab/openvpn/openvpn-services/   # Dir to save data ** this must exist **
vpn_data=$PWD/openvpn-services/                                           
if [ ! -d $vpn_data ]; then
 mkdir -p $vpn_data
fi

NAME=swarmlab-vpn-services                              # Name of docker service 
DOCKERnetwork=swarmlab-vpn-services-network             # Docker network
docker=registry.vlabs.uniwa.gr:5080/myownvpn            # Docker image

docker stop  $NAME					      #Stop container
sleep 1
docker container rm  $NAME				#rm container

# rm config files
rm -f $vpn_data/openvpn.conf.*.bak
rm -f $vpn_data/openvpn.conf
rm -f $vpn_data/ovpn_env.sh.*.bak
rm -f $vpn_data/ovpn_env.sh

# create network
sleep 1
docker network create --attachable=true --driver=bridge --subnet=172.50.0.0/16 --gateway=172.50.0.1 $DOCKERnetwork

#run container        see ovpn_genconfig
docker run --net=none -it -v $vpn_data:/etc/openvpn  -p 1194:1194 --rm $docker ovpn_genconfig  -u udp://$IP:1194 \
-N -d -c -p "route 172.50.20.0 255.255.255.0" -e "topology subnet" -s $OVPN_SERVER   

# create pki          see ovpn_initpki
docker run --net=none -v $vpn_data:/etc/openvpn  --rm -it $docker ovpn_initpki     

#                     see ovpn_copy_server_files
#docker run --net=none -v $vpn_data:/etc/openvpn  --rm $docker ovpn_copy_server_files

#create vpn           see --cap-add=NET_ADMIN
sleep 1
docker run --detach --name $NAME -v $vpn_data:/etc/openvpn --net=$DOCKERnetwork --ip=172.50.0.2 -p $P:1194/udp --cap-add=NET_ADMIN $docker  

sudo sysctl -w net.ipv4.ip_forward=1

#show created
docker ps
```

Στο παραπάνω αρχείο δηλώνουμε, την τοπική IP του server, την port στην οποία θα ακούει, το δίκτυο VPN που δημιουργούμε. Στην συνέχεια θα δημιουργηθεί ένας φάκελος, δηλώνεται το όνομα του docker service, network και το image που θα κάνουμε pull. Στην συνέχεια θα δημιουργηθεί το δίκτυο και θα τρέξει το docker container στο οποίο μέσα σηκώνουμε τον OpenVPN server μας. Τρέχουμε το παραπάνω script με την εντολή:
```
sudo ./create-vpn.sh
```
Θα χρειαστεί να ακολουθήσουμε τις οδηγίες που θα εμφανιστούν και να εισάγουμε τους κωδικούς που θα ζητηθούν. Εάν όλα πήγαν καλά με το *docker ps* που θα τρέξει θα πρέπει να βλέπουμε το swarmlab-vpn-services container να τρέχει. Αφού δημιουργηθεί το VPN μας, χρειάζεται να δημιουργήσουμε ένα αρχείο χρήστη για να μπορεί να συνδεθεί. Δημιουργούμε το αρχείο *create-user.sh* και βάζουμε μέσα τα  παρακάτω:
```
#!/bin/bash
USERNAME=testusermaster
vpn_data=$PWD/openvpn-services/
docker=registry.vlabs.uniwa.gr:5080/myownvpn

docker run -v $vpn_data:/etc/openvpn --rm -it $docker easyrsa build-client-full $USERNAME nopass
docker run -v $vpn_data:/etc/openvpn --log-driver=none --rm $docker ovpn_getclient $USERNAME  > $USERNAME.ovpn
```
Τρέχουμε το παραπάνω script με την παρακάτω εντολή:
```
sudo ./create-user.sh
```
Το αρχείο που θα δημιουργηθεί περιέχει τα απαραίτητα κλειδιά για να μπει ο χρήστης μας στο VPN και κάποιες επιπλέον ρυθμίσεις. Προθέτουμε τις παρακάτω γραμμές στην κορυφή του αρχείου βάζοντας την IP του VPN Server μας πάνω στον οποίο θα γίνει η σύνδεση δίπλα στην πόρτα που χρησιμοποιούμε (1194).
```
client
nobind
dev tun
comp-lzo
resolv-retry infinite
keepalive 15 60

remote-cert-tls server
remote <host-IP> 1194 udp
float
```
Το αρχείο με τα παραπάνω και με τα κλειδιά που έχει μέσα θα τα χρησιμοποιήσει ο χρήστης (ο master του swarm μας) για να συνδεθεί. Αρκεί να μπούμε στον master και να εγκαταστήσουμε το openvpn με την παρακάτω εντολή:
```
sudo apt-get install openvpn
```
Αφου εγκαταστήσουμε το OpenVPN, θα εκτελέσουμε την παρακάτω εντολή με το αρχείο που δημιουργήσαμε πριν, στην περίπτωση μας το *testusermaster.ovpn* για παράμετρο ως εξής:
```
openvpn --config testusermaster.ovpn
```
Θα εμφανιστεί μήνυμα επιτυχίας εάν ο χρήστης συνδεθεί με επιτύχια και μπορούμε να ελέγξουμε αν έχει αποκτήσει IP του VPN μας μέσω *ifconfig* όπου θα πρέπει να εμφανιστεί σε μια διεπαφή διεύθυνση του δικτύου VPN μας (στην περίπτωση μας 10.80.0.0/16).

Στον VPN Server μπορούμε να δούμε τους users καθώς και τους connected clients με τις παρακάτω εντολές αντίστοιχα:
```
docker exec -it swarmlab-vpn-services ovpn_listclients
```
```
docker exec -it swarmlab-vpn-services cat /tmp/openvpn-status.log
```
Τέλος εάν θέλουμε να αφαιρέσουμε τον χρήστη από το VPN μας, δημιουργούμε αρχείο *rm-user.sh* με το παρακάτω περιεχόμενο:
```
#!/bin/bash

CLIENTNAME=testusermaster
U=$CLIENTNAME

vpn_data=$PWD/openvpn-services/
docker=registry.vlabs.uniwa.gr:5080/myownvpn

rm -f $vpn_data/pki/reqs/$CLIENTNAME.req
rm -f $vpn_data/pki/private/$CLIENTNAME.key
rm -f $vpn_data/pki/issued/$CLIENTNAME.crt
rm -f $vpn_data/server/ccd/$CLIENTNAME
rm -f $vpn_data/ccd/$CLIENTNAME
pem=$(sudo grep "CN=$U$"  $vpn_data/pki/index.txt | cut  -f4)

rm -f $vpn_data/pki/certs_by_serial/$pem.pem
sed -i "/CN=$U$/d"  $vpn_data/pki/index.txt
echo $pem
docker run -v $vpn_data:/etc/openvpn --log-driver=none --rm -it $docker ovpn_revokeclient  $CLIENTNAME remove

rm -f $vpn_data_user_config/$CLIENTNAME.ovpn
rm -f $vpn_data_user_config1/$CLIENTNAME.ovpn
```
TIP: Βάζουμε για CLIENTNAME το όνομα του χρήστη που θέλουμε να αφαιρέσουμε.

Και τέλος ο χρήστης θα αφαιρεθεί με την εκτέλεση του παραπάνω script με την παρακάτω εντολή:
```
sudo ./rm-user.sh
```
=== Στιγμιότυπα οθόνης από δημιουργία VPN στο swarm