家宽IPv6 80/443端口公网被ban? 利用Happy Eyeballs实现双栈分流

家宽IPv6 80/443端口公网被ban? 利用Happy Eyeballs实现双栈分流

家宽运营商封锁 80/443 端口公网入站, 导致自建服务无法通过标准端口对外访问. 本文利用 Happy Eyeballs (快乐眼球) 算法的双栈回退机制, 通过 DDNS-Go 将 AAAA 解析指向家宽 IPv6 地址, A 解析指向 CDN 节点, CDN 通过非标端口 (如 8443) 回源 IPv6. 公网用户走 IPv4 -> CDN -> 非标端口回源; 局域网用户走 IPv6 直连, 从而绕过端口封锁实现双栈分流建站. (AI摘要总结)

前言#

家宽运营商通常封锁 80 和 443 端口的公网入站流量, 导致自建服务无法通过标准端口对外提供访问. 例如 DDNS 域名和 [ipv6]:80.

原理#

在 IPv4 和 IPv6 过渡期间, 为了追求更佳的用户体验, 诞生了一种名为 Happy Eyeballs(快乐眼球) 的算法.

Happy Eyeballs(快乐眼球),亦被称作 Fast Fallback(快速回退),是一个由 IETF 发布的算法. 支持该算法的程序会尝试同时使用 IPv4 和 IPv6 协议进行连接, 若两者皆可连通则首选 IPv6, 使得同时支持 IPv4 和 IPv6 的双栈应用程序对用户的响应更加灵敏, 从而最大限度地减少 IPv6 连接或设置不完善的用户遇到的常见问题.

实际应用中 浏览器会优先发起 IPv6连接 , 一段时间后再发起 IPv4连接.

利用这个机制: 我们可以通过DDNS-Go , 将 AAAA解析 指向家宽IPv6地址; 将 A解析 指向 CDN . CDN回源家宽IPv6非标准端口( 如:81 ).

补充一个冷知识: 除了 Cloudflare(不含 SaaS) 这类需要 NS 接入的CDN, 绝大多数CDN可以直接通过 A/AAAA 解析指向CDN节点(Cloudflare SaaS 优选的原理也是这个).

流量路径:

  • 公网环境:

    • 根据 Happy Eyeballs 同时向 IPv4/IPv6 建立连接, IPv6 端口不可达; IPv4 连接成功.
    • 用户 ---IPv4---> CDN ---非标端口---> 目标网站
  • 局域网环境:

    • 根据 Happy Eyeballs 同时向 IPv4/IPv6 建立连接, IPv6 连接成功.
    • 用户 ---IPv6---> 目标网站

教程#

教程使用: Debian 13 系统, Web服务器使用 Nginx 1.30.2 , DNS使用 腾讯云 DNSPod , CDN使用 阿里ESA , 演示中的网站访问域名为 vm.yppp.net .

准备#

你需要:

  • 一个域名(有备案肯定更好了)
  • 一个支持IPv6回源的CDN(如果你的域名已经完成了ICP备案 可以使用免费的ESA/EO)(Cloudflare自己折腾吧 用Cloudflare SaaS.)
  • 家宽有IPv6, 非标端口未封入站.

安装DDNS-Go#

项目地址: jeessy2/ddns-go

下载可执行文件 一般情况下是 x86_64 .

可以使用以下命令查询CPU架构:

uname -m
wget https://github.com/jeessy2/ddns-go/releases/download/v6.17.1/ddns-go_6.17.1_linux_x86_64.tar.gz
tar -xvzf ddns-go_6.17.1_linux_x86_64.tar.gz

安装 DDNS-Go.

chmod +x ddns-go
./ddns-go -s install

配置DDNS-Go的部分参考 借助 DDNS-Go 使用家宽 IPv6 套 CDN 建站 .

教程的演示网站访问域名为 vm.yppp.net DDNS-Go的配置应该如下:

home-docker.yppp.net 用于CDN回源.

安装Nginx#

国内镜像源的Nginx都很老, 我们需要手动安装最新版本的Nginx, 新版本修复了很多高危漏洞.

如果你可以流畅地访问 Nginx 官方源 可以直接使用官方文档中的教程: https://nginx.org/en/linux_packages.html#Debian.

多数情况下是无法访问; 或者访问速度极慢(比如我这才20Kb/s). 我们需要手动安装Nginx.

浏览器访问 https://nginx.org/packages/debian/pool/nginx/n/nginx/.

下载 nginx_1.30.2-1~bullseye_amd64.deb(amd64=x86_64 下载对应CPU架构的deb文件), 手动上传到服务器, 使用以下命令安装:

apt install ./nginx_1.30.2-1~bullseye_amd64.deb

配置Nginx#

Nginx的配置文件在 /etc/nginx . 建议在 conf.d 文件夹中增加配置, 而不是修改 nginx.conf .

推荐一个SSH客户端 HexHub 可以很方便地远程编辑配置文件. 免费版功能足够使用.

创建一个新文件 我喜欢用 域名.conf 的格式来命名 粘贴以下内容 将 vm.yppp.net 修改为你实际的域名.

这份配置仅监听IPv6 并只提供HTTPS访问 CDN也将通过HTTPS回源. 80/443用于局域网访问; 8443用于CDN回源. 你需要配置 SSL证书, 可以使用 Certimate 实现自动化部署.

注: 你需要为 vm.yppp.net 也添加DDNS-Go 如果你有n个站点 在DDNS-Go中 应该有n+1个域名 一个域名用来CDN回源(这个域名应该只有IPv6解析) 一个域名用于访问.

server {
    listen [::]:80;
    server_name vm.yppp.net;
    return 301 https://$host$request_uri;
}

server {
    listen [::]:443 ssl;
    http2 on;
    server_name vm.yppp.net;

    ssl_certificate     /etc/ssl/yppp.net/cert.crt;
    ssl_certificate_key /etc/ssl/yppp.net/cert.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    add_header Strict-Transport-Security "max-age=15552000" always;

    location / {
        proxy_pass http://127.0.0.1:8001;
        
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        
        proxy_http_version 1.1;
        # proxy_set_header Upgrade $http_upgrade;
        # proxy_set_header Connection "Upgrade";
        # 如果需要WS 就取消注释

        proxy_connect_timeout 30;
        proxy_send_timeout 30;
        proxy_read_timeout 30;
    }
}

server {
    listen [::]:8443 ssl;
    http2 on;
    server_name vm.yppp.net;

    ssl_certificate     /etc/ssl/yppp.net/cert.crt;
    ssl_certificate_key /etc/ssl/yppp.net/cert.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    add_header Strict-Transport-Security "max-age=15552000" always;

    set_real_ip_from 0.0.0.0/0;
    real_ip_header X-Forwarded-For; 

    location / {
        proxy_pass http://127.0.0.1:8001;
        
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        
        proxy_http_version 1.1;
        # proxy_set_header Upgrade $http_upgrade;
        # proxy_set_header Connection "Upgrade";

        proxy_connect_timeout 30;
        proxy_send_timeout 30;
        proxy_read_timeout 30;
    }
}

配置CDN#

以 阿里ESA 为例, 添加站点 vm.yppp.net , 记录类型选择 CNAME , 记录值/源站选择 域名 , 在这里输入 DDNS-Go 的域名

在 SSL/TLS -> 源站证书 中, 将 回源协议和端口 修改为HTTPS 端口修改为上方Nginx配置文件中的第三个Server块中的监听端口号

如果 CDN 中有其他网站 可以在 规则 -> 回源规则 中只修改需要特定端口回源的域名

DNS解析#

在 DDNS-Go 阶段 已经添加了 vm.yppp.net的 AAAA解析, 因为CNAME解析会覆盖AAAA解析 只能添加A解析来指向CDN

使用 https://www.itdog.cn/ TCPing 测试 , 测试CDN服务商分配的CNAME域名 将 IP 结果作为 A 解析的记录值添加(随便添加几个就行了).

总结:

  1. DDNS-Go中添加两个域名 一个作为回源 一个作为访问域名 仅添加AAAA解析
  2. 配置完成Nginx和CDN后 手动添加A解析 指向CDN节点
  3. 手动在Nginx和CDN上配置证书(推荐 Certimate )

参考资料

暂未开放评论区, 欢迎加入 QQ 群交流讨论:

QQ 群 959731247