GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Linux – Wie kann ich die Netzwerkfreigabe für den aktuellen Prozess aufheben?

Es ist möglich, einen neuen Befehl ohne Netzwerkzugriff als Nicht-Root mit unshare -r -n auszuführen , zum Beispiel:

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

Ein Befehl, der Netzwerkzugriff erfordert, wird vorhersehbar fehlschlagen.

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

Ich frage mich, ob es möglich ist, den Netzwerkzugriff für den aktuellen Prozess zu entfernen, möglicherweise durch Schreiben in eine magische Datei in /sys oder ähnliches.

Ich würde gerne so etwas tun können wie

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

Ein Auszug aus strace -ing unshare -r -n ls zeigt den unshare Systemaufruf

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

Was mir nahelegt, dass das Aufheben der Freigabe des Netzwerkzugriffs aus dem aktuellen Prozess tatsächlich die einzige Möglichkeit ist, die Aufhebung der Freigabe zu erreichen (d. h. es kann nicht als Argument an spawn übergeben werden oder ein Äquivalent davon). Es deutet auch darauf hin, dass das Aufheben der Freigabe aus einem Shell-Skript nicht funktionieren würde, es sei denn, die Shell wurde speziell erweitert, um einen Wrapper um unshare bereitzustellen .

Akzeptierte Antwort:

Dies kann sozusagen mit dem gdb erfolgen Debugger, und ob der laufende Prozess angehängt werden kann (Programme, die ihren Dumpable-Status ändern oder setgid sind usw., können nicht angehängt werden, es sei denn von root).

Einige optionale Dateien können helfen, gdb wie Debug-Symbole für libc6 zu verwenden, und einige Linux-bezogene Include-Dateien, um später die tatsächlichen Werte einiger Symbole zu erhalten (z. B. unter Debian:(möglicherweise) libc6-dbg). , libc6-dev und linux-libc-dev Pakete), aber sobald das „Rezept“ erstellt ist, werden sie wahrscheinlich nicht mehr benötigt.

Zuerst was mehr als unshare() unshare -r macht gerade? Ohne dies bleibt der neue Benutzer bei nobody und kann nicht einmal als Erstbenutzer schreiben:

$ 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

Das wird später verwendet.

$ 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
$

Auf einem anderen Terminal:

$ 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)

Rufen wir nun die erste Funktion auf:

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

Ok, es könnte eine Methode geben, gdb es wissen zu lassen, aber ich bin kein 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

Auf dem geänderten Prozess kann man den eth0 überprüfen Schnittstelle verschwunden:

$ 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

Es gibt kein Zurück:Der neue Benutzernamensraum kann nicht zu seinem ursprünglichen Namensraum zurückkehren. Wenn der Prozess mit genügend Privilegien läuft (z. B. root ohne verlorene Fähigkeiten oder SELinux), dann wäre es möglich (nur mit unshare(CLONE_NEWNET)). / setns(savedopenedfd) ).

Verwandte:Wie lege ich Desktop-Standardeinstellungen für neue Benutzer fest?

Natürlich ist es möglich, es in einer Datei zu skripten und jeden erlaubten laufenden Prozess zu ändern oder die Shell sich selbst von einem gdb-Unterprozess ändern zu lassen. Inhalt von removenetwork.gdb , hier nur gültig, um einen Prozess mit pid:gid zu ändern ==1000:1000 :

UPDATE:Der (ungefähre) Rückgabetyp für die folgenden Systemaufrufe wurde hinzugefügt, dies sollte verhindern, dass sich einige Versionen von gdb in Nicht-Entwicklungsumgebungen beschweren:

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

Beispiel:

$ 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

AKTUALISIEREN :Wenn root überhaupt nicht benötigt wird, wie es für diese Frage erscheint, ist es überhaupt nicht erforderlich, root zuzuordnen. Ersetzen Sie einfach Vorkommen von write($XX, "0 1000 1", 8) mit write($XX, "1000 1000 1", 11) (für die uid:gid ==1000:1000 Fall). Ergänzende Gruppen gehen immer noch unvermeidlich verloren, aber die uid/gid ändert sich nicht (wird auf sich selbst abgebildet).


Linux
  1. So beenden Sie einen Zombie-Prozess unter Linux

  2. 8 Linux-Befehle für effektives Prozessmanagement

  3. So begrenzen Sie die CPU-Auslastung eines Prozesses in Linux

  4. Linux – Netzwerkzugriff eines Prozesses blockieren?

  5. So überprüfen Sie die Heap-Größe für einen Prozess unter Linux

So beenden Sie Zombie-Prozesse in Linux

So teilen Sie den Drucker im Netzwerk unter Linux

So finden Sie verfügbare Netzwerkschnittstellen unter Linux

Wie man einen Prozess unter Linux beendet

So fügen Sie eine Route unter Linux hinzu

So legen Sie ein externes Netzwerk für Container in Linux-Containern (LXC) fest