Pemilihan OpenVPN acak di systemd: mengapa ExecStart gagal
systemd bukan shell, jadi salinan yang diacak di dalam ExecStart mati. Pindahkan pilihan ke ExecStartPre, atau biarkan OpenVPN memilih server sendiri.
Empat puluh berkas .ovpn untuk satu negara datang dari penyedia, dan rencananya tampak jelas: salin satu secara acak ke tempatnya, lalu mulai terowongan. Ditulis sebagai pipa di dalam ExecStart, rencana itu mati saat boot dengan kode status yang tidak menjelaskan apa pun. Berkas unit bukan skrip, dan perbaikannya adalah entah menghadirkan shell secara eksplisit atau berhenti memilih berkas sama sekali.
Gejalanya: unit yang mulai lalu mati seketika
Status menunjukkan layanan gagal dalam sepersekian detik, dan baris jurnal menyebut perintah yang tidak akan pernah diterima shell mana pun. Tidak ada yang muncul tentang terowongan, karena terowongan itu tidak pernah dimulai.
Membaca baris perintah persis dari jurnal adalah cara tercepat untuk memastikannya. systemd menggemakan apa yang dijalankannya, dan string itu akan menampilkan karakter pipa sebagai argumen literal, bukan sebagai operator.
Mengapa ExecStart tidak dapat menjalankan pipa
systemd memecah baris perintahnya sendiri, menerapkan kutipan dan substitusi variabelnya sendiri, lalu menjalankan hasilnya secara langsung. Pipa, pengalihan, perluasan pola oleh shell, dan substitusi perintah sama sekali bukan bagian dari tata bahasa itu. Ini pilihan desain, bukan kelalaian: unit menyatakan secara deklaratif apa yang harus dijalankan, dan logika shell berada dalam skrip yang dipanggil unit. Kedua perbaikan mengikuti dari itu, dan tak satu pun menuntut memberi unit lebih banyak hak istimewa.
Itu juga menjelaskan kode keluar yang menyesatkan. Argumen pertama diperlakukan sebagai biner, jadi baris yang cacat gagal sebelum bagian mana pun dari logika Anda berjalan.
Lakukan pemilihan di ExecStartPre
Perbaikan langsungnya adalah langkah persiapan yang memanggil shell secara eksplisit, menjaga pemilihan dan permulaan dalam unit yang sama agar kegagalan di satu sisi tidak meninggalkan sisi lain berjalan sendiri.
[Service]
Type=notify
ExecStartPre=/bin/bash -c "ls /etc/openvpn/profiles/au* | shuf -n 1 | xargs -r -I{} cp -f {} /etc/openvpn/%i.conf"
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/%i.conf
Tiga detail menentukan apakah ini bertahan saat berhadapan dengan mesin sungguhan. Penamaan adalah jebakan pertama: systemd mengganti %i saat mengurai unit, jauh sebelum bash berjalan, jadi penentu itu harus berada di luar tanda kutip tunggal. xargs -r mencegah cp berjalan tanpa argumen saat pola tidak cocok dengan apa pun. Dan langkah persiapan yang gagal menghentikan unit, dan itulah hasil yang benar: memulai dengan konfigurasi kemarin lebih buruk daripada tidak memulai. Pemilihan acak yang selalu mengambil berkas yang sama biasanya bukan nasib buruk. Periksa apakah berkas yang disalin ditimpa oleh pembaruan paket, atau apakah pola hanya cocok dengan satu entri usang.
Atau biarkan OpenVPN memilih titik akhir
OpenVPN sudah dapat menyimpan beberapa titik akhir dalam satu profil dan memilih di antaranya secara acak, yang menghapus shell, penyalinan, dan akses tulis dari jalur boot sepenuhnya.
client
remote-random
<connection>
remote au1.example.net 1194 udp
</connection>
<connection>
remote au2.example.net 1194 udp
</connection>
Bentuk ini menyimpan pilihan server di dalam berkas yang dibuat penyedia, sehingga rotasi yang mengganti nama berkas tidak merusak unit. Ini juga membuat daftar kandidat dapat diaudit, yang tidak pernah dimiliki pola atas direktori. Pengacakan tetap berguna ketika profil berbeda lebih dari sekadar titik akhir: sertifikat berbeda, direktif perutean berbeda, kebijakan cipher berbeda. Dalam hal itu pilihannya adalah di antara konfigurasi utuh, dan langkah shell adalah cara jujur menyatakannya.
Baca kembali instans dan berkas yang dipakainya
Pastikan unit mana yang benar-benar berjalan sebelum men-debug isinya. Layanan meta yang dipaketkan dan templat adalah infrastruktur; unit yang sesuai dengan berkas Anda adalah instans yang dinamai menurut berkas itu.
systemctl list-units 'openvpn*'
systemctl cat [email protected]
journalctl -u openvpn@au -n 30 --no-pager
Instans yang tidak ada yang ingat pernah mengaktifkannya biasanya mengarah ke berkas konfigurasi tersesat di direktori paket. Matikan instans bernama itu alih-alih templatnya, jika tidak, peningkatan paket berikutnya akan mengembalikannya. Setelah perubahan, mulai unit dan baca baris perintah yang dilaporkan jurnal, lalu pastikan jalur konfigurasi yang benar-benar dibukanya. Satu pemeriksaan itu memisahkan pemilihan acak yang bekerja dari layanan yang diam-diam memakai ulang berkas dari bulan lalu.