Perintah untuk menjalankan proses anak "offline" (tidak ada jaringan eksternal) di Linux

15

Saya memiliki program yang ingin saya uji dalam mode offline tanpa mencatat jaringan saya yang sebenarnya. Program ini masih perlu terhubung ke soket lokal, termasuk soket domain unix dan loopback. Itu juga perlu mendengarkan pada loopback dan terlihat oleh aplikasi lain.

Tetapi upaya untuk terhubung ke mesin jarak jauh harus gagal.

Saya ingin memiliki utilitas yang berfungsi seperti strace/ unshare/ sudodan hanya menjalankan perintah dengan Internet (dan LAN) disembunyikan dan semuanya masih berfungsi:

$ offline my-program-to-test

Pertanyaan ini memiliki petunjuk pada jawabannya: Memblokir akses jaringan dari suatu proses?

Ada beberapa saran di sana, seperti dijalankan sebagai pengguna lain kemudian memanipulasi iptables, atau unshare -n. Tetapi dalam kedua kasus saya tidak tahu mantera untuk mendapatkan soket domain unix dan loopback untuk dibagikan dengan sistem utama - jawaban untuk pertanyaan itu hanya memberi tahu saya cara untuk tidak berbagi seluruh jaringan.

Program yang saya uji masih perlu terhubung ke X server dan dbus saya dan bahkan dapat mendengarkan di loopback untuk koneksi dari aplikasi lain pada sistem.

Idealnya saya ingin menghindari membuat chroot atau pengguna atau VM atau sejenisnya, karena itu sama menjengkelkannya seperti mencabut kabel jaringan. yaitu titik pertanyaannya adalah bagaimana saya bisa membuat ini sesederhana a sudo.

Saya suka proses menjalankan 100% secara normal kecuali bahwa panggilan jaringan 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 diputar baik-baik saja (diharapkan, bahkan).

Saya bahkan senang menyelesaikan ini dengan menulis program C, jika itu yang terlibat, jadi jawaban yang melibatkan penulisan C baik-baik saja. 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!

Havoc P
sumber

Jawaban:

9

Jawaban tradisional adalah menjalankan program sebagai pengguna lain dan digunakan iptables -m owner. Dengan begitu, konfigurasi jaringan dibagi. Namun, dengan munculnya ruang nama, ada cara yang lebih mudah.

Dengan ruang nama, Anda membatalkan tautan jaringan, lalu membuat tautan jaringan virtual jika Anda memerlukan akses jaringan terbatas.

Untuk berbagi soket domain unix, yang Anda butuhkan adalah memiliki kernel yang cukup baru, setelah tambalan 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 banyak dokumentasi; Saya menemukan mantra yang tepat di beberapa blog:

Dalam potongan di bawah ini, saya menggunakan ns_execadalah wrapper ini sekitarsetns tercantum dalam halaman manual untuk memunculkan sisi host dari link jaringan dari proses yang berjalan di namespace terbatas. Anda sebenarnya tidak memerlukan ini: Anda dapat mengatur sisi host tautan dari luar namespace terbatas. Melakukannya dari dalam hanya memfasilitasi kontrol aliran, jika tidak, Anda perlu sinkronisasi untuk mengatur 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" "$@"
' /path/to/program --argument

Anda perlu melakukan semua ini sebagai root. The pengenalan ruang nama pengguna di kernel 3.8 dapat membuat ini bisa dilakukan tanpa izin khusus, kecuali menyiapkan akhir global link jaringan.

Saya tidak tahu bagaimana cara berbagi localhost antara dua ruang nama. Antarmuka ethernet virtual membuat jembatan point-to-point. Anda dapat menggunakan iptablesaturan penerusan untuk mengalihkan lalu lintas dari / ke lojika diinginkan.

Gilles 'SO- berhenti menjadi jahat'
sumber
Info tambahan yang bagus, terima kasih. Saya pikir veth memberi saya tautan ke "di luar" namespace tetapi namespace baru saya masih berjumlah node jaringan yang terpisah, daripada node jaringan yang sama minus antarmuka non-lokal. Implikasinya adalah (?): Unix domain / soket abstrak masih akan gagal, dan loopback dapat diteruskan melalui iptables, tetapi penerusan tidak mencapai pembagian - yaitu, ruang nama asli dan terbatas mungkin mendengarkan pada loopback dan kedua set (secara dinamis) -berubah) port harus terlihat di kedua namespaces ... mulai menebak apa yang saya inginkan tidak mungkin di sini: - /
Havoc P
1

Ini juga bisa dicapai dengan cgroup yang cocok dengan aturan iptables. Saya menulis alat untuk abstrak langkah-langkahnya. Meskipun memerlukan izin root untuk pengaturan awal dan sebaliknya merupakan setary binary, saya pikir ini menawarkan cara yang cukup mudah untuk menangani masalah dalam pertanyaan. Ini membutuhkan versi iptables yang cukup baru dan modul netfilter yang tepat tersedia.

https://github.com/quitesimpleorg/qsni

crtxcr
sumber
0

/ !! \ Ini mungkin bukan jawaban yang valid karena ini akan membawa semua traffic Anda turun, bukan hanya traffic satu pid saja.

Saya belum menggunakannya, tapi saya pikir Anda berpotensi menggunakan Comcast:

https://github.com/tylertreat/Comcast

set ke paket loss 100%

Sekali lagi, saya belum menguji ini, tetapi secara teoritis, dimodifikasi dari readme mereka yang dapat Anda lakukan:


Linux

Di Linux, Anda dapat menggunakan iptablesuntuk menjatuhkan paket yang masuk dan keluar.

$ iptables -A INPUT -m statistic --mode random --probability 1 -j DROP
$ iptables -A OUTPUT -m statistic --mode random --probability 1 -j DROP

Atau, Anda dapat menggunakan tcyang mendukung beberapa opsi tambahan.

$ tc qdisc change dev eth0 root netem reorder 0 duplicate 0 corrupt 1

Untuk mengatur ulang:

$ tc qdisc del dev eth0 root netem
ThorSummoner
sumber