Konfigurasi Libvirt Selamat dengan TLS dan Pengesahan Kerberos melalui SASL

Percubaan saya dengan libvirt pada mulanya tidaklah serius. Hanya ingin mengenali asas pengurusan mesin maya menerusi virt-install dan virsh, sambil-sambil membaca dokumentasi yang ditemui di Internet. Namun begitu, semakin lama saya mencuba, semakin tertarik saya kepada aspek keselamatan dan pengesahan sambungan klien dalam libvirt, sesuatu yang sebelum ini saya abaikan kerana berasakan tidak perlu.
Rujukan seperti ArchWiki hanya memperkenalkan topik autentikasi ini secara sepintas lalu, dengan pautan kepada dokumentasi rasmi: libvirt: Connection authentication. Dari sinilah saya mula menyelami secara lebih serius kaedah-kaedah autentikasi yang disokong oleh libvirt.
Memandangkan sistem saya sudahpun dikonfigurasikan dengan Kerberos sebagai kaedah pengesahan untuk sambungan SSH dalam rangkaian tempatan, saya tertarik untuk mengintegrasikan libvirt dengan Kerberos melalui GSSAPI. Dalam teori, ia kelihatan mudah, dan saya dengan penuh yakin menganggap ia boleh disiapkan dalam masa singkat.
Namun realitinya tidak begitu. Apa yang kelihatan mudah di permukaan, rupanya penuh dengan kekangan konfigurasi, modul yang tidak didokumentasikan sepenuhnya, dan cabaran pemahaman konsep SASL, TLS, serta hak akses pengguna. Beberapa kali saya hampir berputus asa, benar-benar terasa ingin berhenti.
Alhamdulillah, selepas beberapa pusingan cubaan, penyahpepijatan, dan bacaan lintang-pukang, saya akhirnya berjaya menyiapkan satu konfigurasi libvirt yang selamat, lengkap dengan sokongan TLS serta autentikasi Kerberos menggunakan SASL.
Catatan ini saya tulis bukan sahaja untuk rujukan pengguna lain yang ingin mencapai perkara sama, tetapi juga sebagai ingatan kepada diri sendiri bahawa jalan yang sukar selalunya menyimpan pelajaran yang tidak ternilai.
Skop dan Objektif Artikel
Artikel ini menggunakan pendekatan modular daemons, bukan lagi libvirtd.service. Jika anda masih menggunakan monolithic daemon, sesetengah bahagian perlu disesuaikan.
Penulisan ini memfokuskan kepada konfigurasi libvirt untuk menyokong sambungan selamat melalui protokol TLS serta pengesahan berasaskan Kerberos menggunakan modul SASL. Ia mengandaikan persekitaran rangkaian tempatan (LAN) yang telah sedia mempunyai perkhidmatan Kerberos dan akses kepada pengguna sah melalui GSSAPI.
Tujuan utama adalah untuk:
- Menyediakan konfigurasi
TLSyang betul antara hos dan klienlibvirt; - Mengaktifkan dan menyelaras modul
SASLdengan kaedahGSSAPIuntuk autentikasi pengguna berasaskanKerberos; - Menghurai isu-isu umum yang mungkin timbul semasa integrasi, termasuk konfigurasi hak akses, ralat modul, serta tingkah laku sambungan;
- Memberikan penyelesaian berasaskan senario sebenar, bukan sekadar bergantung pada dokumentasi rasmi.
Sasaran Pembaca
Artikel ini ditujukan kepada pengguna yang telah terbiasa dengan asas libvirt, serta memahami konsep asas Kerberos, SASL, dan konfigurasi perkhidmatan dalam sistem berasaskan Linux, khususnya Arch Linux dan yang setaraf dengannya.
Keperluan Sistem
Sesetengah sistem operasi tidak memasang plugin SASL Kerberos secara lalai. Anda boleh menyemak keberadaannya dengan arahan berikut:
bashpluginviewer | grep gssapiSekiranya tiada output terpapar, anda perlu memasang pakej cyrus-sasl-gssapi. Setelah dipasang, semakan semula menggunakan pluginviewer akan memaparkan mekanisme seperti berikut:
...
Plugin "gssapiv2" [loaded], API version: 4
SASL mechanism: GSSAPI, best SSF: 256, supports setpass: no
security flags: NO_ANONYMOUS|NO_PLAINTEXT|NO_ACTIVE|PASS_CREDENTIALS|MUTUAL_AUTH
features: WANT_CLIENT_FIRST|PROXY_AUTHENTICATION|DONTUSE_USERPASSWD
...
Perisian Tambahan diperlukan:
dnsmasq: diperlukan untukvirtual NAT bridge.certtoolatauOpenSSL: untuk penjanaan sijil TLS.remote-viewer: untuk akses GUI VM melalui protokol SPICE.
Konfigurasi Autentikasi GSSAPI/Kerberos
Menurut dokumentasi rasmi libvirt di pautan GSSAPI/Kerberos auth, hos perlu memiliki satu prinsipal iaitu libvirt/full.hostname@KERBEROS.REALM. Prinsipal ini perlu dieksport ke dalam keytab dan diletakkan di lokasi khusus, iaitu /etc/libvirt/krb5.tab.
Namun begitu, berdasarkan pengalaman saya, hanya meletakkan satu prinsipal ini mengakibatkan kegagalan proses autentikasi. Berikut ialah mesej ralat yang saya hadapi:
virtproxyd: authentication failed: Failed to start SASL negotiation: -13 (SASL(-13): authentication failure: GSSAPI Failure: gss_accept_sec> virtproxyd: authentication failed: authentication failed virtproxyd: Cannot recv data: Input/output error
Saya mendapati bahawa autentikasi hanya berjaya setelah saya menambah dua prinsipal berikut ke dalam fail krb5.tab.
host/full.hostname@EXAMPLE.COMlibvirt/full.hostname@EXAMPLE.COM
Tambah kunci untuk servis libvirt
bashsudo kadmin.localkadmin.local: addprinc -randkey libvirt/full.hostname No policy specified for libvirt/full.hostname@EXAMPLE.COM; defaulting to no policy Principal "libvirt/full.hostname@EXAMPLE.COM" created. kadmin.local: ktadd -k /etc/libvirt/krb5.tab libvirt/full.hostname Entry for principal libvirt/full.hostname with kvno 2, encryption type aes256-cts-hmac-sha384-192 added to keytab WRFILE:/etc/libvirt/krb5.tab. Entry for principal libvirt/full.hostname with kvno 2, encryption type aes128-cts-hmac-sha256-128 added to keytab WRFILE:/etc/libvirt/krb5.tab.
Semak kandungan
keytab:bashsudo klist -kt /etc/libvirt/krb5.tabKeytab name: FILE:/etc/libvirt/krb5.tab KVNO Timestamp Principal ---- ------------------- ------------------------------------------------------ 3 08/01/2025 11:46:03 host/full.hostname@EXAMPLE.COM 3 08/01/2025 11:46:03 host/full.hostname@EXAMPLE.COM 2 08/01/2025 11:57:17 libvirt/full.hostname@EXAMPLE.COM 2 08/01/2025 11:57:17 libvirt/full.hostname@EXAMPLE.COM
Uji Sambungan Menggunakan TCP
Sebagai langkah awal, saya memulakan ujian sambungan menggunakan protokol TCP sebelum mengaktifkan TLS. Hal ini memudahkan saya mengasingkan isu berkaitan autentikasi tanpa diganggu masalah sijil keselamatan.
Konfigurasi Fail Berkaitan:
Apabila beralih kepada sambungan
TLS, tukar nilai “listen_tls” kepada1dan “listen_tcp” kepada0. Nyahkomen jugaauth_tls="sasl"./etc/libvirt/virtproxyd.conflisten_tls = 0 listen_tcp = 1 auth_tcp = "sasl" #auth_tls = "sasl"/etc/sasl2/libvirt.confmech_list: gssapi keytab: /etc/libvirt/krb5.tabSaya rujuk dokumentasi
libvirtdi Modular driver daemons: Switching to modular daemons untuk mengaktifkan perkhidmatan berkaitan:bashfor drv in qemu network storage do sudo systemctl enable virt${drv}d.service virt${drv}d{,-ro,-admin}.socket doneMulakan soket untuk set daemon yang sama:
bashfor drv in qemu network storage do sudo systemctl start virt${drv}d{,-ro,-admin}.socket doneAktifkan juga perkhidmatan
virtproxyd:bashsudo systemctl enable virtproxyd.service virtproxyd{,-ro,-admin}.socket sudo systemctl start virtproxyd{,-ro,-admin}.socketDalam konfigurasi ini, hanya
virtqemud,virtnetworkd,virtproxyddanvirtstorageddigunakan. Oleh itu, saya hanya mengaktifkan daemon dan soket yang berkaitan dengan keempat-empat perkhidmatan tersebut.kinitdan semak tiket:bashkinit <username> klistTicket cache: KEYRING:persistent:1000:1000 Default principal: <username>@EXAMPLE.COM
Valid starting Expires Service principal 08/02/2025 22:36:06 08/03/2025 08:36:06 krbtgt/EXAMPLE.COM@EXAMPLE.COM renew until 08/09/2025 22:36:06Mulakan soket
virtproxyd-tcp:bashsudo systemctl start virtproxyd-tcp.socketGunakan arahan di bawah untuk uji sambungan:
bashvirsh -c qemu+tcp://<hostname>/systemGantikan
<hostname>dengan namahostname/FQDNyang ditetapkan untuk alamat IP peranti anda di dalam fail/etc/hosts.Jika berjaya, semakan tiket seterusnya akan turut memaparkan prinsipal servis untuk
libvirt:... Valid starting Expires Service principal 08/02/2025 22:45:12 08/03/2025 08:36:06 libvirt/full.hostname@EXAMPLE.COM renew until 08/09/2025 22:36:06 ...
Konfigurasi Sijil TLS x509
Setelah autentikasi GSSAPI berfungsi menggunakan protokol TCP, saya beralih kepada konfigurasi sambungan TLS yang lebih selamat dan disokong sepenuhnya oleh libvirt.
certtool
Rujuk libvirt | Public Key Infrastructure set up untuk mengetahui struktur direktori dan lokasi fail sijil yang betul.
Ikuti langkah-langkah penjanaan sijil CA, pelayan dan klien dari pautan tersebut.
Tambah entri
encryption_keydalam failserver.infodanclient.infountuk mengelakkan ralatdecryption failed:server.info... tls_www_server encryption_key signing_keyclient.info... tls_www_client encryption_key signing_keyKemudian, sunting
/etc/libvirt/virtproxyd.confsemula untuk mengaktifkanTLS.Aktifkan dan mulakan soket
virtproxyd-tls:bashsudo systemctl enable --now virtproxyd-tls.socket
Uji Sambungan Menggunakan TLS
Gunakan arahan di bawah untuk uji sambungan menggunakan
TLS:bashvirsh -c qemu://full.hostname/systemSaya menetapkan dua nama hos bagi peranti ini:
kdc.archey.locwrarchey
Walau bagaimanapun, hanya nama hos penuh pertama yang berjaya disambung.
Hostnamependek sepertiwrarcheygagal kerana sijil tidak memadankan nama hos.warning : virNetTLSContextCheckCertificate:532 : Certificate check failed Certificate [session] owner does not match the hostname wrarchey error: failed to connect to the hypervisor error: authentication failed: Failed to verify peer's certificate
Semak status perkhidmatan
virtqemud,virtnetworkddanvirtproxyddengan arahan:bashsudo systemctl status <service-name>
Konfigurasi SPICE (GUI VM)
Nyahkomen baris berikut pada fail:
/etc/libvirt/qemu.confspice_listen = "0.0.0.0" spice_tls = 1Sijil untuk SPICE perlu diletakkan di
/etc/pki/libvirt-spice. Direktori ini mesti mengandungi:ca-cert.pem- sijil CAserver-cert.pem- sijil pelayanserver-key.pem- kunci peribadi pelayan
Opsyen untuk paparan
spicedenganTLSsekiranya menggunakanvirt-install:--graphics spice,listen=0.0.0.0,defaultMode=secure
- Jika mengubah terus
XMLdomain:<graphics type='spice' autoport='yes' defaultMode='secure'> <listen type='address' address='0.0.0.0'/> </graphics>
- Akses GUI VM melalui
SPICE:bashremote-viewer --spice-ca-file=/etc/pki/libvirt-spice/ca-cert.pem "spice://full.hostname?tls-port=5900"
Penjanaan Sijil untuk SPICE
Menggunakan OpenSSL
Rujuk artikel Jana Sijil HTTPS untuk Domain yang Berasaskan ’localhost’ sebagai panduan asas.
Ubah suai fail
domains.extagar sesuai untuk digunakan denganspice, dengan melakukan penyesuaian berikut:Sunting nilai
keyUsagedengan hanya mengekalkandigitalSignature. Nilai ini sahaja sudah mencukupi keranaSPICEmenggunakan sijil ini untuk tujuan pengesahan identiti, bukan penyulitan berlapis sepertiHTTPS.Gantikan entri nama domain
localhostdengan nama domain yang merujuk kepada alamat IP peranti anda.
Menggunakan certtool
- Prosedurnya sama seperti untuk
libvirt, tetapi untukspice, anda tidak perlu menyertakan entriencryption_keydalam failserver.info, kerana SPICE tidak memerlukan fungsi penyulitan tahap tinggi yang sama.
Autentikasi SASL (GSSAPI/Kerberos) untuk SPICE
Autentikasi SASL melalui GSSAPI juga disokong oleh SPICE, namun proses konfigurasi ini lebih rumit berbanding libvirt. Dokumentasi yang tersedia banyak merujuk kepada penggunaan prinsipal qemu/full.hostname@KERBEROS.REALM, yang ternyata tidak berfungsi dalam kes saya.
Hanya selepas beberapa kali percubaan, barulah muncul ralat sebenar yang mendedahkan prinsipal sebenar yang diperlukan:
(remote-viewer): GSpice-CRITICAL : Failed to start SASL negotiation: -1 (SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (Server spice/full.hostname@EXAMPLE.COM not found in Kerberos database))
Rupa-rupanya, SPICE menjangkakan prinsipal spice/FQDN@REALM, bukannya qemu.
Berikut ialah langkah-langkah yang saya ambil untuk menyelesaikan isu ini:
Tambah prinsipal
spice/full.hostnamedengan opsyen-randkeymenggunakankadmin.local.Eksport kunci prinsipal ini ke dalam fail
/etc/qemu/krb5.tab.Tetapkan pemilikan fail tersebut kepada pengguna dan kumpulan
libvirt-qemu.Nyahkomen entri di bawah pada fail berikut:
/etc/libvirt/qemu.confspice_sasl = 1Pastikan fail yang seterusnya ini mengandungi baris-baris berikut:
/etc/sasl2/qemu.confmech_list: gssapi keytab: /etc/qemu/krb5.tabMulakan semula semua perkhidmatan yang berkaitan:
bashfor drv in qemu network storage do sudo systemctl restart virt${drv}d{,-ro,-admin}.socket done sudo systemctl restart virtproxyd{,-ro,-admin}.socket sudo systemctl restart virtproxyd-tls.socket
Penyelesaian Masalah
Jika
libvirt NATgagal mendapatkan alamatDHCP, pastikanfirewalltidak menyekat rangkaianvirbr0: Gunakan peraturan umum berikut untuk membenarkan trafik NAT dan DHCP:bashsudo ufw allow in on virbr0 sudo ufw allow out on virbr0 sudo ufw reloadvirbr0ialah antara muka rangkaian maya (virtual bridge) yang digunakan olehlibvirtsecara lalai untuk NAT.Isu kebenaran ditolak melibatkan hak akses ke direktori sistem: Pastikan pengguna dan kumpulan
libvirt-qemumempunyai akses penuh ke direktori berikut:/var/lib/libvirt/images/etc/pki/libvirt-spice
Tambahkan juga pengguna anda ke dalam kumpulan
libvirtdanlibvirt-qemu:bashsudo usermod -aG libvirt,libvirt-qemu $USER
Kesimpulan
Pendekatan modular daemons dalam konfigurasi libvirt yang digabungkan dengan sokongan TLS dan GSSAPI (Kerberos) menawarkan kelebihan dari aspek keselamatan dan pengasingan perkhidmatan.
Walau bagaimanapun, pelaksanaannya bukanlah sesuatu yang mudah memandangkan dokumentasi rasmi agak terpecah dan memerlukan pemahaman mendalam terhadap Kerberos, SASL, dan pengurusan TLS.
Semoga catatan ini dapat membantu pengguna lain yang sedang mencuba kaedah autentikasi selamat untuk libvirt.
