Headless instalace Ubuntu serveru
Dnes se podíváme na to jak nainstalovat linux na stroj, ke kterému není k dispozici ani klávesnice, ani monitor. Aby to nebylo tak jednoduché, tak to všechno bude nainstalováno do šifrovaného kontejneru, ke kterému se po rebootu zadává heslo přes SSH.
Motivace
Jak říkával můj oblíbený učitel na střední škole: „Doba je zlá, ne-li kritická“. NSA šmíruje kde se dá, ale i ostatní orgány se už pomalu začínají orientovat ve světě informačních technologií. Podniková špionáž, všeobecná paranoia. Přesto skoro kamkoliv přijdu, tak stačí nabootovat live distribuci Linuxu a během pár minut si můžu dělat s nainstalovaným systémem co chci - přidávat tam soubory, mazat a upravovat stávající, či si kopírovat citlivá data. Proto tedy šifrovaný disk.

Nevím kde máte server vy, já mám jeden pod dřezem a druhý kdesi v cloudu u poskytovatele. Oboje dvoje je relativně špatně dostupné - pod dřezem je nedostatek zásuvek a přenášet server či monitory se mi nechtělo. Do cloudu mě pro změnu nikdo fyzicky nepustí. Proto tedy headless instalace.
early-ssh
Na internetu se dá najít odkaz na balíček early-ssh
, který údajně dělá více/méně všechno zde popsané, co se dropbear
u týče (headless instalaci vám nevyrobí).
Pokud na něj narazíte, rozhodně ho nepoužívejte! Jedná se o neudržovaný a velmi rozbitý script, který nejenže nefunguje, ale má tendence navíc rozbít i některé potenciálně obtížně opravitelné věci (initramfs
).
Shrnutí postupu
Vše níže popsáno bylo odzkoušeno v systému Linux Mint založeném na Ubuntu, se standardní softwarovou výbavou.
1. Stažení současného serverového 64b instalátoru Ubuntu 14.04, což je LTS (Long Time Support) verze s dlouhodobou podporou. Ubuntu používám protože je uživatelsky příjemné a je pro něj dostupno asi nejvíc balíčků software. Také je to relativně jednoduchá a blbuvzdorná distribuce, se kterou mám na serveru dost zkušeností.
2. Rozbalení staženého ISO souboru na disk, přidání preseed souboru a několika dalších scriptů. Tento krok zajistí, že instalátor nebude vyžadovat interaktivní přítomnost uživatele na vstupně výstupních zařízeních serveru (monitor, klávesnice). Místo toho bude spuštěno SSH
s textovým dialogovým menu, přes které je možné dále postupovat v instalaci.
3. Vytvoření nového ISO souboru z modifikovaných komponent.
4. Instalace systému na disk. V tomto kroku nainstaluji Ubuntu na disk. Na konci se spustí preseed konfigurace, která zajistí instalaci dropbearu (miniaturní SSH server) a jeho přidání do initramfs
, aby startoval během žádosti o zadání hesla k disku. Dále je zde upravení grubu aby přeskakoval interaktivní menu, nastavení portu pro dropbear
a tak dále.
5. Zadání hesla pro šifrovaný disk. Celá procedura není tak jednoduchá a uživatelsky přívětivá, jak by mohla, proto je jí věnován větší prostor.
Upozornění
V průběhu článku budeme konfigurovat tři různé SSH servery/sessiony:
- Preseed netinstall konzole. Tímto se připojujeme na proces instalace.
- Dropbear SSH server, který slouží k zadání hesla k šifrovanému disku. Používáme certifikát (heslo se nejspíš ani nedá použít, zkoušel jsem, ale nepochodil).
- OpenSSH server, který běží po bootu a odemčení disku na serveru.
Postup úprav
Instalační médium
Začněme stažením instalačního média. Celý postup mám odzkoušený na 64b verzi a je možné, že některé detaily, hlavně co se týče preseed souboru a cest, které jsou v něm specifikované, mohou být odlišné.
wget -c http://releases.ubuntu.com/trusty/ubuntu-14.04.1-server-amd64.iso
Dále je dobré se ujistit, že máte nainstalovaný program mkisofs, který je použit k opětovnému sestavení ISO souboru po jeho rozbalení:
sudo aptitude install mkisofs
Upravení instalace
Ze všeho nejdříve si vytvořím dva adresáře a přepnu se na root
a, abych nemusel neustále opisovat sudo
:
mkdir ubuntu_iso
mkdir headless_ubuntu
sudo su
Nyní je na čase si vybalit obsah ISO souboru do samostatného adresáře, aby bylo možné provést všechny nutné úpravy.
mount -o loop ubuntu-14.04.1-server-amd64.iso ubuntu_iso/
cp -rT ubuntu_iso/ headless_ubuntu/
umount ubuntu_iso
rm -r ubuntu_iso
cd headless_ubuntu/
authorized_keys
Naprostou nutností je přidat soubor preseed/authorized_keys
, který je použit dropbear
em pro zpřístupnění konzole, kam zadáváte heslo k disku. Do tohoto souboru nakopírujte váš veřejný klíč, který většinou najdete v ~/.ssh/id_dsa.pub
.
Zkopírovat ho můžete například tímto příkazem:
cat ~/.ssh/id_dsa.pub >> preseed/authorized_keys
Upozornění: Pokud tento soubor nebude vytvořen, nebude možné ani vzdáleně odemknout šifrovaný disk. Zkoušel jsem si hrát s nastavením dropbear
u a donutit ho používat heslo, ale bezúspěšně.
Poznámka: Pokud nemáte soubor ~/.ssh/id_dsa.pub
, je možné, že je uložen jinde, nebo že ještě nebyl vygenerován. Jak na to zjistíte například zde: Jak se přihlašovat na SSH
bez zadávání hesla.
isolinux.cfg
Dále je zapotřebí upravit jeden soubor a vytvořit další dva. Začněme úpravou souboru isolinux/isolinux.cfg
, který je možné celý přepsat, proto jsem vše shrnul do jednoho příkazu, jenž stačí zkopírovat do konzole:
cat > isolinux/isolinux.cfg <<EOF
F9 f9.txt
F0 f10.txt
prompt 0
timeout 0
DEFAULT netconsole
LABEL netconsole
kernel /install/vmlinuz
append auto=true vga=normal file=/cdrom/preseed/preseed.seed initrd=/install/initrd.gz locale=cs_CZ console-keymaps-at/keymap=cz-lat2
EOF
unlock.sh
Hodit se nám bude také soubor preseed/unlock.sh
, který slouží k odemčení šifrovaného disku. Není toho zde moc k vidění a tak jsem opět soubor upravil do tvaru, který je možné jednoduše vložit do terminálu a vytvořit ho tak automaticky:
cat > preseed/unlock.sh <<EOF
#!/bin/sh
kill -9 `ps | grep "/bin/sh" | grep cryptroot | cut -d " " -f 3`
echo "Please wait, this will take some time (35s).."
sleep 35
/scripts/local-top/cryptroot
kill -9 `ps | grep "/bin/sh" | grep -v grep | cut -d " " -f 3`
EOF
preseed.seed
Nyní přichází na řadu první část instalace, kde je zapotřebí dávat důkladný pozor na to co děláte. Vytvořte soubor preseed/preseed.seed
(doporučuji použít editor, protože pravděpodobně budete chtít změnit některé detaily) s následujícím obsahem:
d-i debian-installer/locale string cs_CZ
# Podstatné je hlavně NEWMACHINE, neboť bude nastaveno jako hostname nového stroje
d-i debconf/priority select critical
d-i auto-install/enabled boolean true
d-i netcfg/choose_interface select auto
d-i netcfg/get_hostname string NEWMACHINE
# Instalace potřebných balíčků pro připojení po SSH
d-i preseed/early_command string anna-install network-console
d-i pkgsel/include string openssh-server build-essential
d-i anna/choose_modules string network-console
# Nastavení hesla uživatele SSH sessiony
d-i network-console/password password r00tme
d-i network-console/password-again password r00tme
# Pokud dáváte přednost ručnímu nastavení sítě:
#d-i netcfg/disable_dhcp boolean true
# Defaultně je použito DHCP. Pokud chcete použít statické nastavení,
# odkomentujte řádky dole.
#d-i netcfg/dhcp_failed note
#d-i netcfg/dhcp_options select Configure network manually
#d-i netcfg/get_nameservers string 10.0.0.1
#d-i netcfg/get_ipaddress string 10.0.0.20
#d-i netcfg/get_netmask string 255.255.255.0
#d-i netcfg/get_gateway string 10.0.0.1
#d-i netcfg/confirm_static boolean true
# Postinstall příkazy - in-target se provedou v systému
d-i preseed/late_command string \
in-target aptitude update ; \
in-target aptitude -y install dropbear busybox libnss3 ; \
in-target sed 's/^\/sbin\/dropbear.*/\/sbin\/dropbear -p 80/g' -i /usr/share/initramfs-tools/scripts/init-premount/dropbear ; \
cp cdrom/preseed/authorized_keys target/etc/initramfs-tools/root/.ssh/authorized_keys; \
cp cdrom/preseed/unlock.sh target/etc/initramfs-tools/root/unlock.sh; \
in-target chmod +x /etc/initramfs-tools/root/unlock.sh ; \
in-target bash -c "echo 'cp /etc/initramfs-tools/root/unlock.sh \"\${DESTDIR}/bin/\"' >> /usr/share/initramfs-tools/hooks/dropbear" ; \
in-target bash -c "echo 'GRUB_RECORDFAIL_TIMEOUT=3' >> /etc/default/grub" ; \
in-target update-initramfs -u -k all ; \
in-target update-grub
Tento soubor je automaticky načten instalátorem, který si z něj vyzobe informace potřebné pro automatické spuštění netinstall konzole. Všímavější čtenáři se mohou podívat do adresáře preseed/
, kde je již několik scriptů k dispozici.
Předpokládám, že budete chtít provést některé úpravy, proto jsem zvýraznil několik řádků:
Řádek 7
Zde je možné změnit hostname počítače. Instalátor si ho pamatuje a automaticky ho nastaví pro nainstalovaný systém. Dá se to změnit i později, ale je to otrava.
Řádek 9
Heslo, pod kterým se připojíte do instalátoru.
Řádek 10
Heslo ještě jednou.
Řádky 23 až 29
Statické nastavení sítě. Tyto řádky je odkomentujte pokud chcete aby instalátor použil uvedené IP adresy a konfiguraci sítě. Pokud zůstanou tyto řádky zakomentované, tak je použito dhcp
a může být složité zjistit adresu instalátoru (hlavně v případě VPS).
Řádek 35
Tento řádek obsahuje příkaz, který poněkud barbarským způsobem donutí SSH
server dropbear
startovat na portu 80
, místo standardního 22
.
Toto chování je zvoleno z prostého důvodu; dropbear
spuštěný při zadávání hesla k disku používá (a měl by používat!) jiné klíče než OpenSSH
, který je spuštěn později. To ovšem vede ke konfliktu fingerprintu, který je uložený ve vašem ~/.ssh/known_hosts
, a SSH
klient se odmítne připojit, dokud zadaný fingerprint neodstraníte.
Tuto procedůru by bylo nutné provádět po každém restartu serveru, proto byl zvolen alternativní port, u kterého je navíc jistá jeho dostupnost i skrz některé nepříliš přátelské firewally.
Pokud vám toto chování nevyhovuje, můžete řádek číslo 35 smazat (v tom případe je použit port 22
), či zvolené číslo portu nahradit.
Pozor: jedná pouze o port pro zadání hesla k šifrovanému disku, ne o port, kde bude naslouchat OpenSSH
, jakmile je heslo úspěšně zadáno a systém nabootuje!
Bonus
Jak je možné pochopit z komentáře na řádku 31, veškeré následující příkazy se provedou, jakmile bude instalace dokončena. Řádky začínající na in-target
jsou provedeny v chrootu, ostatní z cesty instalátoru. Pokud si vyberete druhou možnost, obsah ISO souboru je dostupný v adresáři cdrom/
, nainstalovaný systém pak v target/
.
Jestliže chcete provést nějaké změny v nainstalovaném systému ještě v době instalace, je možné přidat další řádky, které například nastaví statickou IP adresu (doporučuji použít postup na řádku 36, tedy uložit soubory na ISO do adresáře preseed/
a pak je prostě zkopírovat stylem cp cdrom/preseed/soubor target/etc/soubor; \
), či podobné konfigurace.
Následující ukázka nastaví OpenSSH
(nikoliv dropbear
!) aby zamezil loginu root
a:
in-target sed 's/^PermitRootLogin.*/PermitRootLogin no/g' -i /etc/ssh/sshd_config; \
Dále je možné také změnit port pro OpenSSH
například na můj oblíbený 443
:
in-target sed 's/^Port.*/Port 443/g' -i /etc/ssh/sshd_config; \
Příkazy můžete zamíchat někam mezi ostatní, či přidat na konec. V takovém případě si ale musíte dát pozor, aby všechny mezi prvním a posledním končily sekvencí ; \
a poslední řádek byl bez nich.
IP adresa dropbearu
Poměrně užitečnou možností je například úprava IP adresy, na které se startuje dropbear
. Ta je v defaultu vybrána automaticky a ovlivnit jí je možné úpravou souboru /etc/initramfs-tools/conf.d/network_config
, kam lze přidat řádek ve formátu:
export IP=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>.
K tomu je možné použít například následující snippet:
in-target bash -c "echo 'export IP=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>' >> /etc/initramfs-tools/conf.d/network_config" ; \
Konkrétně tedy třeba:
in-target bash -c "echo 'export IP=10.0.0.2::10.0.0.1:255.255.255.0:myserver:eth0' >> /etc/initramfs-tools/conf.d/network_config" ; \
Snippet přidejte před řádek 41, kde probíhá update initramfs
.
Poznámka: Styl 'bash -c "echo ..'
je použit záměrně. Nemám dobrou zkušenost s přesměrováním pomocí >>
použitými v preseed souboru. Možná by se to dalo nějak vyescapovat, ale případné testování je docela pomalé, protože jestli to fungovalo se dozvíte vždy až na konci instalace a po dvanácti pokusech už nemám moc náladu na experimentování.
Vytvoření ISO souboru
Jakmile máme všechny úpravy hotové, o vytvoření nového instalačního média se postará tento dlouhý příkaz:
cd ..
mkisofs -r -V "Ubuntu headless" -cache-inodes -J -l -b isolinux/isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -o headless_ubuntu-14.04.1-server-amd64.iso headless_ubuntu/
Výsledkem by měl být přibližně 600MB velký soubor soubor headless_ubuntu-14.04.1-server-amd64.iso
.
Instalace
Instalace serveru probíhá poměrně standardním způsobem a každý kdo někdy instaloval ubuntu na server by to měl zvládnout.
Osobně jsem si zvolil expert mode, jednoduše jsem se proklikal všemi nastaveními a počkal, dokud se vše neprovede. Nezapomeňte hlavně zvolit že chcete šifrovaný disk, nikoliv šifrovanou jen home adresář uživatele!
Pokud by někoho zajímaly detaily, zde je šestnáctiminutová videoukázka celého postupu:
Odemčení disku přes SSH
Odemčení provedete tak, že se připojíte přes SSH
jako root
na port zadaný při instalaci. Pokud jste nedělali změny v preseed souboru, tak by to měl být port 80
. Automaticky by se vám měl načíst busybox shell, neboť při vytváření instalačního média byl přidán váš veřejný klíč. Zde stačí spustit script unlock.sh
, chvíli počkat, zadat heslo a to je vše. Tedy skoro.
$ ssh root@192.168.1.114 -p 80
BusyBox v1.21.1 (Ubuntu 1:1.21.0-1ubuntu1) built-in shell (ash)
Enter 'help' for a list of built-in commands.
# unlock.sh
Please wait, this will take some time (35s)..
/scripts/local-top/cryptroot: line 1: modprobe: not found
Unlocking the disk /dev/disk/by-uuid/1ffe6c90-d053-4c49-9225-137e6e21a491 (sda5_crypt)
Enter passphrase:
Reading all physical volumes. This may take a while...
Found volume group "NEWMACHINE-vg" using metadata type lvm2
2 logical volume(s) in volume group "NEWMACHINE-vg" now active
cryptsetup: sda5_crypt set up successfully
Killed
# kill: can't kill pid 274: No such process
kill: can't kill pid 278: No such process
Jak je možné vidět, celý proces generuje podstatně víc textu, než je očekávané a občas se stane, že celý proces odemykání zamrzne na nějaké podivné hlášce. Potom je zapotřebí vše zopakovat, či provést restart, což zatím vždy zabralo.
Pokud se podíváte do scriptu /bin/unlock.sh
, zjistíte, že je to docela bastl, který prvně zabije proces čekající na interaktivní konzoli. Z nějakého důvodu to trvá přibližně 30 vteřin, než se proces ukončí. Poté je zadáno heslo pro šifrovaný disk přes program cryptroot
a následně je opět zabit proces na interaktivní konzoli.
#!/bin/sh
kill -9 `ps | grep "/bin/sh" | grep cryptroot | cut -d " " -f 3`
echo "Please wait, this will take some time (35s).."
sleep 35
/scripts/local-top/cryptroot
kill -9 `ps | grep "/bin/sh" | grep -v grep | cut -d " " -f 3`
Poznámka: Zkoušel jsem přijít na to, jak to udělat bez zabíjení procesu, ale nepodařilo se mi. Na internetu se dá najít starší verze celého postupu, kde je heslo zadáno do jakési pojmenované roury, což nyní nefunguje, neboť roura již není kde by měla být.
Pokud by někdo stále tápal, zde je videoukázka:
Zdroje
Přijít na celý postup a hlavně ho otestovat mi zabralo cca třináct hodin čistého času na dva zátahy. Během té doby jsem prošel nemalé množství zdrojů na tohle téma. Většina z nich je buď neaktuální, nekompletní, nebo blbě, ale přesto si myslím, že stojí za zmínku: