记一次因IPv6导致的钉钉Webhook机器人消息推送异常

2025-10-16

最近遇到一个小问题,折腾了一番,发现背后其实挺有意思的。事情的起因是我们团队从飞书切换到钉钉,在适配钉钉群机器人的消息推送时报错,提示“系统异常,请稍后再试”或者“ip 不在白名单中”。一开始以为是自己配置的不对,到后来经过多次验证以为是钉钉的bug,心想大厂产品不应该啊,结果最终排查下来,竟然是因为IPv6。

一、问题的由来

我们团队之前用的是飞书的群机器人,后来因为一些原因切换到了钉钉。刚开始配置钉钉机器人的时候,一切都挺顺利,按照文档一步步来,结果在测试消息推送时,服务器端总是返回错误:

钉钉机器人有个安全机制要求,即关键字、加签或者IP地址(段)三选一,否则无法创建群机器人。于是我第一时间怀疑是不是 IP 没加对。

二、排查过程

1. 反复确认 IP

虽然这台服务器的IP地址我本来就记得滚瓜烂熟,但还是用 curl 查了下出口 IP:

curl cip.cc
IP      : ***
地址    : ***
运营商  : ***

数据二  : ***

数据三  : ***

URL     : http://www.cip.cc/***

得到的 IPv4 地址和白名单里的完全一致,没问题。

这时我陷入了困惑:为什么钉钉还是说我的 IP 不在白名单里?

2. 跨平台验证

又换了 curl ifconfig.me/all 试试:

curl ifconfig.me/all

ip_addr: 2001:***
remote_host: unavailable
user_agent: curl/7.81.0
port: 51554
language: 
referer: 
connection: 
keep_alive: 
method: GET
encoding: 
mime: */*
charset: 
via: 1.1 google
forwarded: ***

结果发现除了 IPv4,这台服务器还有一个 IPv6 地址。这才意识到,服务器其实有两个出口地址。

3. DNS 解析钉钉 API

继续查 oapi.dingtalk.com 的 DNS 记录:

dig oapi.dingtalk.com AAAA

;; QUESTION SECTION:
;oapi.dingtalk.com.             IN      AAAA

;; ANSWER SECTION:
oapi.dingtalk.com.      ...     IN      CNAME   oapi.dingtalk.com.gds.alibabadns.com.
oapi.dingtalk.com.gds.alibabadns.com. ... IN CNAME v6-cname.dingtalk.com.
...
cn-v6-cname.dingtalk.com.gds.alibabadns.com. ... IN AAAA 2401:b180:2000:60::f
cn-v6-cname.dingtalk.com.gds.alibabadns.com. ... IN AAAA 2401:b180:2000:70::e
cn-v6-cname.dingtalk.com.gds.alibabadns.com. ... IN AAAA 2401:b180:2000:50::b
cn-v6-cname.dingtalk.com.gds.alibabadns.com. ... IN AAAA 2401:b180:2000:80::d

果然,钉钉 API 域名有 IPv6 解析,也就是说,系统很可能默认用 IPv6 访问钉钉。

4. 白名单只能填 IPv4

我试着把 IPv6 地址填进钉钉机器人的安全设置页面,结果提示“请输入正确的IP地址”。钉钉的白名单只接受 IPv4,IPv6直接被拒绝。

三、问题分析

事情至此真相大白:

所以,虽然我的 IPv4 在白名单里,但实际请求用的是 IPv6,导致被钉钉拒绝。

四、解决方案

既然钉钉不支持 IPv6,而我也不需要 IPv6 那就让服务器也不用 IPv6:

临时关闭 IPv6:

sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1

永久关闭 IPv6:

  1. 编辑 /etc/sysctl.conf,添加以下两行:

    net.ipv6.conf.all.disable_ipv6 = 1
    net.ipv6.conf.default.disable_ipv6 = 1
    
  2. 保存并退出,然后运行 sudo sysctl -p 使配置生效。

关掉 IPv6 后,钉钉消息推送恢复正常。

五、一些感想

这个小问题其实挺有代表性:IPv6 越来越普及,很多平台(包括钉钉)却还没完全适配 IPv6。随着 IPv6 的普及性进一步提高,这类兼容性问题肯定会越来越多。希望钉钉早日支持 IPv6 白名单,不然大家还得不停折腾网络设置。

如果你也遇到类似问题,不妨用 curl ifconfig.me/all 看看自己的服务器是不是也有 IPv6 地址。很多时候,问题就藏在这种你“从来没注意过”的细节里。


有些小 bug,看起来不起眼,背后却藏着技术演进的脚步。愿大家都能在“意料之外”多留个心眼,少踩点坑。