首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >dnsmasq错误地将DHCP绑定到0.0.0.0:67,而DNS查询则正确地侦听10.0.0.1:53

dnsmasq错误地将DHCP绑定到0.0.0.0:67,而DNS查询则正确地侦听10.0.0.1:53
EN

Unix & Linux用户
提问于 2021-05-25 09:15:41
回答 1查看 1K关注 0票数 2

我有两个DHCP服务器,运行在不同的两个接口上。(只有eth0/10.0.0.1使用dnsmasq.)

根据命令页,对于DNS和DHCP,下列选项应该使它只监听10.0.0.1:

代码语言:javascript
复制
dnsmasq --keep-in-foreground --pid-file=/data/dnsmasq.pid --server=172.31.139.16 \
--server=172.30.139.16 --bind-interfaces --except-interface=wlan0 --except-interface=lo \
--except-interface=wwan0 --dhcp-range=10.0.0.100,10.0.0.109 --log-dhcp --dhcp-authoritative \
--listen-address=10.0.0.1

上面的参数会导致DNS的预期行为,但是DHCP被错误地绑定到0.0.0.0:67。

代码语言:javascript
复制
smarc_mx8mq:/ # netstat -lnup                                                                                                                                                                                                                         
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program Name
udp        0      0 10.0.0.1:53             0.0.0.0:*                           5167/dnsmasq
udp        0      0 0.0.0.0:67              0.0.0.0:*                           5167/dnsmasq

我已经尝试过这些参数的几个变体,但是DHCP总是在0.0.0.0:67上监听。

更新:

strace显示地址0.0.0.0上打开的端口67:

代码语言:javascript
复制
setsockopt(4, SOL_IP, IP_MTU_DISCOVER, [0], 4) = 0
setsockopt(4, SOL_IP, IP_TOS, [192], 4) = 0
setsockopt(4, SOL_IP, IP_PKTINFO, [1], 4) = 0
setsockopt(4, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0
setsockopt(4, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(4, {sa_family=AF_INET, sin_port=htons(67), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE) = 5

有趣的是,它是用SO_REUSEPORT打开的,允许多个侦听过程(如果他们也设置了SO_REUSEPORT)。

EN

回答 1

Unix & Linux用户

回答已采纳

发布于 2021-05-25 10:49:18

问题在dhcp.c中。

代码语言:javascript
复制
  /* When bind-interfaces is set, there might be more than one dnsmasq
     instance binding port 67. That's OK if they serve different networks.
     Need to set REUSEADDR|REUSEPORT to make this possible.
     Handle the case that REUSEPORT is defined, but the kernel doesn't 
     support it. This handles the introduction of REUSEPORT on Linux. */
  if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
    {
      int rc = 0;

#ifdef SO_REUSEPORT
      if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt))) == -1 && 
      errno == ENOPROTOOPT)
    rc = 0;
#endif
      
      if (rc != -1)
    rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
      
      if (rc == -1)
    die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET);
    }


  memset(&saddr, 0, sizeof(saddr));
  saddr.sin_family = AF_INET;
  saddr.sin_port = htons(port);
  saddr.sin_addr.s_addr = INADDR_ANY;
#ifdef HAVE_SOCKADDR_SA_LEN
  saddr.sin_len = sizeof(struct sockaddr_in);
#endif

  if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)))
    die(_("failed to bind DHCP server socket: %s"), NULL, EC_BADNET);

套接字不带任何条件地绑定到INADDR_ANY (0.0.0.0)。

看起来,作者的意图是让多个dnsmasqs使用SO_REUSEPORT共享0.0.0.0:67。对于多个dnsmasqs来说,这很好,但是当dnsmasq需要与另一个不设置SO_REUSEPORT的DHCP服务器共存时,情况就不好了。

Java有SO_REUSEADDR,但没有SO_REUSEPORT:

代码语言:javascript
复制
packages/modules/NetworkStack/src/android/net/dhcp/DhcpServer.java:642: error: cannot find symbol
                Os.setsockoptInt(mSocket, SOL_SOCKET, SO_REUSEPORT, 1);

但这可以通过以下几个方面加以解决:

代码语言:javascript
复制
final int SO_REUSEPORT = 15;
票数 2
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/651253

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档