Saya melaburkan masa yang agak lama untuk menghadam kegunaan protokol Kerberos menerusi banyaknya sesi percubaan yang mengecewakan. Setelah menempuh bersiri-siri episod kehampaan, kali ini terbayar juga sekian jumlah sumbangan tenaga yang agak melelahkan itu.
Secara teorinya, hal ini melibatkan dua istilah utama; Pelayan Kerberos dan Klien Kerberos. Saya ringkaskan keduanya hanya kepada istilah Pelayan dan Klien. Apa proses yang berlaku? Apabila Klien hendak bersambung dengan Pelayan:-
.keytab
;kinit
) untuk bersambung kepada Pelayan melalui SSH
dengan kaedah pengesahan GSSAPI
. Di sini, ada proses-prosesnya yang melibatkan akronim KDC
dan TGT
namun untuk tujuan pemahaman ringkas, saya tinggalkan penerangan berkenaannya. Penjelasan yang tuntas boleh diperolehi dari YouTube
,
Kerberos Authentication Explained | A deep dive.Kelihatan mudah, bukan? Walaubagaimanapun, prosesnya tidaklah sesenang yang disangkakan. Saya pening pada mulanya sebab memikirkan Klien tidak perlu untuk mempunyai pangkalan datanya sendiri namun, kefahaman saya silap. Secara rumusannya, Klien masih perlu membuat perkara sama sebagaimana proses yang berlaku untuk Pelayan.
Makanya, dua topik yang akan saya sentuh di sini iaitu:
OpenSSH
di dalam Fedora
telah disusun bersama dengan opsyen pengesahan melalui GSSAPI
secara lalai, tidak seperti distribusi lain yang memerlukan tampalan (patch) GSSAPI dipasang secara berasingan.Pemasangan:
sudo dnf install krb5-libs krb5-server krb5-workstation
Konfigurasi:
Uruskan perihal masa yang perlu diselaraskan terlebih dahulu. Fedora secara automatiknya menetapkan masa secara lokal. Kita mahu seragamkan masa ini secara automatik melalui rangkaian dan bukan secara lokal. Maka nyahkan terlebih dahulu tetapan lokal dan mulakan servis systemd-timesyncd
.
sudo timedatectl set-local-rtc 0
sudo systemctl enable --now systemd-timesyncd
timedatectl timesync-status
Server: 60.50.221.91 (0.fedora.pool.ntp.org) Poll interval: 1min 4s (min: 32s; max 34min 8s) Leap: normal Version: 4 Stratum: 2 Reference: AFF20F0 Precision: 1us (-22) Root distance: 8.895ms (max: 5s) Offset: -36.849ms Delay: 26.281ms Jitter: 78.696ms Packet count: 6 Frequency: +112.631ppm
Umumnya, aras Stratum yang bagus adalah 5 dan ke bawah kerana ia menunjukkan bahawa jam telah diseragamkan dengan sumber yang dipercayai. Semestinya aras 1 adalah terbaik tetapi peranti yang mencapai aras 1 keseragaman masa biasanya melibatkan kos yang tinggi, namun tidaklah semahal peranti-peranti yang menjadi sumber primer dalam rujukan bagi keselarasan masa dengan aras Stratum 0. Dalam kes saya ini, aras 2 sudah memadai.
Empat fail utama untuk ditetapkan (sunting dan sesuaikan di setiap VM).
/etc/krb5.conf
# To opt out of the system crypto-policies configuration of krb5, remove the
# symlink at /etc/krb5.conf.d/crypto-policies which will not be recreated.
includedir /etc/krb5.conf.d/
[libdefaults]
dns_lookup_realm = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt
spake_preauth_groups = edwards25519
dns_canonicalize_hostname = fallback
qualify_shortname = ""
default_realm = KERBEROS.LKL
default_ccache_name = KEYRING:persistent:%{uid}
[realms]
KERBEROS.LKL = {
kdc = vmone.kerberos.lkl
admin_server = vmone.kerberos.lkl
default_principal_flags = +preauth
}
[domain_realm]
.kerberos.lkl = KERBEROS.LKL
kerberos.lkl = KERBEROS.LKL
#[logging]
#kdc = FILE:/var/log/kerberos/krb5kdc.log
#admin_server = FILE:/var/log/kerberos/kadmind.log
#default = FILE:/var/log/kerberos/krb5libs.log
Saya langkau bahagian logging kerana proses pengesahan dilaksanakan melalui GSSAPI
iaitu komponen sistem Kerberos
yang berlainan dan tidak melibatkan servis KDC
secara langsung. Oleh itu, tiada sebarang output yang akan dikeluarkan dan dicatatkan oleh KDC
ke dalam log.
/var/kerberos/krb5kdc/kdc.conf
[kdcdefaults]
kdc_ports = 88
kdc_tcp_ports = 88
spake_preauth_kdc_challenge = edwards25519
[realms]
KERBEROS.LKL = {
master_key_type = aes256-cts-hmac-sha384-192
acl_file = /var/kerberos/krb5kdc/kadm5.acl
dict_file = /usr/share/dict/words
admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
supported_enctypes = aes256-cts-hmac-sha384-192:normal aes256-cts-hmac-sha1-96:normal
key_stash_file = /var/kerberos/krb5kdc/.k5.KERBEROS.LKL
# Supported encryption types for FIPS mode:
#supported_enctypes = aes256-cts-hmac-sha384-192:normal aes128-cts-hmac-sha256-128:normal
}
/var/kerberos/krb5kdc/kadm5.acl
*/admin@KERBEROS.LKL *
krb5one/admin@KERBEROS.LKL e *
~/.k5login
krb5two@KERBEROS.LKL
Cipta pangkalan data:-
sudo kdb5_util create -s
Initializing database '/var/kerberos/krb5kdc/principal' for realm 'KERBEROS.LKL', master key name 'K/M@KERBEROS.LKL' You will be prompted for the database Master Password. It is important that you NOT FORGET this password. Enter KDC database master key: Re-enter KDC database master key to verify:
Mulakan servis:-
sudo systemctl start krb5kdc
sudo systemctl start kadmin
Teruskan dengan langkah-langkah selanjutnya untuk menambah prinsipal bagi pengguna:
sudo kadmin.local
Authenticating as principal root/admin@KERBEROS.LKL with password. kadmin.local: addprinc krb5one No policy specified for krb5one@KERBEROS.LKL; defaulting to no policy Enter password for principal "krb5one@KERBEROS.LKL": Re-enter password for principal "krb5one@KERBEROS.LKL": Principal "krb5one@KERBEROS.LKL" created. kadmin.local: addprinc krb5one/admin No policy specified for krb5one/admin@KERBEROS.LKL; defaulting to no policy Enter password for principal "krb5one/admin@KERBEROS.LKL": Re-enter password for principal "krb5one/admin@KERBEROS.LKL": Principal "krb5one/admin@KERBEROS.LKL" created. kadmin.local: listprincs K/M@KERBEROS.LKL kadmin/admin@KERBEROS.LKL kadmin/changepw@KERBEROS.LKL krb5one/admin@KERBEROS.LKL krb5one@KERBEROS.LKL krbtgt/KERBEROS.LKL@KERBEROS.LKL kadmin.local: quit
Tip: Arahan di atas boleh juga ditaip menggunakan perintah baris yang berikut.
# Menambah admin
sudo kadmin.local -q "addprinc krb5one/admin"
# Tambah pengguna yang akan mendapatkan tiket melalui `kinit`
kadmin -p krb5one/admin -q "addprinc krb5one"
Buat langkah-langkah yang sama untuk VM2 dengan mengedit fail dan opsyen arahan seadanya serta mulakan semula servis krb5kdc
dan kadmin
jika ada sebarang perubahan dilakukan terhadap konfigurasinya.
Penyambungan Kerberos dari Klien (VM2) ke Pelayan (VM1).
Konfigurasi universal SSH
(lebih mudah tetapkan perkara di bawah ini di kedua-dua VM). Nyahkan komen dan aktifkan opsyen Kerberos
serta GSSAPI
:
/etc/ssh/sshd_config
# Kerberos options
KerberosAuthentication yes
# GSSAPI options
GSSAPIAuthentication yes
GSSAPICleanupCredentials yes
GSSAPIKeyExchange yes
/etc/ssh/ssh_config
Host *
GSSAPIAuthentication yes
GSSAPIDelegateCredentials yes
GSSAPIKeyExchange yes
Mulakan semula servis: sudo systemctl restart sshd
.
Di VM2 (Klien): Tambahkan hos Pelayan, hasilkan kunci untuknya, simpan ke dalam fail dan salin fail tersebut ke VM1 (Pelayan).
sudo kadmin.local
Authenticating as principal root/admin@KERBEROS.LKL with password. kadmin.local: addprinc -randkey host/vmone.kerberos.lkl No policy specified for host/vmone.kerberos.lkl@KERBEROS.LKL; defaulting to no policy Principal “host/vmone.kerberos.lkl@KERBEROS.LKL” created. kadmin.local: ktadd -k vmone.keytab host/vmone.kerberos.lkl Entry for principal host/vmone.kerberos.lkl with kvno 2, encryption type aes256-cts-hmac-sha384-192 added to keytab WRFILE:vmone.keytab. Entry for principal host/vmone.kerberos.lkl with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:vmone.keytab. kadmin.local: quit
Saya gagal menghadam cara yang dijelaskan oleh ArchWiki
pada subtopik “5.1 Remote Admin” di bawah “Service principals and keytabs”. Saya cuba cara ini namun tak berjaya. Hanya dengan kaedah manual di bawah saya dapat bersambung dengan Pelayan melalui SSH menggunakan pengesahan ‘GSSAPI’.
sudo chown krb5two:krb5two vmone.keytab
scp vmone.keytab vmone:.
Tip:
Seandainya tetapan untuk mengekstrak kekunci telahpun dibuat bagi krb5two/admin
[rujuk ‘/var/kerberos/krb5kdc/kadm5.acl’], arahan di atas boleh digantikan dengan:
kadmin -p krb5two/admin -q "addprinc -randkey host/vmone.kerberos.lkl"
kadmin -p krb5two/admin -q "ktadd -k vmone.keytab host/vmone.kerberos.lkl"
scp vmone.keytab vmone:.
Di VM1 (Pelayan): Import kunci yang telah disalin dari VM2 (Klien).
sudo ktutil
ktutil: rkt vmone.keytab ktutil: list slot KVNO Principal ---- ---- --------------------------------------------------------------------- 1 2 host/vmone.kerberos.lkl@KERBEROS.LKL 2 2 host/vmone.kerberos.lkl@KERBEROS.LKL ktutil: wkt /etc/krb5.keytab ktutil: quit
sudo klist -k -e /etc/krb5.keytab # Semak kunci
Keytab name: FILE:/etc/krb5.keytab KVNO Principal ---- -------------------------------------------------------------------------- 2 host/vmone.kerberos.lkl@KERBEROS.LKL (aes256-cts-hmac-sha384-192) 2 host/vmone.kerberos.lkl@KERBEROS.LKL (aes256-cts-hmac-sha1-96)
rm vmone.keytab
Di VM2 (Klien): Dapatkan tiket Kerberos dan sambungkan ke pelayan SSH.
kinit
klist # Untuk memaparkan maklumat tiket
ssh -v vmone
… debug1: Next authentication method: gssapi-keyex Authenticated to vmone.kerberos.lkl ([192.168.0.101]:22) using “gssapi-keyex”. …
Semak maklumat tiket di kedua-dua VM dengan arahan klist
.
VM1 (Pelayan):
Ticket cache: KCM:1000:51511 Default principal: krb5two@KERBEROS.LKL
Valid starting Expires Service principal 08/01/2024 20:18:20 08/02/2024 20:17:58 krbtgt/KERBEROS.LKL@KERBEROS.LKL renew until 08/01/2024 20:18:00
VM2 (Klien):
Ticket cache: KCM:1000 Default principal: krb5two@KERBEROS.LKL
Valid starting Expires Service principal 08/01/2024 20:18:00 08/02/2024 20:17:58 krbtgt/KERBEROS.LKL@KERBEROS.LKL renew until 08/01/2024 20:18:00 08/01/2024 20:18:20 08/02/2024 20:17:58 host/vmone.kerberos.lkl@ renew until 08/01/2024 20:18:00 Ticket server: host/vmone.kerberos.lkl@KERBEROS.LKL
Mungkin kelihatan sedikit janggal sebab Service principal untuk pelayan kelihatan tidak lengkap tanpa realm
. Pun begitu, jawapan daripada sebuah platform AI ini menyatakan bahawa tidak ada sebarang isu dengannya.
Antara cara untuk memadam kunci yang telah disimpan:-
sudo kadmin.local
Authenticating as principal root/admin@KERBEROS.LKL with password. kadmin.local: ktrem -q host/vmone.kerberos.lkl kadmin.local:
Saya kira, selesai sudah bahagian Kerberos
ini. Sambungan di atas boleh diterbalikkan dengan VM1 menjadi Klien manakala VM2 sebagai Pelayan tetapi Kerberos
mesti dihapuskan terlebih dahulu dengan perintah kdestroy
sebelum mendapatkan tiket semula.
Untuk penyediaan dua VM dengan distribusi yang sama ini, saya gunakan imej QEMU qcow2
bagi Fedora Server 40
, yang dimuat turun dari laman ini di bawah seksyen For Intel and AMD x86_64 systems.
Setiap satu VM ditetapkan alamat IP-nya sendiri dan hal ini dapat dicapai (terima kasih) dengan adanya fungsi untuk menambah peranti TUN/TAP
. Fungsi ini membolehkan pengguna untuk menambah alamat IP yang ditugaskan kepada VM masing-masing melalui laluan (route) daripada alamat IP yang dimiliki oleh hos.
Buat 1 skrip untuk aktifkan peranti tap
i.e. ~/tapup
dan jalankannya di terminal.
#!/usr/bin/env zsh
# Add new TAP (network tap) devices in TAP mode
sudo ip tuntap add dev tap1 mode tap
sudo ip tuntap add dev tap2 mode tap
# Bring up the tap devices, making them active
sudo ip link set dev tap1 up
sudo ip link set dev tap2 up
# Add routes to the assigned IP addresses for each tap
sudo ip route add 192.168.0.101 dev tap1
sudo ip route add 192.168.0.102 dev tap2
Urus firewall melalui UFW
(Uncomplicated Firewall) untuk membenarkan trafik yang diperlukan.
sudo ufw allow in on tap1
sudo ufw allow in on tap2
sudo ufw allow out on tap1
sudo ufw allow out on tap2
sudo ufw allow from 192.168.0.0/24 to any
Edit /etc/default/ufw
:
DEFAULT_FORWARD_POLICY="ACCEPT"
Sunting /etc/ufw/sysctl.conf
dengan menyahkomen baris-baris berikut:
net/ipv4/ip_forward=1
net/ipv6/conf/default/forwarding=1
net/ipv6/conf/all/forwarding=1
Tambah fail /etc/sysctl.d/99-arp-proxy.conf
dengan entri baris di bawah:
net.ipv4.conf.tap1.proxy_arp=1
net.ipv4.conf.tap2.proxy_arp=1
net.ipv4.conf.wlan0.proxy_arp=1
Muat semula sysctl
dan ufw
:
sudo sysctl --system
sudo systemctl restart ufw
sudo ufw reload
sudo ufw status verbose
Salin imej yang dimuat turun dan namakan semula kedua-dua imej agar mempunyai nama unik untuk pelaksanaan, dan ubah saiz imej dengan arahan berikut:
qemu-img resize Fedora-Server-KVM-40-1.14.x86_64_1.qcow2 30G
qemu-img resize Fedora-Server-KVM-40-1.14.x86_64_2.qcow2 30G
Perintah baris untuk memulakan VM adalah seperti berikut (edit yang mana perlu bagi menjalankan kedua-duanya sekali seperti nombor tap, alamat MAC
, dan nama imej):
qemu-system-x86_64 -enable-kvm \
-machine type=q35,vmport=off,usb=on \
-usb -device usb-tablet -device virtio-balloon -daemonize \
-vga qxl -display gtk,gl=on,show-cursor=on \
-display spice-app,gl=on -device virtio-serial-pci \
-spice unix=on,addr=/tmp/vm_spice.socket,disable-ticketing=on \
-m 1G -cpu host -smp 2 \
-nic tap,model=virtio-net-pci,id=nic0,ifname=tap1,script=no,downscript=no,mac=52:54:00:12:34:56 \
-drive media=disk,if=virtio,aio=native,cache.direct=on,file=laluan_ke_imej_Fedora-Server-KVM-40-1.14.x86_64_1.qcow2
Setelah VM dijalankan, ada 5 perkara yang akan terpapar untuk dibuat penetapan:-
enp0s2
.192.168.0.101
255.255.255.0
192.168.0.50
(alamat IP hos)8.8.8.8
Pun begitu, sekiranya terlupa untuk set up konfigurasi rangkaian semasa imej server ini mula-mula boot, buat langkah-langkah di bawah untuk mendapatkan sambungan Internet secara manual (aplikasikan kepada kedua-dua VM).
VM1:
sudo ip addr add 192.168.0.101/24 dev enp0s2
sudo ip route add default via 192.168.0.50 dev enp0s2 # this is the host IP address
VM2:
sudo ip addr add 192.168.0.102/24 dev enp0s2
sudo ip route add default via 192.168.0.50 dev enp0s2 # this is the host IP address
Tambahkan fail /etc/systemd/resolved.conf.d/dns_servers.conf
di kedua-dua VM dengan konfigurasi DNS
sebagaimana berikut.
[Resolve]
DNS=8.8.8.8
Dan mula semula servis systemd-resolved
serta ping
laman web untuk kepastian bahawa sambungan rangkaian telah berjaya.
sudo systemctl restart systemd-resolved
ping -c3 fedoraproject.org
Cuba SSH
dari dan ke semua penjuru iaitu hos, VM1 serta VM2.
Ubah saiz peranti dengan kaedah berikut:-
sudo parted /dev/vda
GNU Parted 3.6 Using /dev/vda Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) print Warning: Not all of the space available to /dev/vda appears to be used, you can fix the GPT to use all of the space (an extra 48234496 blocks) or continue with the current setting? Fix/Ignore? Fix Model: Virtio Block Device (virtblk) Disk /dev/vda: 32.2GB Sector size (logical/physical): 512B/512B Partition Table: gpt Disk Flags: pmbr_boot
Number Start End Size File system Name Flags 1 1049kB 2097kB 1049kB bios_grub 2 2097kB 1076MB 1074MB ext4 bls_boot 3 1076MB 7515MB 6439MB lvm
(parted) unit s (parted) print free Model: Virtio Block Device (virtblk) Disk /dev/vda: 62914560s Sector size (logical/physical): 512B/512B Partition Table: gpt Disk Flags: pmbr_boot
Number Start End Size File system Name Flags 34s 2047s 2014s Free Space 1 2048s 4095s 2048s bios_grub 2 4096s 2101247s 2097152s ext4 bls_boot 3 2101248s 14678015s 12576768s lvm 14678016s 62914526s 48236511s Free Space
(parted) resizepart 3 62914526s (parted) unit compact (parted) print free Model: Virtio Block Device (virtblk) Disk /dev/vda: 32.2GB Sector size (logical/physical): 512B/512B Partition Table: gpt Disk Flags: pmbr_boot
Number Start End Size File system Name Flags 17.4kB 1049kB 1031kB Free Space 1 1049kB 2097kB 1049kB bios_grub 2 2097kB 1076MB 1074MB ext4 bls_boot 3 1076MB 32.2GB 31.1GB lvm
(parted) quit Information: You may need to update /etc/fstab.
sudo pvresize /dev/vda3
Physical volume "/dev/vda3" changed 1 physical volume(s) resized or updated / 0 physical volume(s) not resized
sudo lvresize -l +100%FREE -r sysvg/root
Size of logical volume sysvg/root changed from <6.00 GiB (1535 extents) to <29.00 GiB (7423 extents). File system xfs found on sysvg/root mounted at /. Extending file system xfs to <29.00 GiB (31134318592 bytes) on sysvg/root... xfs_growfs /dev/sysvg/root meta-data=/dev/mapper/sysvg-root isize=512 agcount=4, agsize=392960 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=1, sparse=1, rmapbt=1 = reflink=1 bigtime=1 inobtcount=1 nrext64=1 data = bsize=4096 blocks=1571840, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0, ftype=1 log =internal log bsize=4096 blocks=16384, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 data blocks changed from 1571840 to 7601152 xfs_growfs done Extended file system xfs on sysvg/root. Logical volume sysvg/root successfully resized.
Apabila sudah selesai, boleh hentikan dan padam peranti tap
, e.g. skrip tapdn
:
#!/usr/bin/env zsh
# Flush the routing table for the TAP devices
sudo ip route flush dev tap1
sudo ip route flush dev tap2
# Bring down the TAP devices
sudo ip link set dev tap1 down
sudo ip link set dev tap2 down
# Delete the TAP devices
sudo ip link del dev tap1
sudo ip link del dev tap2
# Remove the TAP devices from the system
sudo ip tuntap del dev tap1 mode tap
sudo ip tuntap del dev tap2 mode tap