Sistemde tam güvenmediğim betikleri test veya hata ayıklamam gerektiği sık olur — belki bir kamusal repodan, bir同事的 gist'inden veya sorun giderme sırasında bulduğum bir şeyden. Üretim ortamında ya da hatta iş istasyonunda doğrudan çalıştırmak riskli. İşte burada systemd-nspawn ve seccomp profillerinin birleşimi işe yarar. Bu, işlemin yapabileceği sistem çağrılarını kısıtlayarak güvenilmeyen kodu sanal makine başlatmadan etkili bir şekilde sandbox'lemeyi sağlayan hafif, izole bir ortam oluşturmama olanak tanır.
systemd-nspawn ile Sandboxing Neden Kullanılır
systemd-nspawn, konteynerler veya sanal makineler kıyasla hafiftir. Mevcut çekirdek isim alanlarını kullanır ancak sistemd yöneticisi üzerinden sıkı kontrol sağlar. Minimal overhead ile izole bir dosya sisteminde bir kabuk çalıştırabilir veya komut çalıştırabilirim. Seccomp (güvenli işlem modu) filtresiyle birleştirildiğinde, ptrace, mount veya fork/clone kombinasyonu gibi ayrıcalık yükseltmesi veya konteyner kaçışı yol açabilecek tehlikeli sistem çağrılarını engelleyebilirim.
İş akışımda, /var/lib/container/ altında minimal bir Debian veya Ubuntu temel imajı tutar ve bu imajı geçici test ortamları için kök dosya sistemi olarak kullanırım. Böylece ana sistemimi kirletmez ve sadece dizini silerek her şeyi sıfırlayabilirim.
Temel İmagin Oluşturulması
Öncelikle minimal bir dosya sistemi oluştururum. Debian tabanlı sistemler için debootstrap kullanırım:
sudo debootstrap --arch=amd64 bookworm /var/lib/container/testbox http://deb.debian.org/debian
Tamamlandıktan sonra, kök şifresini ayarlamak veya bir kullanıcı eklemek için chroot'a girebilirim:
sudo chroot /var/lib/container/testbox
passwd
adduser testuser
exit
Artık önyüklenebilir-ish bir dizin ağacım var. Bir kabuk ve temel komutları çalıştırmak için tam bir init sistemine ihtiyacım yok.
Özel seccomp Profili Oluşturma
seccomp, çekirdek seviyesinde sistem çağrılarını filtreler. JSON formatında bir politika tanımlarım ve bu política izin verilen, engellenen veya bir hata tetikleyen çağrıları belirtirim. Güvenilmeyen betikleri test ederken, strict bir varsayılanla başlarım: her şeyi engellerim, ardından sadece gerekenleri izne veririm.
Basit Bash veya Python betiklerini çalıştırmak için kullandığım minimal profil şu şekildedir:
{
"defaultAction": "SCMP_ACT_ERRNO",
"archMap": [
{"architecture": "SCMP_ARCH_X86_64", "subArchitectures": ["SCMP_ARCH_X86", "SCMP_ARCH_X32"]}
],
"syscalls": [
{"name": "read", "action": "SCMP_ACT_ALLOW"},
{"name": "write", "action": "SCMP_ACT_ALLOW"},
{"name": "openat", "action": "SCMP_ACT_ALLOW"},
{"name": "close", "action": "SCMP_ACT_ALLOW"},
{"name": "fstat", "action": "SCMP_ACT_ALLOW"},
{"name": "mmap", "action": "SCMP_ACT_ALLOW"},
{"name": "mprotect", "action": "SCMP_ACT_ALLOW"},
{"name": "munmap", "action": "SCMP_ACT_ALLOW"},
{"name": "brk", "action": "SCMP_ACT_ALLOW"},
{"name": "exit", "action": "SCMP_ACT_ALLOW"},
{"name": "exit_group", "action": "SCMP_ACT_ALLOW"},
{"name": "rt_sigaction", "action": "SCMP_ACT_ALLOW"},
{"name": "rt_sigprocmask", "action": "SCMP_ACT_ALLOW"},
{"name": "ioctl", "action": "SCMP_ACT_ALLOW"},
{"name": "getdents64", "action": "SCMP_ACT_ALLOW"},
{"name": "getrandom", "action": "SCMP_ACT_ALLOW"}
]
}
Bu profili /etc/systemd/nspawn/seccomp-lockdown.json olarak kaydederim. defaultActionnin errno olarak ayarlanması, açıkça izin verilen olmayan tüm sistem çağrılarının bir hata (genellikle EPERM) döndürmesini ve süreçte güvenli olmayan bir şey yapmaya çalıştığında sonlanmasını sağlar.
Sandbox'ı Başlatma
Şimdi seccomp filtresi uygulanmış bir ad alanı içinde komut çalıştırabilirim:
sudo systemd-nspawn \
--directory=/var/lib/container/testbox \
--bind=/home/furkan/test-scripts:/mnt/tests \
--seccomp-policy=/etc/systemd/nspawn/seccomp-lockdown.json \
/usr/bin/bash
Bu komut, test betiklerimi /mnt/tests'te bağlayarak konteyner içinde bir kabuk açar. --bind baydı varsayılan olarak okuma-yazma olur; ancak sadece betikleri okumam gerekiyorsa genellikle --bind-ro kullanırım.
Tek bir betik çalıştırmak ve çıkış yapmak istersem şöyle yaparım:
sudo systemd-nspawn \
--directory=/var/lib/container/testbox \
--bind-ro=/home/furkan/test-scripts/script.sh:/mnt/script.sh \
--seccomp-policy=/etc/systemd/nspawn/seccomp-lockdown.json \
/bin/bash /mnt/script.sh
Bu Profil Ne Engeller (Ve Ne Engellemez)
Bu profil ile yaygın kaçış vektörleri engellenir:
ptrace— diğer süreçlere hata ayıklama yapma veya bağnma işlemini önlerCLONE_NEWNSveyaCLONE_NEWUSERileclone— isim alanı oluşturmayı durdururmount,umount2— dosya sistemi müdahalesini engellerkexec_load,init_module— çekirdek kodu yüklemeyi önleropenatile tehlikeli yollar (yol filtrelemesiyle birlikteyse, seccomp tek başına yol filtrelemesi yapmaz)
Ancak seccomp varsayılan olarak bağımsız değişkenleri filtrelemez (yeni SCMP_CMP kurallarıyla hariç). Örneğin, openat sadece /tmp için izin vermek gibi bir şey yapamam. Daha sıkı kontrol için bu profili isim alanları, kullanıcı isim alanları veya Firejail gibi bir container çalışma zamanıyla birleştiririm. Ancak sadece dosyaları okumak, hesaplama yapmak ve çıktı yazmak gereken betikler için hızlı testte bu yeterli olur.
Pratik İpuçları ve Gotchas
- Seccomp profilinizi önce güvenli bilinen bir programla test edin.
strace -fkullanarak yaptığı sistem çağrılarını görün ve profili ona göre ayarlayın. - Bir betik hemen "Operation not permitted" ile başarısız olursa, seccomp denetim mesajları için
/var/log/syslogveyajournalctla bakın (denetim etkinse). execveizni vermek gerekmedikçe izin vermeyin — bu, ikili zincirleme kapısını açar. İzin vermek zorundaysanız, bağ mounts veexecvebağımsız değişkeni filtrelemesi üzerinden spesifik çalıştırılabilir dosyaları izin listesine alın (daha yeni çekirdeklerde mevcut).- Temizliği unutmayın: testten sonra konteyner dizinini siler veya yeniden kullanım için bir anlık görüntü alırım.
Daha Fazla İzolasyon Gerektiğinde Ne Yapmalıyım
Daha derin izolasyon gerekiyorsa — ağ erişimi kontrolü, kullanıcı ID eşleme veya çok katmanlı savunma — Firejail veya Podman/Docker ile tam OCI konteyneri kullanırım. Ancak hızlı ve minimum kurulum gerektiren ad hoc komut satırı testleri için systemd-nspawn ve seccomp benim başıma gelen çözümür.
[systemd Slice kaynak izolasyonu](https://furkanikkan.com/urun/systemd-slice-ile-bellek-io-sinirlari-kaynak-izolasyon-kilavuzu-112) hakkında önceki yazımda da belirttiğim gibi, burada da aynı prensipler geçerli: tehdit modeline uygun doğru aracı kullanın. Burada seccomp performansla ilgili değil, güvensiz kod için saldırı yüzeyini sıfıra yakın levelsine indirmekle ilgilidir.
Düzenli olarak üçüncü taraf betiklerle çalışıyorsanız, bu yaklaşım sisteminizi tehlikeye atmadan onları test etmek için tekrarlanabilir, denetlenebilir bir yol sağlar. Doğru kod incelemesi veya CI'de sandboxing'in yerini tutmaz, ama ops katmanındaki güvenli bir ağdır olarak iş görür.
Kapak görseli: Unknown · CC0 (Openverse / kamu malı) · https://www.rawpixel.com/image/5904551/photo-image-background-public-domain-technology
