V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
syam
V2EX  ›  C++

求助一个技术问题,关于网络端口和进程的关联的问题

  •  
  •   syam · 2023-11-29 15:29:26 +08:00 · 1616 次点击
    这是一个创建于 390 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求大概是个要对 linux 操作系统所有的进程和绑定的端口进行一个数据的结合,

    目的是将来用于限制单个进程绑定的端口,一种防护策略,开发语言是 c++,

    我的思路通过/proc/net/tcp 找到所有开启的端口,然后去找进程然后绑定,然后依次 udp 的

    但是目前根据网上找到的方案和 chatgpt 给的答案都无法完成绑定的这个步骤,

    绕来绕去都是围绕 netstat 和 ss 这几个命令输出信息。

    请教一下有什么办法能只用系统编程或者 proc 文件系统把信息绑定起来吗?

    16 条回复    2023-11-30 16:27:24 +08:00
    syam
        2
    syam  
    OP
       2023-11-29 15:45:24 +08:00
    @lsk569937453 我一开始是按着这个思路走的,我看的是我机器的 ssh 服务,后来发现存在一些 inode 不在 tcp 和 udp 的文件里面,多出来的几个文件有点不敢确定是不是错过的什么东西
    mjikop1231
        3
    mjikop1231  
       2023-11-29 15:45:27 +08:00
    `/proc/<pid>/net/tcp`
    `/proc/<pid>/net/tcp`
    `/proc/<pid>/net/tcp`
    mjikop1231
        4
    mjikop1231  
       2023-11-29 15:46:10 +08:00
    #3
    敲。。
    tcp/tcp6/udp/udp6 里面存 listening 信息
    syam
        5
    syam  
    OP
       2023-11-29 15:48:58 +08:00
    @mjikop1231 不行的你这个文件本质还是/proc/net/tcp 的内容 一模一样
    mjikop1231
        6
    mjikop1231  
       2023-11-29 15:56:33 +08:00
    关于#2 @syam 你可以先举个例子
    syam
        7
    syam  
    OP
       2023-11-29 16:26:38 +08:00
    @mjikop1231 我是拿 ssh 服务的进程看的 会明显多几个,但是实际我的机器没有产生任何的 ssh 连接
    barathrum
        8
    barathrum  
       2023-11-29 16:41:36 +08:00
    说实话你的 目的 这一块我没理解到位,是为了安全?还是资源限制?理论上来说可以学习 selinux 管理权限,学习 ulimit 管理资源。
    syam
        9
    syam  
    OP
       2023-11-29 16:45:27 +08:00
    @barathrum 简单理解就是我要知道每个进程绑定了那些端口 那个端口绑定在那个进程上
    kuanat
        10
    kuanat  
       2023-11-29 18:17:31 +08:00
    我觉得这个事情的思路有点跑偏了,Linux 内核网络栈的抽象还是比较难的。

    首先“端口”是个协议层面的概念,假如 tcp 只有二元组(源 IP ,目标 IP )局限就太大了。

    所以内核网络栈不会对“端口”做抽象的,因为没有必要。有必要的是对四元组(源 IP ,源端口,目标 IP ,目标端口)做抽象,这个完整的四元组可以唯一确定一个 tcp 连接。这个抽象在 Linux 里就是 socket 。

    因此内核里也就不会有端口号的映射关系,如果你去看 netstat/ss 的代码,我猜测都是曲线救国。

    由于网络栈是内核实现,为了方便用户态的程序使用,就通过 socketfs 抽象成一般 fd ,这样应用程序只需要确定 socket fd 就能直接在连接层面上完成网络功能了。

    前面铺垫这么多,就是为了引出结论,你这个问题的本质是“如何确定 socket fd 和 pid 的映射关系”。

    问题在于 fd 这个东西是可以复制或者转移的,于是最终还要回到 /proc/*/fd/* 去遍历才能确认。


    PS

    “限制进程可绑定端口”的标准操作是 ACL 机制,selinux 比较方便。自己造这个轮子非常不理智。
    gulucn
        11
    gulucn  
       2023-11-29 18:25:55 +08:00
    可以考虑 systemtap 的方式去进行监控,chatgpt 关于 systemtap 的例子
    # socket_trace.stp

    global sockets

    probe begin {
    print("Tracing sockets...\n")
    }

    probe syscall.socket {
    pid = pid()
    sfd = $return
    sockets[pid, sfd] = 1
    }

    probe syscall.close {
    pid = pid()
    sfd = $fd
    if (exists(sockets[pid, sfd])) {
    delete sockets[pid, sfd]
    printf("Process %d closed socket %d\n", pid, sfd)
    }
    }

    然后再考虑一下怎么把 socket id 跟端口关联就可以了
    idontnowhat2say
        12
    idontnowhat2say  
       2023-11-29 18:43:13 +08:00
    你的需求如果没法直接调用 ss 或 lsof 命令输出处理的话,要不去看看他们代码怎么实现的?另外感觉你开发的这个东西这个很像 HIDS ,可以找找开源的 HIDS 看他们怎么写的
    ttvast
        13
    ttvast  
       2023-11-29 18:49:30 +08:00 via iPhone
    netstat -anp
    syam
        14
    syam  
    OP
       2023-11-30 09:32:20 +08:00
    @kuanat 是的 我看过 lsof 的实现命令了就是遍历出来的,之所以不用 selinux 是因为 我分到的模块只是监控的这一部分 这个是参与的一个社区开源项目
    julyclyde
        15
    julyclyde  
       2023-11-30 11:51:44 +08:00
    首先,你这个需求是错的
    这个需求用 selinux 或者 appArmor 就可以实现,没必要你自己在额外实现一遍
    先不说你的开发质量怎么样,就单凭,人家是内核,你只是应用层,就差很多了

    其次,不知道你说的所谓绑定是什么
    是通过端口倒查 pid ?还是网络编程里所谓 bind/listen 那个 bind ?
    不要在自己不懂的情况下乱发明新的术语
    jones2000
        16
    jones2000  
       2023-11-30 16:27:24 +08:00
    用钩子把 bind 函数截获。 其他程序调用 bind 你记录下不就可以了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1371 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 17:19 · PVG 01:19 · LAX 09:19 · JFK 12:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.