AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 457117
Accepted
Greg Nisbet
Greg Nisbet
Asked: 2018-07-19 20:10:25 +0800 CST2018-07-19 20:10:25 +0800 CST 2018-07-19 20:10:25 +0800 CST

如何取消当前进程的网络共享

  • 772

可以使用 以非 root 身份在没有网络访问权限的情况下运行新命令unshare -r -n,例如:

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

一个确实需要网络访问的命令将会失败。

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

我想知道是否可以通过写入一个神奇的文件/sys或类似的东西来删除当前进程的网络访问。

我希望能够做类似的事情

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

strace-ing的摘录unshare -r -n ls显示了unshare系统调用

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

这向我表明,从当前进程取消共享网络访问实际上是实现取消共享的唯一方法(即它不能作为参数传递给spawn或与其等价物)。它还表明从 shell 脚本取消共享将不起作用,除非 shell 已被专门扩展以暴露unshare.

linux networking
  • 1 1 个回答
  • 2033 Views

1 个回答

  • Voted
  1. Best Answer
    A.B
    2018-07-20T17:06:21+08:002018-07-20T17:06:21+08:00

    这可以通过gdb调试器来完成,并且如果可以附加到正在运行的进程(改变其可转储状态的程序,或者是 setgid 等不能附加到,除非从根目录)。

    一些可选文件可以帮助使用 gdb,例如 libc6 的调试符号,以及一些与 Linux 相关的包含文件,以便稍后获取一些符号的实际值(例如,在 Debian: (possibly)libc6-dbg和libc6-dev包linux-libc-dev中),但实际上曾经是“配方“已经制作好了,它们可能不再需要了。

    首先,除了正在做什么?没有这个,新用户将保持不变,甚至不能作为其初始用户编写:unshare() unshare -rnobody

    $ 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
    

    这将在以后使用。

    $ ip -4 -br a
    lo               UNKNOWN        127.0.0.1/8 
    eth0@if19        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
    $
    

    在另一个终端上:

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

    现在让我们调用第一个函数:

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

    好的,可能有一种方法可以让 gdb 知道它,但我不是专家:

    (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
    

    在修改后的过程中,可以验证eth0界面消失了:

    $ 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
    

    没有回头路:新的用户命名空间不能变回它的初始命名空间。如果进程以足够的权限运行(例如没有丢失功能的 root 或 SELinux),那么它是可能的(仅使用unshare(CLONE_NEWNET)/ setns(savedopenedfd))。

    当然,可以在文件中编写脚本,并更改​​任何允许的运行进程,或者让 shell 从 gdb 子进程中更改自身。的内容removenetwork.gdb,仅在使用pid:gid==更改进程时有效1000:1000:

    更新:为下面的系统调用添加了(近似)返回类型,这应该避免某些版本的 gdb 在非开发环境中抱怨:

    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
    

    例子:

    $ 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
    

    更新:如果根本不需要root,就像这个问题出现的那样,那么根本不需要映射到root。只需将出现的情况替换为write($XX, "0 1000 1", 8)(write($XX, "1000 1000 1", 11)对于uid:gid==1000:1000情况)。补充组仍然不可避免地丢失,但 uid/gid 不会改变(映射到自身)。

    • 2

相关问题

  • 使用键盘快捷键启动/停止 systemd 服务 [关闭]

  • 奇怪的路由器与centos 6一起工作[关闭]

  • 需要一些系统调用

  • astyle 不会更改源文件格式

  • 通过标签将根文件系统传递给linux内核

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve