Saya memiliki program yang ingin saya uji dalam mode offline tanpa mematikan jaringan saya yang sebenarnya. Program ini masih perlu terhubung ke soket lokal, termasuk soket domain unix dan loopback. Ia juga perlu mendengarkan di loopback dan dapat dilihat oleh aplikasi lain.
Namun upaya untuk menyambung ke mesin jarak jauh akan gagal.
Saya ingin memiliki utilitas yang berfungsi seperti strace
/unshare
/sudo
dan cukup jalankan perintah dengan Internet (dan LAN) tersembunyi dan yang lainnya masih berfungsi:
$ offline my-program-to-test
Pertanyaan ini memiliki petunjuk jawabannya:Blokir akses jaringan dari suatu proses?
Ada beberapa saran di sana, seperti jalankan sebagai pengguna lain lalu manipulasi iptables, atau unshare -n
. Tetapi dalam kedua kasus saya tidak tahu mantra untuk mendapatkan soket domain unix dan loopback untuk dibagikan dengan sistem utama – jawaban atas pertanyaan itu hanya memberi tahu saya cara membatalkan berbagi seluruh jaringan.
Program yang saya uji masih perlu terhubung ke server X dan dbus saya dan bahkan dapat mendengarkan koneksi loopback dari aplikasi lain di sistem.
Idealnya saya ingin menghindari membuat chroot atau pengguna atau VM atau sejenisnya, karena itu sama menjengkelkannya dengan mencabut kabel jaringan. yaitu inti pertanyaannya adalah bagaimana saya bisa membuat ini sesederhana sudo
.
Saya ingin proses berjalan 100% secara normal kecuali bahwa panggilan jaringan yang menentukan alamat non-lokal akan gagal. Idealnya menjaga uid yang sama, homedir yang sama, pwd yang sama, semuanya sama kecuali … offline.
Saya menggunakan Fedora 18, jadi jawaban Linux yang tidak dapat dibawa-bawa baik-baik saja (diharapkan, bahkan).
Saya bahkan senang menyelesaikan ini dengan menulis program C, jika itu yang terlibat, jadi jawaban yang melibatkan penulisan C tidak masalah. Saya hanya tidak tahu syscalls apa yang perlu dibuat oleh program C untuk mencabut akses jaringan eksternal sambil menjaga jaringan lokal.
Pengembang mana pun yang mencoba mendukung "mode offline" mungkin akan menghargai utilitas ini!
Jawaban yang Diterima:
Jawaban tradisionalnya adalah menjalankan program sebagai pengguna lain dan menggunakan iptables -m owner
. Dengan begitu, konfigurasi jaringan dibagikan. Namun, dengan munculnya namespace, ada cara yang lebih mudah.
Dengan ruang nama, Anda membatalkan berbagi jaringan, lalu membuat tautan jaringan virtual jika Anda memerlukan akses jaringan terbatas.
Untuk berbagi soket domain unix, yang Anda butuhkan hanyalah memiliki kernel yang cukup baru, setelah patch 2010 ini, jadi 2.6.36 atau lebih tinggi (yang merupakan kasus pada semua distribusi saat ini pada saat penulisan kecuali RHEL/CentOS).
Jalankan program di namespace IP-nya sendiri. Sebelum memulai program, buat antarmuka ethernet virtual. Sepertinya tidak ada banyak dokumentasi; Saya menemukan mantra yang tepat di beberapa blog:
- Ruang Nama Linux di Arista
- Beberapa catatan tentang antarmuka veth oleh waldner
- Memperkenalkan Ruang Nama Jaringan Linux oleh Scott Lowe
Dalam cuplikan di bawah ini, saya menggunakan ns_exec
apakah pembungkus ini di sekitar setns
terdaftar di halaman manual untuk memunculkan sisi host tautan jaringan dari proses yang berjalan di namespace terbatas. Anda sebenarnya tidak memerlukan ini:Anda dapat mengatur sisi host tautan dari luar namespace yang dibatasi. Melakukannya dari dalam hanya memfasilitasi kontrol aliran, jika tidak, Anda memerlukan beberapa sinkronisasi untuk menyiapkan tautan setelah dibuat tetapi sebelum memulai program Anda.
unshare -n -- sh -c '
# Create a virtual ethernet interface called "confined",
# with the other end called "global" in the namespace of PID 1
ip link add confined type veth peer name global netns 1
# Bring up the confined end of the network link
ip addr add 172.16.0.2/30 dev confined
ip link set confined up
# Bring up the global end of the network link
ns_exec /proc/1/ns/net ifconfig global 172.16.0.1 netmask 255.255.255.252 up
# Execute the test program
exec sudo -E -u "$TARGET_USER" "$0" "[email protected]"
' /path/to/program --argument
Anda perlu melakukan semua ini sebagai root. Pengenalan ruang nama pengguna di kernel 3.8 dapat membuat ini dapat dilakukan tanpa izin khusus, kecuali menyiapkan ujung global tautan jaringan.
Saya tidak tahu cara berbagi localhost di antara dua ruang nama. Antarmuka ethernet virtual membuat jembatan point-to-point. Anda dapat menggunakan iptables
aturan penerusan untuk mengalihkan lalu lintas dari/ke lo
jika diinginkan.