加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

套接字 – SO_REUSEADDR和AF_UNIX

发布时间:2020-12-15 18:55:51 所属栏目:安全 来源:网络整理
导读:事实 在POSIX文档中,我看不到有任何东西阻止对UNIX域套接字使用AF_UNIX的SO_REUSEADDR套接字选项. 但是,如果套接字节点已经存在,并且似乎被忽略,并且似乎需要在调用bind之前首先取消链接文件系统上的套接字节点,总之,它不重用地址.网络上有很多关于这个问题
事实

在POSIX文档中,我看不到有任何东西阻止对UNIX域套接字使用AF_UNIX的SO_REUSEADDR套接字选项.

但是,如果套接字节点已经存在,并且似乎被忽略,并且似乎需要在调用bind之前首先取消链接文件系统上的套接字节点,总之,它不重用地址.网络上有很多关于这个问题的线程,没有一个解决方案.

问题

我不会坚持,如果它不起作用,它不起作用(至少在BSD和Linux系统上似乎是一样的),只是有一个问题:这是正常的行为吗?有没有任何指针建议它应该被支持,或者相反,任何指针,建议它不应该?还是这个未指定的?注意问题是在POSIX上下文中提出的,而不是在任何特定的平台上下文中.

我欢迎POSIX参考.

额外:一个小小的片段,不会盲目地解除谁知道什么

我已经看到网络上的一些线程,建议在绑定之前取消链接预期名称的任何节点.我觉得这是不安全的,在这种情况下,应该只解除一个已经是套接字节点的节点:ex.取消链接名为mysocket的文本文件可能会重新创建相同名称的套接字节点.为此,这里是一个很小的片段:

/* Create the socket node
 * ----------------------
 * Note `SO_REUSEADDR` does not work with `AF_UNIX` sockets,* so we will have to unlink the socket node if it already exists,* before we bind. For safety,we won't unlink an already existing node
 * which is not a socket node. 
 */

status = stat (path,&st);
if (status == 0) {
   /* A file already exists. Check if this file is a socket node.
    *   * If yes: unlink it.
    *   * If no: treat it as an error condition.
    */
   if ((st.st_mode & S_IFMT) == S_IFSOCK) {
      status = unlink (path);
      if (status != 0) {
         perror ("Error unlinking the socket node");
         exit (1);
      }
   }
   else {
      /* We won't unlink to create a socket in place of who-know-what.
       * Note: don't use `perror` here,as `status == 0` (this is an
       * error we've defined,not an error returned by a system-call).
       */
      fprintf (stderr,"The path already exists and is not a socket node.n");
      exit (1);
   }
}
else {
   if (errno == ENOENT) {
      /* No file of the same path: do nothing. */
   }
   else {
      perror ("Error stating the socket node path");
      exit (1);
   }
}

/* … invoke `bind` here,which will create the socket node … */
我只能访问一个POSIX规范文档,这是 System Interfaces,所以我要尽力从这里.

我们的规范spelunking冒险当然必须从2.10.6 Use of Options开始,它定义了SO_REUSEADDR选项,如下所示:

The SO_REUSEADDR option indicates that the rules used in validating addresses supplied in a bind() should allow reuse of local addresses. Operation of this option is protocol-specific. The default value for SO_REUSEADDR is off; that is,reuse of local addresses is not permitted.

这一段基本上不会对这个选项真正做的任何规定,通过将它委托给底层协议的规范.

Section 2.10.17 Use of Sockets for Local UNIX Connections描述了创建UNIX域套接字的机制,但是它告诉我们的唯一的事情是使用什么套接字类型常量,哪些结构用于地址. The documentation for the sockattr_un struct只告诉我们它的格式,而不是关于它的绑定行为.

The documentation for bind itself可以理解为协议无关,只告诉我们地址已经在使用中会发生什么,而不是重新绑定同一套接字有效的情况.

虽然它不是POSIX标准文档,但是如果仅仅是因为它不是专门针对Linux或BSD,富士通才有a document on the POSIX sockets API的意义.本文档的2.6.4节对UNIX套接字绑定的行为有如下要求:

The path name,which must be specified in the sun.sun_path component,is created as a file in the file system using bind(). The process that calls bind() must therefore have write rights to the directory in which the file is to be written. The system does not delete the file. It should therefore be deleted by the process when it is no longer required.

虽然这对SO_REUSEADDR没有什么特别的说明,但它确实指出,bind的行为是创建一个文件,并且绑定进程有责任在不再使用它时将其删除.

最后,本文档对setsockopt的描述如下:SO_REUSEADDR:

Specifies that the rules for the validity check on the addresses specified for bind() should permit the reuse of local addresses provided this is supported by the protocol.

因此,尽管没有特别提及AF_UNIX,但它确实确认此选项不适用于所有协议.

我也发现a (non-authoritative) summary describing the intended purpose of SO_REUSEADDR

This socket option tells the kernel that even if this port is busy (in the TIME_WAIT state),go ahead and reuse it anyway. If it is busy,but with another state,you will still get an address already in use error.

TIME_WAIT状态主要用于面向Internet的套接字,以避免新程序绑定到最近由另一个程序使用的端口,并无意中接收与旧程序相关的数据包.这个问题可能不适用于UNIX域套接字,因为两个程序不太可能尝试在同一路径上创建一个套接字,所以如果没有为UNIX套接字实现TIME_WAIT,那么这可能是一个(近似)解释为什么SO_REUSEADDR不适用于AF_UNIX.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读