【问题标题】:Check sender when listening to unix socket监听 unix 套接字时检查发件人
【发布时间】:2016-11-06 04:53:50
【问题描述】:

我有一个监听 unix 套接字的进程。 但是,在阅读之前,我想检查有关此传入消息的一些元数据,例如它的源进程(例如,我想删除来自不受信任的发件人的消息)。是否有任何系统调用可以检索此信息。

    if(listen(sock_fd, 10) != 0) {
        assert("listen failed");
    }

    while((conn_fd = accept(sock_fd,
                       (struct sockaddr *) &address,
                       &address_length)) != -1) {
        int nbytes = 0;
        static char buffer[PAYLOAD_SZ];
        nbytes = (int)read(conn_fd, buffer, PAYLOAD_SZ);

【问题讨论】:

  • 受信任基于什么?
  • 顺便说一句,它闻起来像 XY problem。那么你真正的目标是什么?你想达到什么目标?可能是第一次握手,连接接受后,你的解决方案?我的意思是客户端请求连接,并且基于某些东西,服务器接受或关闭连接。
  • @LPs,感谢您的评论。也许我的措辞不够清楚。我想允许根据预定义的列表读取来自特定进程(pids)的消息。因此,当我从套接字队列中弹出一条新消息时,我想验证它的来源。
  • 好吧,你怎么会有一个预定义列表的pid?这些进程是否修复了 PID?如果不是,正如我评论的那样,不能成为接受连接的解决方案,要求 PID 号和密码/哈希/验证连接,然后将特定连接添加到白名单?
  • @LPs,预定义的列表是固定的,它作为监听器进程的输入。

标签: c macos sockets unix-socket xnu


【解决方案1】:

经过一番研究,我找到了最适合我需求的答案。

使用 getsockopt 我能够获得对等 pid。

getsockopt(fd,SOCK_STREAM, LOCAL_PEERPID, &pid, &pid_len); 

使用此功能,我还能够收集对等凭据等。只需要验证发送此查询时对等方没有关闭套接字。

【讨论】:

    【解决方案2】:

    对于 linux 内核 3.3 及其更高版本,您可以使用命令行ss -xp

    ThisUnix & Linux 上的问题有很好的讨论和答案,可能有助于您理解。

    【讨论】:

    • 我忘了说我在 OSX 平台下工作,支持 unix 套接字,但没有 /proc 文件夹。我相信侦听器队列上的每个项目(最多有“积压”待处理项目)都具有描述编写此消息的原始进程的 pid 的元数据。我想知道是否有一个 C api 来检索这些信息......
    • 而且,ss 是否提供了任何连接进程的 PID?
    • 我不相信。如果连接队列已用尽,则连接请求可能会被拒绝。那么可能就没有办法获取到进程的PID了。
    【解决方案3】:

    getpeername() 可能就是您要找的。 Example code

    // assume s is a connected socket
    
    socklen_t len;
    struct sockaddr_storage addr;
    char ipstr[INET6_ADDRSTRLEN];
    int port;
    
    len = sizeof addr;
    getpeername(s, (struct sockaddr*)&addr, &len);
    
    // deal with both IPv4 and IPv6:
    if (addr.ss_family == AF_INET) {
        struct sockaddr_in *s = (struct sockaddr_in *)&addr;
        port = ntohs(s->sin_port);
        inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
    } else { // AF_INET6
        struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
        port = ntohs(s->sin6_port);
        inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
    }
    
    printf("Peer IP address: %s\n", ipstr);
    printf("Peer port      : %d\n", port);
    

    【讨论】:

    • 好吧,如果使用LOCALHOST (127.0.0.1)?
    • getpeername() 如果对等方位于同一主机上,则仍然有效,除非我错过了您所说的内容。
    • 我的意思是你不能识别同一台机器上的不同进程。
    • getpeername() 将获取对等方的端口号。如果您对lsof -i :### 执行 strace,它看起来会打开并读取所有 /proc//fdinfo 文件以找到匹配的端口号并打印 pid。可能对OP没用。也许推动 OP 使用 SSL 连接来验证客户端?对于正在处理套接字的人来说,这似乎是一大步。
    • OP 专门使用 Unix domain sockets,而不是 IP。
    猜你喜欢
    • 2011-08-11
    • 1970-01-01
    • 2014-07-18
    • 2014-11-12
    • 2018-07-13
    • 2013-01-17
    • 2011-02-15
    • 2011-11-26
    • 2013-03-29
    相关资源
    最近更新 更多