GNU/Linux >> Belajar Linux >  >> Linux

Linux – Bagaimana Cara Berhenti Berbagi Jaringan Untuk Proses Saat Ini?

Perintah baru dapat dijalankan tanpa akses jaringan sebagai non-root menggunakan unshare -r -n , misalnya:

$ unshare -r -n ls
a.txt  b.txt

Perintah yang memang membutuhkan akses jaringan dapat diprediksi akan gagal.

$ unshare -r -n curl unix.stackexchange.com
curl: (6) Could not resolve host: unix.stackexchange.com

Saya bertanya-tanya apakah mungkin untuk menghapus akses jaringan untuk proses saat ini, berpotensi dengan menulis ke file ajaib di /sys atau yang serupa.

Saya ingin dapat melakukan sesuatu seperti

$ /bin/sh -c 'echo 1 > /sys/unsharethis; curl unix.stackexchange.com'

Kutipan dari strace -ing unshare -r -n ls menunjukkan unshare panggilan sistem

open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=4759040, ...}) = 0
mmap(NULL, 4759040, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f7ec6968000
close(3)                                = 0
unshare(CLONE_NEWUSER|CLONE_NEWNET)     = 0
open("/proc/self/setgroups", O_WRONLY)  = 3
write(3, "deny", 4)                     = 4

Yang menunjukkan kepada saya bahwa tidak membagikan akses jaringan dari proses saat ini sebenarnya adalah satu-satunya cara untuk mencapai unsharing (yaitu tidak dapat diteruskan sebagai argumen ke spawn atau yang setara dengannya). Ini juga menunjukkan bahwa berhenti berbagi dari skrip shell tidak akan berfungsi kecuali jika shell telah secara khusus diperluas untuk mengekspos pembungkus di sekitar unshare .

Jawaban yang Diterima:

Hal ini dapat dilakukan, semacam, dengan gdb debugger, dan jika proses yang berjalan dapat dilampirkan (program yang mengubah status dumpable-nya, atau setgid, dll. tidak dapat dilampirkan, kecuali dari root).

Beberapa file opsional dapat membantu menggunakan gdb seperti simbol debug untuk libc6, dan beberapa file terkait Linux menyertakan file untuk mendapatkan nilai sebenarnya dari beberapa simbol nanti (misalnya pada Debian:(mungkin) libc6-dbg , libc6-dev dan linux-libc-dev paket), tetapi sebenarnya setelah "resep" dibuat, mereka mungkin tidak diperlukan lagi.

Pertama apa yang lebih dari unshare() unshare -r sedang melakukan? Tanpa ini, pengguna baru tetap berada di nobody dan bahkan tidak bisa menulis sebagai pengguna awalnya:

$ id
uid=1000(user) gid=1000(user) groups=1000(user)
$ strace unshare -r -n /bin/sleep 1 2>&1 |sed -n '/^unshare/,/^execve/p'
unshare(CLONE_NEWNET|CLONE_NEWUSER)     = 0
open("/proc/self/setgroups", O_WRONLY)  = 3
write(3, "deny", 4)                     = 4
close(3)                                = 0
open("/proc/self/uid_map", O_WRONLY)    = 3
write(3, "0 1000 1", 8)                 = 8
close(3)                                = 0
open("/proc/self/gid_map", O_WRONLY)    = 3
write(3, "0 1000 1", 8)                 = 8
close(3)                                = 0
execve("/bin/sleep", ["/bin/sleep", "1"], [/* 18 vars */]) = 0

Itu akan digunakan nanti.

$ ip -4 -br a
lo               UNKNOWN        127.0.0.1/8 
[email protected]        UP             10.0.3.66/24 
$ ping -c1 10.0.3.1
PING 10.0.3.1 (10.0.3.1) 56(84) bytes of data.
64 bytes from 10.0.3.1: icmp_seq=1 ttl=64 time=0.167 ms

--- 10.0.3.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms

rtt min/avg/max/mdev = 0.167/0.167/0.167/0.000 ms
$ id
uid=1000(user) gid=1000(user) groups=1000(user)
$ echo $$
338
$

Di terminal lain:

$ gdb --pid=338
Reading symbols from /bin/bash...(no debugging symbols found)...done.
Reading symbols from /lib/x86_64-linux-gnu/libtinfo.so.5...(no debugging symbols found)...done.
Reading symbols from /lib/x86_64-linux-gnu/libdl.so.2...Reading symbols from /usr/lib/debug/.build-id/b8/95f0831f623c5f23603401d4069f9f94c24761.debug...done.
done.
Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...Reading symbols from /usr/lib/debug/.build-id/aa/889e26a70f98fa8d230d088f7cc5bf43573163.debug...done.
done.

[…]

(gdb)

Sekarang mari kita panggil fungsi pertama:

(gdb) call unshare(CLONE_NEWNET|CLONE_NEWUSER)
No symbol "CLONE_NEWNET" in current context.

Oke, mungkin ada metode agar gdb mengetahuinya, tapi saya bukan seorang guru:

(gdb) !
$ grep CLONE_NEW /usr/include/linux/sched.h # man 2 unshare
#define CLONE_NEWNS 0x00020000  /* New mount namespace group */
#define CLONE_NEWCGROUP     0x02000000  /* New cgroup namespace */
#define CLONE_NEWUTS        0x04000000  /* New utsname namespace */
#define CLONE_NEWIPC        0x08000000  /* New ipc namespace */
#define CLONE_NEWUSER       0x10000000  /* New user namespace */
#define CLONE_NEWPID        0x20000000  /* New pid namespace */
#define CLONE_NEWNET        0x40000000  /* New network namespace */
$ find /usr/include/ -name fcntl.h |xargs grep O_WRONLY # man 2 open
/usr/include/asm-generic/fcntl.h:#define O_WRONLY   00000001
$ exit
exit
(gdb) call unshare(0x50000000)
$1 = 0
(gdb) call open("/proc/self/setgroups", 1)
$2 = 3
(gdb) call write($2,"deny",4)
$3 = 4
(gdb) call close($2)
$4 = 0
(gdb) call open("/proc/self/uid_map", 1)
$5 = 3
(gdb) call write($5, "0 1000 1", 8)
$6 = 8
(gdb) call close($5)
$7 = 0
(gdb) call open("/proc/self/gid_map", 1)
$8 = 3
(gdb) call write($8, "0 1000 1", 8)
$9 = 8
(gdb) call close($8)
$10 = 0
(gdb) quit
A debugging session is active.

    Inferior 1 [process 338] will be detached.

Quit anyway? (y or n) y
Detaching from program: /bin/bash, process 338

Pada proses yang diubah, seseorang dapat memverifikasi eth0 antarmuka menghilang:

$ ip -br a
lo               DOWN           127.0.0.1/8 
$ echo $$
338
$ id
uid=0(root) gid=0(root) groupes=0(root)
$ touch /
touch: setting times of '/': Permission denied
$ touch ~/test1
$ ls ~/test1
/home/user/test1
$ ping 10.0.3.1
connect: Network is unreachable

Tidak ada jalan untuk kembali:ruang nama pengguna baru tidak dapat diubah kembali ke ruang nama awalnya. Jika proses berjalan dengan hak yang cukup (misalnya root tanpa kehilangan kemampuan atau SELinux) maka itu akan mungkin (hanya menggunakan unshare(CLONE_NEWNET) / setns(savedopenedfd) ).

Terkait:Bagaimana cara mengatur default desktop untuk pengguna baru ??

Tentu saja dimungkinkan untuk membuat skrip dalam file, dan mengubah proses berjalan yang diizinkan, atau meminta shell mengubah dirinya sendiri dari subproses gdb. Isi removenetwork.gdb , valid di sini hanya untuk mengubah proses dengan pid:gid ==1000:1000 :

PEMBARUAN:menambahkan (perkiraan) jenis pengembalian untuk syscalls di bawah ini, ini harus menghindari beberapa versi gdb untuk dikeluhkan di lingkungan non-dev:

call (int)unshare(0x50000000)
call (int)open("/proc/self/setgroups", 1)
call (long)write($2,"deny",4)
call (int)close($2)
call (int)open("/proc/self/uid_map", 1)
call (long)write($5, "0 1000 1", 8)
call (int)close($5)
call (int)open("/proc/self/gid_map", 1)
call (long)write($8, "0 1000 1", 8)
call (int)close($8)
quit

Contoh:

$ sh -c 'id; gdb --pid=$$ < removenetwork.gdb >/dev/null 2>&1; id; curl unix.stackexchange.com'
uid=1000(user) gid=1000(user) groups=1000(user)
uid=0(root) gid=0(root) groups=0(root)
curl: (6) Could not resolve host: unix.stackexchange.com

PERBARUI :jika root tidak diperlukan sama sekali, seperti yang muncul untuk Pertanyaan ini, maka tidak perlu memetakan ke root sama sekali. Cukup ganti kemunculan write($XX, "0 1000 1", 8) dengan write($XX, "1000 1000 1", 11) (untuk uid:gid ==1000:1000 kasus). Grup tambahan masih tetap hilang, tetapi uid/gid tidak berubah (dipetakan ke dirinya sendiri).


Linux
  1. Cara mematikan proses zombie di Linux

  2. Linux – Blokir Akses Jaringan Suatu Proses?

  3. Cara Menginstal dan Mengonfigurasi Monit di Linux untuk Pemantauan Proses

  1. 8 perintah Linux untuk manajemen proses yang efektif

  2. Cara Mengatur Ikatan Etherchannel Linux untuk Antarmuka Jaringan HA

  3. Bagaimana cara menonaktifkan pembuatan soket untuk proses Linux, untuk kotak pasir?

  1. 10 Perintah Linux Untuk Diagnostik Jaringan

  2. Cara Membatasi Penggunaan CPU Suatu Proses Di Linux

  3. Cara menginstal vtop di Linux