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
TLS
yang betul antara hos dan klienlibvirt
; - Mengaktifkan dan menyelaras modul
SASL
dengan kaedahGSSAPI
untuk 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:
bash
pluginviewer | grep gssapi
Sekiranya 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
.certtool
atauOpenSSL
: 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.COM
libvirt/full.hostname@EXAMPLE.COM
Tambah kunci untuk servis libvirt
bash
sudo kadmin.local
kadmin.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
:bash
sudo klist -kt /etc/libvirt/krb5.tab
Keytab 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
” kepada1
dan “listen_tcp
” kepada0
. Nyahkomen jugaauth_tls="sasl"
./etc/libvirt/virtproxyd.conf
listen_tls = 0 listen_tcp = 1 auth_tcp = "sasl" #auth_tls = "sasl"
/etc/sasl2/libvirt.conf
mech_list: gssapi keytab: /etc/libvirt/krb5.tab
Saya rujuk dokumentasi
libvirt
di Modular driver daemons: Switching to modular daemons untuk mengaktifkan perkhidmatan berkaitan:bash
for drv in qemu network do sudo systemctl enable virt${drv}d.service virt${drv}d{,-ro,-admin}.socket done
Mulakan soket untuk set daemon yang sama:
bash
for drv in qemu network do sudo systemctl start virt${drv}d{,-ro,-admin}.socket done
Aktifkan juga perkhidmatan
virtproxyd
:bash
sudo systemctl enable virtproxyd.service virtproxyd{,-ro,-admin}.socket sudo systemctl start virtproxyd{,-ro,-admin}.socket
Dalam konfigurasi ini, hanya
virtqemud
,virtnetworkd
, danvirtproxyd
digunakan. Oleh itu, saya hanya mengaktifkan daemon dan soket yang berkaitan dengan ketiga-tiga perkhidmatan tersebut.kinit
dan semak tiket:bash
kinit <username> klist
Ticket 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
:bash
sudo systemctl start virtproxyd-tcp.socket
Gunakan arahan di bawah untuk uji sambungan:
bash
virsh -c qemu+tcp://<hostname>/system
Gantikan
<hostname>
dengan namahostname
/FQDN
yang 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_key
dalam failserver.info
danclient.info
untuk mengelakkan ralatdecryption failed
:server.info
... tls_www_server encryption_key signing_key
client.info
... tls_www_client encryption_key signing_key
Kemudian, sunting
/etc/libvirt/virtproxyd.conf
semula untuk mengaktifkanTLS
.Aktifkan dan mulakan soket
virtproxyd-tls
:bash
sudo systemctl enable --now virtproxyd-tls.socket
Uji Sambungan Menggunakan TLS
Gunakan arahan di bawah untuk uji sambungan menggunakan
TLS
:bash
virsh -c qemu://full.hostname/system
Saya menetapkan dua nama hos bagi peranti ini:
kdc.archey.loc
wrarchey
Walau bagaimanapun, hanya nama hos penuh pertama yang berjaya disambung.
Hostname
pendek sepertiwrarchey
gagal 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
,virtnetworkd
danvirtproxyd
dengan arahan:bash
sudo systemctl status <service-name>
Konfigurasi SPICE (GUI VM)
Nyahkomen baris berikut pada fail:
/etc/libvirt/qemu.conf
spice_listen = "0.0.0.0" spice_tls = 1
Sijil 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
spice
denganTLS
sekiranya menggunakanvirt-install
:--graphics spice,listen=0.0.0.0,defaultMode=secure
- Jika mengubah terus
XML
domain:<graphics type='spice' autoport='yes' defaultMode='secure'> <listen type='address' address='0.0.0.0'/> </graphics>
- Akses GUI VM melalui
SPICE
:bash
remote-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.ext
agar sesuai untuk digunakan denganspice
, dengan melakukan penyesuaian berikut:Sunting nilai
keyUsage
dan kekalkan hanyadigitalSignature
. Nilai ini sahaja sudah mencukupi keranaSPICE
menggunakan sijil ini untuk tujuan pengesahan identiti, bukan penyulitan berlapis sepertiHTTPS
.Gantikan entri nama domain
localhost
dengan nama domain yang merujuk kepada alamat IP peranti anda.
Menggunakan certtool
- Prosedurnya sama seperti untuk
libvirt
, tetapi untukspice
, anda tidak perlu menyertakan entriencryption_key
dalam 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.hostname
dengan opsyen-randkey
menggunakankadmin.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.conf
spice_sasl = 1
Pastikan fail yang seterusnya ini mengandungi baris-baris berikut:
/etc/sasl2/qemu.conf
mech_list: gssapi keytab: /etc/qemu/krb5.tab
Mulakan semula semua perkhidmatan yang berkaitan:
bash
for drv in qemu network 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
Sambungan ke rangkaian maya
NAT bridge
gagal disebabkan sekatanfirewall
Saya menggunakanUFW
, dan perlu membuka port serta antara muka yang berkaitan:bash
sudo ufw allow in on virbr0 sudo ufw allow out on virbr0 sudo ufw allow in proto udp from 192.168.122.0/24 to any port 67
virbr0
ialah antara muka rangkaian maya (virtual bridge) yang digunakan olehlibvirt
secara lalai untuk NAT.Isu kebenaran ditolak melibatkan hak akses ke direktori sistem Pastikan pengguna dan kumpulan
libvirt-qemu
mempunyai akses penuh ke direktori berikut:/var/lib/libvirt/images
/etc/pki/libvirt-spice
Tambahkan juga pengguna anda ke dalam kumpulan
libvirt
danlibvirt-qemu
:bash
sudo 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
.