Apakah skrip hook bisa mencapai sisi lain terowongan bergantung pada tiga syarat: peristiwa mana yang diatribusikan padanya, apakah OpenVPN masih berada dalam urutan mulainya saat skrip berjalan, dan apakah pekerjaan itu sudah dilepaskan dari urutan tersebut. Sebagian besar skrip gagal pada syarat ketiga. Menambahkan jeda memperlakukan masalah siklus hidup sebagai masalah waktu, dan itu berhasil cukup sering untuk menyesatkan.

Tentukan dulu peristiwanya, lalu mekanisme penundaan pekerjaan, lalu tempat pekerjaan tertunda berjalan. Ketiga keputusan itu saling bebas, dan mencampurnya adalah cara hook dua baris menjadi satu sore penuh.

Mengapa hook menunggu terowongan yang menunggunya

OpenVPN memanggil hook-nya secara sinkron, di dalam proses yang sama yang memindahkan paket. up dipicu setelah perangkat tun atau tap ada tetapi sebelum rute apa pun ditambahkan, dan route-up dipicu setelah rute; tidak ada momen yang menjanjikan bahwa lawan akan menjawab. Selama skrip dari salah satu hook masih berjalan, daemon tidak meneruskan, jadi perintah yang berharap lalu lintas melintasi terowongan menunggu terowongan yang menunggu perintah itu. Penantian melingkar inilah sebabnya eksekusi manual lolos dan hook kehabisan waktu.

Tambalan yang jelas, tidur beberapa detik, kadang berhasil karena ujung jauh naik sendiri, bukan karena jeda memperbaiki sesuatu. Pembantu yang menanyakan kesiapan adalah jawaban lain: hook kembali, penerusan dimulai, dan pembantu mendapat apa yang dibutuhkannya begitu hal itu benar-benar ada.

Pilih hook berdasarkan peristiwa, bukan berdasarkan kemudahan

Pasang up pada pekerjaan yang hanya membutuhkan perangkat, route-up pada pekerjaan yang membutuhkan rute, dan simpan client-connect serta client-disconnect untuk tugas per klien di sisi server. Pembersihan saat terputus harus tahan dijalankan dua kali, karena penyambungan ulang melalui antarmuka persisten tidak mengikuti urutan yang sama dengan mulai ulang penuh. Di server, client-connect dipicu saat klien mengautentikasi, bukan saat daemon mulai, yang layak dipastikan sebelum logika dipindahkan ke sana. Jika pekerjaan itu milik siklus hidup layanan dan bukan satu koneksi, unit systemd adalah rumah yang lebih baik daripada hook mana pun.

Perintah hook dijalankan langsung oleh daemon, tanpa shell di antaranya, jadi ifconfig_remote dalam baris up tiba sebagai teks literal. Bungkus perintah itu dalam shell eksplisit, atau simpan logikanya dalam skrip yang membaca lingkungan. ipchange adalah satu direktif yang menambahkan argumennya sendiri: ia menyerahkan alamat dan port kepada perintah, jadi skrip yang ditulis untuk tidak satu pun melihat dua argumen tak terduga.

Tiga cara melepaskan pekerjaan

Opsi pertama adalah mengirim pembantu ke latar dari dalam hook: jalankan dengan setsid atau systemd-run --scope, tutup deskriptor warisan, dan keluar dengan nol seketika. Yang kedua adalah membiarkan hook menulis berkas status kecil dan membiarkan timer systemd atau unit path bertindak atasnya, yang menjaga hook tetap sepele dan menaruh kebijakan percobaan ulang di tempat yang ada lognya. Yang ketiga adalah membuang hook sepenuhnya dan memindahkan pekerjaan ke unit yang diurutkan setelah layanan VPN, yang merupakan jawaban tepat ketika pekerjaan itu sama sekali bukan per koneksi. Ketiganya berbagi satu aturan: hook harus kembali sebelum membutuhkan terowongan.

Apa pun yang Anda pilih, buat pembantu itu idempoten dan teramati. Dua pemanggilan yang tumpang tindih tidak boleh menjalankan tindakan tak dapat dibatalkan yang sama dua kali, dan pembantu yang gagal harus meninggalkan sesuatu yang bisa dibaca manusia.

Pisahkan kegagalan sandbox dari kegagalan siklus hidup

Ketika skrip berjalan dari prompt root dan gagal sebagai layanan, penyebabnya biasanya sandbox dan bukan jaringan. ProtectHome yang membatasi, ProtectSystem yang hanya-baca, atau direktori kerja yang tidak ada dapat membuat skrip atau datanya tak terjangkau, dan pada host SELinux berkas itu juga memerlukan konteks yang mengizinkan eksekusi. Baca unit dengan systemctl cat openvpn-server@server dan jurnal dengan journalctl -u openvpn-server@server -n 80, lalu cari kesalahan izin atau konteks alih-alih waktu tunggu koneksi. Menonaktifkan sandbox seharusnya menjadi langkah terakhir, bukan yang pertama.

Kegagalan siklus hidup terlihat berbeda: hook mulai, pembantu berjalan, dan soketnya memang belum ada. Tulis baris bertanda waktu dari hook itu sendiri, putuskan dan sambungkan lagi, lalu baca peristiwanya berurutan. Ketika pembantu benar-benar membutuhkan terowongan, biarkan ia menanyakan kesiapan alih-alih tidur selama periode tetap.

Tiga bidang membuat laporan berikutnya berguna: hook mana yang berjalan, akun mana yang dipakai, dan di mana ia berhenti. Tanpa itu, setiap penyelidikan berikutnya dimulai dari awal.

Artikel terkait