Στο άρθρο αυτό θα δούμε πως μπορούμε να ξεκλειδώσουμε ένα κρυπτογραφημένο σύστημα αρχείων με τη βοήθεια ενός απλού USB storage. Στην περίπτωση που δεν υπάρχει συνδεμένο το USB κατά την εκκίνηση, ή το έχουμε χάσει, θα ζητηθεί ο κωδικός κανονικά.
Το σύστημα της δοκιμής τρέχει Pop OS, το οποίο χρησιμοποιείς το initramfs-tools
για τη δημιουργία του αρχικού ramdisk εκκίνησης. Αν το σύστημα σας χρησιμοποιεί το drakut
δε θα λειτουργήσει και θα πρέπει να τροποποιηθούν οι οδηγίες. Αν κάποιος το κάνει θα εκτιμούσα ένα σχόλιο με το πως το έκανε.
Για την κρυπτογράφηση των δίσκων
Διαβάστε πρώτα το κεφάλαιο “Εξερεύνηση του κρυπτογραφημένου δίσκου” στο άρθρο
όπου έχει κάποιες λίγες, αλλά χρήσιμες πληροφορίες για τους κρυπτογραφημένους δίσκους.
Πως θα είναι αποθηκευμένος ο κωδικός
Μα κάπου μέσα στο στικάκι, αλλά πως; Υπάρχουν οι εξής λύσεις
- Σαν κάποιο αρχείο μέσα στο στικάκι, η ποιο απλή λύση, αλλά μπορεί να σβηστεί το αρχείο
- Κρυμμένο μέσα στο στικάκι, έκτος συστήματος αρχείων με την εντολή
dd
στους τελευταίους sectors - Πουθενά
Δοκίμασα και τις 3 λύσεις και βρίσκω την τελευταία σαν την καλύτερη, γιατί μιας και δεν υπάρχει η πληροφορία μέσα στον δίσκο, μπορείς ακόμα και να το κάνεις format. Πώς όμως;
Σε ένα τερματικό γράφουμε (αλλάξτε το /dev/sdc
με αυτό του USB):
udevadm info -n /dev/sdc | grep ID_ | cut -f2 -d" "
Μεταξύ άλλων θα δούμε κάποια πράγματαπου μας βοηθούν να αναγνωρίσουμε την συσκευή
ID_VENDOR=USB ID_VENDOR_ENC=\x20USB\x20\x20\x20\x20 ID_VENDOR_ID=0781 ID_MODEL=SanDisk_3.2Gen1 ID_MODEL_ENC=\x20SanDisk\x203.2Gen1 ID_MODEL_ID=5583 ID_REVISION=1.00 ID_SERIAL=USB_SanDisk_3.2Gen1_04013df......... ID_SERIAL_SHORT=04013dfec44a56d6b825....... ID_USB_DRIVER=usb-storage ID_PATH=pci-0000:02:00.0-usb-0:3:1.0-scsi-0:0:0:0 ID_PART_TABLE_TYPE=dos
Στο δικό μου υπάρχει ένα εξαιρετικά μεγάλο ID_SERIAL
κάτι που το καθιστά ένα ιδανικό υποψήφιο για κλειδί. Αλλά παλιά η φτηνά στικάκια δεν έχουν τόσο μεγάλο αριθμό ή δεν έχουν καθόλου. Σε αυτή την περίπτωση πάμε με τη μέθοδο του αρχείου στον δίσκο, είτε αγοράζουμε κάποιο επώνυμο. Το στικάκι είναι πλήρως λειτουργικό οπότε δεν είναι σπατάλη χρημάτων και είναι πραγματικά φτηνά στις μέρες μας. Αν κάποιος δε θέλει αυτή τη λύση, ας γράψει στα σχόλια μια αίτηση για τη μέθοδο με το αρχείο στον δίσκο.
Αν πάει κάτι στραβά
Στη διαδικασία που ακολουθεί θα τροποποιήσουμε το initramdisk
. Και πιστέψτε με πολλά μπορούν να πάνε στραβά. Οπότε καλό είναι να κάνουμε πρώτα ένα αντίγραφο του αρχικού, ώστε πειράζοντας στον grub
ή στο systemd-boot
το command line, να μπορούμε να συνδεθούμε:
sudo cp /boot/initrd.img-$(uname -r) /boot/initrd.img-$(uname -r)-old
Θα πρέπει να ξέρεις πως να αλλάξεις τις παραμέτρους απο το
grub
ή τοsystemd-boot
. Στο τελευταίο στο μενού πατάς e. Αλλάζεις το initrd με το αντίγραφο.
Βήμα 1: Αυτόματη αποκρυπτογράφηση
Θα φτιάξομε ένα αρχείο sh
με όνομα crypt-usb-from-serial
και θα το μεταφέρουμε στον κατάλογο /usr/local/bin
ή όπου αλλού θέλουμε. Θα περιέχει τα παρακάτω:
#!/bin/sh
# Replace with your usb parameters. Find yours with:
# udevadm info -n /dev/... | grep ID_ | cut -f2 -d" "
ID_VENDOR_ENC="\x20USB\x20\x20\x20\x20"
ID_MODEL_ENC="\x20SanDisk\x203.2Gen1"
ID_VENDOR_ID="0781"
ID_MODEL_ID="5583"
## Number of tries, allow at least 2 for password fallback
NUM_TRIES=3
if test ! "$CRYPTTAB_TRIED" = $NUM_TRIES
then
temp_file=$(mktemp)
all_disks=$(lsblk -l -o PATH,TYPE | grep disk | cut -f1 -d" ")
for disk in $all_disks; do
udevadm info -n "$disk" | grep ID_ | cut -f2 -d" " > "$temp_file"
vendor="$(grep 'ID_VENDOR_ENC=' < "$temp_file" | cut -f2 -d'=')"
model="$(grep 'ID_MODEL_ENC=' < "$temp_file" | cut -f2 -d'=')"
vendor_id="$(grep 'ID_VENDOR_ID=' < "$temp_file" | cut -f2 -d'=')"
model_id="$(grep 'ID_MODEL_ID=' < "$temp_file" | cut -f2 -d'=')"
vendor_id="$(grep ID_VENDOR_ID < "$temp_file" | cut -f2 -d'=')"
if test "$vendor" = $ID_VENDOR_ENC -a "$model" = $ID_MODEL_ENC ; then
if test "$vendor_id" = $ID_VENDOR_ID -a "$model_id" = $ID_MODEL_ID ; then
unlock_key="$(grep 'ID_SERIAL=' < "$temp_file" | cut -f2 -d'=')"
# Pass password to unlock
echo "$unlock_key"
fi
fi
done
else
/lib/cryptsetup/askpass "Please enter passphrase: "
fi
Αν θέλεις να το προσαρμόσεις μερικές παρατηρήσεις: Σκοπός του είναι να γράψεις στην έξοδο τον κωδικό. Στην ποιο απλή του μορφή θα μπορούσε να είναι ένα απλό echo sectret
. Οπότε δεν μπορείς να το κάνεις debug με εντολές echo.
Δεν είναι ένα αρχείο BASH! Θα τρέξει στο busybox
που έχει μια πολύ πιο απλή γλώσσα. Εναλλακτικά θα μπορούσαμε να το κάνουμε bash και να προσθέσουμε το ίδιο το bash στο initrd. Διάλεξα τον δύσκολο δρόμο, και τις ελάχιστες δυνατές εξαρτήσεις, για να το κρατήσω όσο μικρότερο είναι δυνατόν.
Κατά την εκκίνηση θα γίνει προσπάθεια για ξεκλείδωμα κάμποσες φορές. Θα δούμε πως αλλάζουμε αυτό το νούμερο παρακάτω. Θα κάνει μια προσπάθεια να το ξεκλειδώσει NUM_TRIES=3
φορές. Αλλιώς θα δοκιμάσει να ζητήσει τον κωδικό από τον χρήστη. Οπότε είναι σημαντικό να του αφήσεις επιπλέον προσπάθειες. Εναλλακτικά βέβαια μπορείς πάντα να απαιτείς πάντα το στικάκι.
Γιατί θέλει να δοκιμάσει πολλές φορές; Γιατί ο υπολογιστής ξεκινά και μπορεί το στικάκι να μην είναι έτοιμο.
Τέλος, είναι απαραίτητο να του κάνεις chmod +x
.
Η ώρα της αλήθειας. Το τρέχουμε και πρέπει να δούμε τον κωδικό. Αν τον δούμε προχωράμε. Μπορεί όμως να μη δουλεύει μέσα στο initrd. Σε αυτή την περίπτωση μια χρήσιμη παράμετρος στην εκκίνηση είναι η break=premount
.
Βήμα 2: Ενημέρωση του /etc/crypttab
Τώρα θα πρέπει να πούμε στο σύστημα να χρησιμοποιεί αυτό το αρχείο. Θα το κάνουμε στο αρχείο /etc/crypttab
. Θα τροποποιήσουμε τη σχετική γραμμή να γράφει:
cryptdata UUID=3aa... none luks,...,keyscript=/usr/local/bin/crypt-usb-from-serial,tries=6
Προσέξτε έδωσα 6 ευκαιρίες να ξεκλειδώσει ο δίσκος. Οι 3 θα δοκιμαστούν με το κλειδί. Μετά έχω 3 ευκαιρίες να μαντέψω σωστά τον κωδικό.
Βήμα 3: Εξαγωγή του κλειδιού και ορισμός του ως κλειδί αποκρυπτογράφησης
Μέχρι τώρα δεν μπορεί να ξεκλειδώσει, για τον απλούστατο λόγο ότι ο κρυπτογραφημένος δίσκος δε γνωρίζει για το κλειδί. Θα το προσθέσουμε επαναχρησιμοποιώντας το σκριπτάκι που φτιάξαμε. Έτσι είμαστε βέβαιοι πως είναι ο ίδιος κωδικός.
Σε ένα τερματικό:
./crypt-usb-from-serial | tee sectret.txt
και προσθέτουμε τον σειριακό αριθμό σαν κλειδί αποκρυπτογράφησης
cryptsetup luksAddKey /dev/... sectret.txt
θα πρέπει να δώσουμε ένα υπάρχων κλειδί αποκρυπτογράφησης.
Αντικαταστήστε το /dev/..
με την κρυπτογραφημένη κατάτμηση στο σύστημα σας. Δεν είναι ανάγκη να μπούμε σε κάποιο live περιβάλλον.
Μπορούμε να σβήσουμε τώρα το αρχείο sectret.txt
.
Βήμα 4: Προσθήκη στο inirtrd
Δεν τελειώσαμε ακόμα. Το ξεκλείδωμα του δίσκου θα γίνει στο initrd και μετά θα ξεκινήσει το λειτουργικό.
To initrd περιέχει ένα ελάχιστο σύστημα αρχείων με τα απαραίτητα για να φορτωθούν ότι οδηγοί χρειάζονται για να δει το σύστημα τους δίσκους και τα συστήματα αρχείων καθώς και να κάνει το όποιο ξεκλείδωμα στους δίσκους και γενικά οτι προετιμασία χρειάζετε για να ξεκινήσει το λειτουργικό απο τον δίσκο (ή απο κάπου αλλού σε υπολογιστές χωρίς δίσκους).
Θα πρέπει λοιπόν να μεταφέρουμε το σκριπτάκι κάναμε στο initrd
. Επίσης να βεβαιωθούμε πως υπάρχει και ότι άλλο χρησιμοποιεί.
Για να καταλάβουεμ καλύτερα το initrd
, ας δούμε πρώτα τι περιέχει:
lsinitramfs /boot/initrd.img-$(uname -r) | less
Θα πρέπει να σημειώσουμε τι χρησιμοποιεί το crypt-usb-from-serial
όπως τις εντολές cut
, grep
, lsblk
, udevadm
κλπ… και να βεβαιωθύμε πως υπάρχουν μέσα.
Στο δικό μου σύστημα δεν υπάρχει ή lsblk
και βέβαια σε όλα τα συστήματα δεν περιμένουμε να βρούμε το /usr/local/bin/crypt-usb-from-serial
.
Θα φτιάξουμε ένα αρχείο /etc/initramfs-tools/hooks/crypt-hook-usb
που θα περιέχει τα παρακάτω:
#!/bin/sh
# /etc/initramfs-tools/hooks/crypt-hook-usb
PREREQ=""
prereqs() {
echo "$PREREQ"
}
case "$1" in
prereqs)
prereqs
exit 0
;;
esac
. "${CONFDIR}/initramfs.conf"
. /usr/share/initramfs-tools/hook-functions
## Change from here
manual_add_modules usb_storage
copy_exec /usr/bin/lsblk /usr/bin/lsblk
copy_exec /usr/local/bin/crypt-usb-from-serial /usr/local/bin/crypt-usb-from-serial
Στο αρχείο αυτό προσθέτουμε ότι επιπλέον θέλουμε να προστεθεί στο initrd
. Έβαλα ένα επιπλέον module στον πυρήνα, έχει μείνει από παλιά προσπάθεια, αλλά το κράτησα να δείξω πως γίνετε.
Το βασικό το κάνουν οι γραμμές copy_exec
που αντιγράφουν ένα εκτελέσιμο (μαζί με τις εξαρτήσεις του) από τον δίσκο στη ramdisk. Το αρχείο θα πρέπει να είναι εκτελέσιμο, οπότε φροντίστε να του έχετε κάνει πριν chmod +x
.
Βήμα 5: Δημιουργία του Ramdisk
Επιτέλους ήρθε η ώρα να φτιάξουμε αυτήν τη ramdisk και να κάνουμε επανεκκίνησή και έλεγχο
sudo update-initramfs -k all -u
Εύχομαι όλα να πήγαν καλά
Επόμενα βήματα
Γιατί να μείνουμε μόνο εκεί; Μπορούμε να επαναχρησιμοποιήσουμε το ίδιο κλειδί για να μη δίνουμε ποτέ τον κωδικό μας.
Διαβάστε πως εδώ:
Σημειώσεις για την ασφάλεια
Η μέθοδος είναι ασφαλής. Πουθενά δεν υπάρχει γραμμένος ο κωδικός αποκρυπτογράφησης στον δίσκο. Αλλά κρατήστε μυστική την ύπαρξη του κλειδιού. Στην τελική είναι ένα αθώο στικάκι με αρχεία είναι, όπως τόσα και τόσα άλλα .
Αλλά οποιοσδήποτε που γνωρίζει το μυστικό μπορεί να αφαιρέσει το στικάκι και να κλέψει τον κωδικό. Και μπορεί εύκολα και φτηνά να φτιάξει μια USB συσκευή που να έχει τα ίδια στοιχεία. Δεν έχει μεγάλη διαφορά απο το να «δανειστεί» κάποιος τα κλειδίας σας και να πάει σε ένα κλειδαρά να βγάλει αντίγραφα.
Θα μπορούσε βέβαια κανείς να «αλατίσει» τον κωδικό – το αφήνω σαν άσκηση για όποιον θέλει να το κάνει στα σχόλια – για μεγαλύτερη ασφάλεια. Αλλά έχει νόημα; το αλάτι θα πρεπει να υπάρχει μέσα στο initrd
το οποίο είναι ένα απλό αρχείο cpio
χωρίς κρυπτογράφηση.
ΥΓ: Το άρθρο αυτό έχει γραφτεί με πολλά δάκρυα, πόνο