You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js GET请求IPv6地址不一致问题及原因问询

问题描述

我在Cloudflare为自己注册的CNAME配置了区域锁定规则,白名单内添加了谷歌搜索「whatsmyip」查到的本机IPv6地址,以及公司IPv4格式的VPN地址。实际请求时出现以下异常现象:

  • curl、Golang程序、Insomnia工具请求该端点都能正常返回200
  • 使用Node.js原生请求、axios发起请求时,仅连接IPv4网络(公司VPN、手机热点)时返回200,其他场景都返回403

相关测试代码如下:

curl https://my-restricted-endpoint.com 
# 200
package main

import (
    "fmt"
    "log"
    "net/http"
)

func main() {
    resp, err := http.Get("https://my-restriced-endpoint.com")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(resp.StatusCode)
    // 200
}
const requestAsync = (options: RequestOptions | string | URL): Promise<number> => {
    return new Promise((resolve, reject) => {
        const req = request(options, (res) => {
            if (typeof res.statusCode !== 'number') {
                reject('no status code returned');
                return;
            }
            resolve(res.statusCode);
        });

        req.on('error', (error) => {
            reject(error);
        });

        req.on('timeout', () => {
            reject('request timed out');
        });

        req.end();
    });
};

const statusCode = await requestAsync('https://my-restricted-endpoint.com')
// 连VPN或连接有IPv4地址的手机热点时返回200,其他场景返回403

我已经找到临时解决方案,给请求参数添加family: 6后就能正常得到结果:

const options = {
    ...standardStuff,
    family: 6,
}

根据Node.js官方文档对该参数的说明:

解析host或hostname时使用的IP地址族,有效值为4或6。未指定时会同时使用IPv4和IPv6。

我有两个疑问:

  1. 按照文档说明未指定参数时应该同时支持IPv4和IPv6,为什么需要额外添加family: 6才能正常请求?
  2. 为什么curl、Golang等其他工具不需要配置该参数就能正常访问?

问题解答

这个差异本质是Node.js默认的DNS解析和IP选择逻辑,和其他常用工具的实现不一致导致的:

  1. Node.js默认IP选择逻辑:Node.js的http/https模块默认使用dns.lookup方法解析域名,该方法调用系统的getaddrinfo接口,会按照接口返回的IP顺序选择第一个可用IP发起请求,绝大多数系统的getaddrinfo默认会把IPv4地址放在返回结果的前面,所以Node.js默认会优先使用IPv4地址发起请求。你不在VPN环境下时,本机的公网IPv4地址不在Cloudflare的白名单内,自然会被拦截返回403。
  2. 其他工具的默认逻辑:curl、Golang标准库、大部分浏览器都默认实现了「Happy Eyeballs」算法,解析域名后会同时发起IPv6和IPv4的连接请求,哪个先返回就用哪个,绝大多数网络环境下IPv6的连接速度更快,所以这些工具会优先用IPv6地址发起请求,刚好你的IPv6地址在白名单内,所以请求正常。
  3. 为什么加family:6就正常:指定该参数后,Node.js解析域名时只会返回IPv6地址,强制使用IPv6发起请求,自然就匹配上了白名单里的IPv6地址,请求正常。

如果不想每次手动指定该参数,也可以改用dns.resolve系列方法替代默认的dns.lookup,或者使用支持Happy Eyeballs的第三方请求库。


内容的提问来源于stack exchange,提问作者amwill04

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 05:06:05