Cara mengetahui sandbox systemd mana yang menolak hook OpenVPN anda
Hook berfungsi sebagai root dan gagal di bawah systemd kerana unit menyimpan lebih sedikit keupayaan, /dev yang lebih kecil dan laluan baca sahaja.
Hook berfungsi apabila anda menjalankannya secara manual sebagai root dan mengembalikan Operation not permitted pada saat perkhidmatan memulakannya. Fail tidak berubah antara kedua-dua larian itu; persekitaran yang berubah. systemd memberikan proses dunia yang lebih kecil: lebih sedikit keupayaan, /dev yang berbeza, laluan sistem fail baca sahaja dan had atas tugasan. Baca kegagalan itu sebagai sempadan yang menolak satu operasi tertentu, bukan sebagai skrip yang rosak.
Mulakan dengan operasi yang ditolak
Baris log yang menyatakan unit gagal hampir tidak memberitahu apa-apa. Baris yang berguna menamakan panggilan yang ditolak: nod peranti yang tidak dapat dibuka, direktori yang tidak dapat ditulis, ruang nama yang tidak dapat dicipta. Cari panggilan itu sebelum anda menyentuh satu arahan pun, kerana setiap satu memetakan kepada kekangan yang berbeza. Kemudian baca unit yang benar-benar berjalan, termasuk drop-in, bukannya fail yang dihantar oleh pakej.
Pertanyaan di bawah mencetak laluan fragmen, direktori drop-in dan sifat yang penting untuk penolakan peranti atau sistem fail. Baca semuanya sebelum memutuskan sempadan mana yang relevan:
systemctl show "[email protected]" -p FragmentPath -p DropInPaths -p PrivateDevices -p DevicePolicy -p DeviceAllow -p ProtectHome -p ProtectSystem -p TasksMax
journalctl -u "[email protected]" -b --no-pager | grep -iE 'operation not permitted|permission denied|cannot open|failed'Tiada apa-apa dalam blok itu menulis. Jika panggilan yang ditolak tiada dalam jurnal, naikkan verbositi klien untuk satu larian daripada meneka arahan. Proses yang berjalan membuktikan unit telah bermula, bukan bahawa hook berjalan dengan keistimewaan yang diperlukan.
Ruang nama memerlukan hak mount yang tidak pernah digunakan oleh peranti TUN
Dua operasi yang kelihatan sama dalam satu hook mempunyai profil kebenaran yang berbeza. Membuka /dev/net/tun dan mencipta antara muka memerlukan pentadbiran rangkaian serta akses kepada nod itu. Mencipta ruang nama rangkaian bernama juga memerlukan kerja mount, kerana alat ruang nama me-mount /sys paparan baharu dan mengikat direktori keadaan pada tempatnya. unit klien huluan sengaja membiarkan pentadbiran mount di luar set sempadannya, jadi langkah ruang nama ditolak sedangkan terowong itu sendiri akan berfungsi.
Sebab itulah memberikan nod peranti tidak menyelamatkan skrip. Kebenaran peranti menjawab satu soalan, sama ada proses ini boleh membuka nod ini, dan soalan ruang nama adalah lain. Padankan panggilan yang gagal dengan keupayaannya sebelum meluaskan apa-apa.
Ujian dalam shell anda mewarisi setiap keupayaan yang dimiliki root tanpa had, dan unit mewarisi apa yang dikekalkan oleh set sempadannya. Kedua-dua larian itu ialah eksperimen yang berbeza walaupun binari itu sama.
Peranti, laluan terlindung dan had atas tugasan
Setelah operasi yang ditolak diketahui, tiga kumpulan arahan menjelaskan kebanyakan kegagalan. Akses peranti dikawal oleh PrivateDevices, yang menggantikan /dev dengan set minimum peranti pseudo, dan oleh DevicePolicy dengan DeviceAllow, yang menentukan apa yang dibenarkan oleh cgroup. /dev/net/tun bukan bahagian daripada set minimum itu, jadi unit dengan PrivateDevices=yes tidak dapat membukanya, apa pun kata dasar peranti.
Perlindungan sistem fail menjawab soalan kedua. ProtectHome=yes menjadikan /home, /root dan /run/user tidak boleh diakses, dan ProtectSystem=full menjadikan /usr, /boot dan /etc baca sahaja. Oleh itu hook yang menulis di sebelah fail konfigurasinya sendiri berfungsi dalam shell anda dan gagal di bawah unit, dengan bentuk kebenaran yang sama seperti keupayaan yang hilang. Pindahkan input yang boleh ditulis ke laluan yang dibenarkan oleh dasar, atau tambah entri ReadWritePaths= yang sempit.
Had sumber ialah kumpulan ketiga, dan yang paling kurang jelas. TasksMax= mengehadkan berapa banyak tugasan yang boleh dicipta oleh unit, dan had atas deskriptor fail berkelakuan sama untuk soket dan pemegang. Penggunaan yang telah berkembang melebihi had gagal dengan ralat sumber dan bukannya ralat kebenaran, dan sebab itulah mesej yang tepat masih penting.
Keluarkan langkah ruang nama daripada hook
Persediaan yang memerlukan keistimewaan yang tidak boleh dimiliki oleh klien tergolong dalam unitnya sendiri. oneshot yang berjalan sebelum klien, menyimpan hasilnya dan disusun sebelum sambungan memberikan langkah ruang nama apa yang diperlukannya tanpa menyerahkan hak itu kepada proses terowong. Klien kemudian merujuk unit itu dan bukannya memanggil skrip daripada hook upnya.
Templat di bawah ialah bentuk permulaan, bukan sesuatu yang digunakan tanpa dibaca. Ia menyimpan persediaan di tempat keistimewaan itu berada dan membiarkan unit terowong tidak disentuh:
# /etc/systemd/system/[email protected]
[Unit]
Description=Namespace preparation for %i
Before=openvpn-client@%i.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/netns-up.sh %i
CapabilityBoundingSet=CAP_NET_ADMIN CAP_SYS_ADMIN
[Install]
WantedBy=multi-user.targetTambahkan susunan dengan drop-in dan bukannya menyunting unit yang dibungkus, supaya peningkatan tidak boleh menggugurkan perubahan anda secara senyap. Direktori itu dikunci kepada nama instans, jadi profil kedua memerlukan failnya sendiri:
sudo mkdir -p /etc/systemd/system/[email protected]
sudo tee /etc/systemd/system/[email protected]/10-namespace.conf >/dev/null <<'CONF'
[Unit]
[email protected]
[email protected]
CONF
sudo systemctl daemon-reloadUlangi panggilan yang sama selepas perubahan
Pembaikan hanya disahkan apabila panggilan yang sama menghasilkan keputusan yang berbeza. Mulakan semula kedua-dua unit, jalankan operasi yang gagal dan bandingkan hasilnya dengan baris jurnal yang anda simpan sebelum perubahan. Unit yang bermula sedangkan hook tidak berjalan lagi bukan pembaikan.
Urutan di bawah mengekalkan perbandingan itu jujur, kerana ia memeriksa panggilan yang ditolak dan bukan warna unit. Simpan outputnya di sebelah baris jurnal yang anda tangkap sebelum perubahan:
sudo systemctl restart "[email protected]" "[email protected]"
systemctl status "[email protected]" --no-pager
journalctl -u "[email protected]" -b --no-pager | grep -c 'Operation not permitted'
ip -brief addr show tun0Kira penolakan dan bukannya membaca baris terakhir, kerana hook boleh gagal, mencuba semula dan berjaya, dan hanya kiraan menunjukkan sama ada sempadan itu bergerak. Tinggalkan komen dalam drop-in yang menamakan arahan yang anda longgarkan dan sebabnya, kerana peningkatan seterusnya membandingkan konfigurasi anda dengan lalai yang dibungkus. Unit yang hanya bermula selepas semua perlindungan dimatikan belum dibaiki.