Chápu, že Marek teď nemá už moc rád Apple, hlavně po tom, co ho poslední problémy natolik vypekly, že z toho byl ještě několik měsíců nešťastný. Kdybych mu ukázal, že mám nějaké potíže, asi by se to zvrhlo zase v hate, že nic nefunguje. Ale ono je potřeba pochopit, že jen nízké desetiny procent procent chyb jsou od výrobce a zbytek zkrátka leží a (ne)běží v samotném používání.
Je cool, pokud můžeme mít svépomocí v nějakých home-lab prostředích skutečně enterprise zabezpečení a zkoušet na tom všechno, co je potřeba, ale prostě nikdy to nebude jako 1:1 v korporátu. Ze samotného RADIUS ověřování pomocí Samba řadičů se postupně stává evergreen jako tomu bylo dřív u Stroje času s kapsami, a to doslova. Mít více DC je výborný nápad pro zajištění funkcionality, pokud něco selže, a ve stejném duchu jsem tu chtěl mít postavený failover i pro samotný RADIUS. Myšlenka dobrá, ale zase nás tam vypekla poměrně komplikovaná PKI věc.
Nuže. Před nějakou dobou jsem tu povídal o tom, jak je komplikovaná specifikace pro certifikáty, jejich platnost a důvěru v iOS – ono s iOS14 to začalo být ještě složitější a s iOS15+ se už teprve pohybujeme ve stratosférách vědomí, kde je jaksi až skoro nemožné hledat chyby související přímo s infrastrukturou v certifikátech. Hned na začátek by se slušelo říct, že PKI provozovatelů se opírá o spoustu lidí a spoustu specializovaných jednotek, kterým zkrátka jen pošlou svoje CSR a zbytek se nějak vytvoří sám. V domácím prostředí je tohle trochu pekelné a možná bude dávat smysl mít pro každou část sítě vlastní kořenovou CA bez superglobálního CA.
Jak to celé vlastně začalo? Síť fungovala krásně, pohoda jahoda, wifi frčí a všechny ty notifikace ukazují, co ani nechceme vědět. A pak, jednoho dne, bum – přišlo konečně přerušení. Připojení není k dispozici, začal vyprávět žlutě iOS u jména bezdrátové sítě. Když se to celé odpojilo, nebo dalo na letadýlko a připojilo znovu, zas to běželo. Asi bubák, jenže se to začalo nějak nehezky často opakovat. Uběhlo několik bezesných odpolední, protože většinou za tohle může DNS, kdy si iOS nemůže ověřit vlastnosti připojení a jestli je to captive portal, nebo jakýho čerta. Jenže nic nepomohlo. Nic. Ani kdy křičet. Natož ze zlata.
V dnešní době máme roboty, autonomní agenty... kdo má tu sílu dát jim SSH klíče a přístup na roota? Někdy se to musí prostě risknout. Trvalo to zas celé odpoledne, ale pak se ukázala konečně celá záhada. Protože Turris využíval failover a přehazoval klienty z jedné instance na druhou, jak mu to zrovna přišlo cool, provádělo se ověřování různými certifikáty (i když podepsanými stejnou CA), které neměly nic společného. Koho by to napadlo. Od iOS14+ je potřeba v rámci striktního RFC 2818 používat Subject Alternative Name pro sdílený logický název, docela stejně jako se to dělá v případě celé domény. A tam to už trochu naráží v domácím prostředí, pokud běží autorita na stejném stroji, resp. na jednom (nebo jako kopie na obou) NAS. Hmm.
V první řadě bylo teda potřeba udělat něco přímo s generováním certifikátů. Když se použije nějaké easyRSA, nebo jak tomu říkají, tak v té kostře stačí upravit základní konfiguraci tak, aby poskytovala SAN (ideálně jako DNS.1) pro logický hostname a hlavně aby se všechna tato rozšíření posílala do budoucích CSR.
[ CA_default ] dir = ./ certificate = $dir/ca.pem private_key = $dir/ca.key # ...standardní pole... preserve = no copy_extensions = copy # bez toho SAN ze CSR do certifikátu nepřejde policy = policy_match [ req ] prompt = no distinguished_name = server default_bits = 2048 input_password = heslo_ca_klice output_password = heslo_server_klice req_extensions = v3_req # extensions jdou do CSR [server] countryName = CZ stateOrProvinceName = Czech Republic organizationName = Eida.cz EXAMPLE commonName = "Eida.cz RADIUS Server" emailAddress = example@eida.lan [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names # SAN sekce [alt_names] # sdílený logický hostname — stejný text v TLSTrustedServerNames v mobileconfig DNS.1 = radius.eida.lan # volitelně – specifický hostname tohoto serveru DNS.2 = dc1.eida.lan
Refresh skript pak sice může žít dál na serveru, ale v tuhle chvíli potřebujeme, aby už nikdy nesahal na CA. Ta má typickou životnost 10 let, na to stačí udělat nějaký číhač a zapomenout. Vytvoření pro první i druhý server se pak dá přenášet, nebo dělat na více místech, ale výsledek by měl být vždy stejný.
#!/bin/bash
# /etc/freeradius/3.0/certs/refresh.sh
# obnova server certifikátu — CA se NIKDY neregeneruje
set -e
cd /etc/freeradius/3.0/certs/
# sanity check — ověř, že CA existuje a je platná
openssl x509 -in ca.pem -noout -fingerprint -sha1 || {
echo "CHYBA: ca.pem chybí nebo je poškozená. Abort." >&2
exit 1
}
# záloha stávajícího certifikátu
cp -f server.pem "server.pem.bak-$(date +%Y%m%d-%H%M%S)" 2>/dev/null || true
# smaž POUZE serverové soubory — ca.key a ca.pem se NEDOTÝKÁME
rm -f server.key server.csr server.crt server.pem server.p12
rm -f index.txt index.txt.attr index.txt.old serial serial.old [0-9]*.pem
echo "01" > serial
touch index.txt
echo "unique_subject = yes" > index.txt.attr
# 1) nový klíč + CSR (SAN pochází ze server.cnf [alt_names])
openssl req -new \
-out server.csr \
-keyout server.key \
-config ./server.cnf \
-passin pass:heslo_ca_klice \
-passout pass:heslo_server_klice
chmod 640 server.key
# 2) podpis CA (copy_extensions=copy zajistí přenos SAN z CSR)
openssl ca -batch \
-keyfile ca.key \
-cert ca.pem \
-in server.csr \
-key heslo_ca_klice \
-out server.crt \
-extensions xpserver_ext \
-extfile xpextensions \
-config ./server.cnf
# ověření SAN v podepsaném certifikátu
echo "=== SAN v novém certifikátu ==="
openssl x509 -in server.crt -noout -text | grep -A3 "Subject Alt" || true
openssl x509 -in server.crt -noout -fingerprint -sha256
# 3) konverze na PEM (formát, který FreeRADIUS čte)
openssl pkcs12 -export \
-in server.crt -inkey server.key -out server.p12 \
-passin pass:heslo_server_klice -passout pass:heslo_server_klice
openssl pkcs12 -in server.p12 -out server.pem \
-passin pass:heslo_server_klice -passout pass:heslo_server_klice
chmod 640 server.pem server.p12
# ověření řetězce
openssl verify -CAfile ca.pem server.pem
# 4) deploy
cp server.key /etc/ssl/radius/server.key
cp server.pem /etc/ssl/radius/server.pem
chown -R root:freerad /etc/ssl/radius/
# 5) smaž TLS session cache (starý session reuse by nabídl certifikát před renewalem)
rm -rf /var/log/freeradius/tlscache/*
systemctl restart freeradius
systemctl is-active freeradius && echo "=== FreeRADIUS OK ===" Pak je vhodná ještě kosmetická úprava samotného EAP modulu pro FreeRADIUS, protože musíme jít trochu s dobou. To znamená konečně bumpnout TLS na 1.3 a udělat možná trochu hack, který souvisel s tím odpojováním – nechat cache třeba na týden, alespoň experimentálně. Pokud se pak objeví v síti nějaký pavouk, tak to bude pak snad dohledatelné v logu.
# /etc/freeradius/3.0/mods-available/eap (sekce tls-common)
tls-config tls-common {
private_key_password = heslo_server_klice
private_key_file = /etc/ssl/radius/server.key
certificate_file = /etc/ssl/radius/server.pem
ca_file = /etc/ssl/radius/ca.pem
# iOS a Android vyžadují TLS 1.2+; TLS 1.3 funguje od iOS 15 / Android 10
tls_min_version = "1.2"
tls_max_version = "1.3"
# Session cache: zkracuje dobu připojení při roamingu
# Lifetime 24h místo defaultních 168h — kompromis výkon/bezpečnost
cache {
enable = yes
lifetime = 86400
name = "EAP-TLS-Session-Cache"
}
} Nezbytnou třešničkou na dortu je pak ještě nasazení nastavení co nejméně bolestivým způsobem. Bohužel tvorba profilů vyžaduje ve full-enterprise provisioning, což se doma dělá trochu složitě, možná až škodlivě. Ale je možné vytvořit profil, nebo možná dokonce dva profily – jeden pro naši CA s overtrust a pak profil, co zařídí WPA2/3-EAP autentizační flow. Tohle jde udělat buď ručně v Apple Configuratoru, nebo se to dá prostě naskriptovat, protože to vlastně jen XMLko.
# /etc/freeradius/3.0/mods-available/eap (sekce tls-common)
tls-config tls-common {
private_key_password = heslo_server_klice
private_key_file = /etc/ssl/radius/server.key
certificate_file = /etc/ssl/radius/server.pem
ca_file = /etc/ssl/radius/ca.pem
# iOS a Android vyžadují TLS 1.2+; TLS 1.3 funguje od iOS 15 / Android 10
tls_min_version = "1.2"
tls_max_version = "1.3"
# Session cache: zkracuje dobu připojení při roamingu
# Lifetime 24h místo defaultních 168h — kompromis výkon/bezpečnost
cache {
enable = yes
lifetime = 86400
name = "EAP-TLS-Session-Cache"
}
} Takto vytvoření soubor by měl mít na sobě ozubené kolečko. Je možné ho pohodlně poslat AirDropem na dotčená zařízení, fungovat to bude na iOS i na macOS, ale je pak ještě nezbytně potřeba zapnout absolutní důvěru pro osobní CA, jinak se to bude pochopitelně každou chvíli ptát.
-
Import konfigurace přes AirDrop
-
Aktivace ve VPN a správa zařízení
-
Profil integruje CA
-
Zeptá se na údaje
-
Profil bude obsahovat všechny sítě zvlášť
-
V Obecné – Informace – Důvěryhodnost certifikátu je potřeba epxlicitně povolit důvěru vlastní kořenové CA
Při importu profilu tedy 1) uložime certifikát, 2) uložíme přihlašovací údaje pro EAP, 3) nastavíme plnou důvěru. Všechno by mělo jít hladce, i když je mi jasné, že to zní celé rozhodně jakkoliv, než hladce. Budu to tedy teď pár dnů zase pozorovat a jestli to zase selže, pak už teda nevím a bude tableflip. Všechno je v cronu, kontroly také... takže nás nespíš zase spíš vypečou updaty a doporučení, ale i to překonáme, musíme. Všechno bude ještě víc enterprise.