目前的情况实在糟糕。我们要么向云服务商付更多的钱,要么坐视自己的网络服务崩溃。
最近一段时间,新闻头条总会时不时提起 IP 地址。AWS 宣布要对每个 IPv4 地址每小时收费 0.005 美元,其他云服务商也纷纷行动,宣称要对公共 IPv4 这种“奢侈品”开价。Google Cloud Platform 开出的价格是 0.004 美元,跟 Azure 和 Hetzner 的每小时 0.001 欧元基本相当。很明显,云服务商自己掏钱购买 IPv4 地址空间的时代即将结束。随着时间推移,当这些地址越来越有价值,想要免费使用自然也就不可能了。
面对这样的压力,我们当然应该赶快切换到 IPv6。其实我第一次听说 IPv6 这东西,是在高中的第一堂思科技术课上。而现在我已经 36 岁了,大家可以想象当时老师说的“即将到来”究竟来得有多慢。到目前为止,我在 IPv6 方面还没做过多少实际工作,毕竟市场对此类技能的需求实在不旺。而且从业经历也还算丰富的我可以证明,没有任何一家雇主会认真强调 IPv6 方面的技能需求。所以我压根就没学,只能说很遗憾错过了这场网络领域的巨大变革和进步。
种一棵树最好的时间是十年前,其次是现在。学习 IPv6 当然也是如此,所以我打算试着把自己的博客迁移到 IPv6。我会继续把它放在 CDN 后面来处理 IPv4 流量,但无论如何,这个重要的历史时刻终于来临了!但我惊恐地发现,关于 IPv6 的一切几乎都没法开箱即用。主要依赖项会立即停止运行,而解决方案也很难称得上“生产就绪”。即使是人员充足的技术团队,在处理 IPv6 迁移过程时也是异常艰难,毕竟几乎没人在这方面的实践经验。我们多年来都忽略了这个问题,而现在是时候付出代价了。
当然有,但受篇幅所限,本文就不具体论述 IPv4 和 IPv6 的优劣了。网上这类文章很多,大家酌情参考。下面,我简要介绍一下为什么要转向 IPv6。
IPv6 数据包标头示例
最后,也是最重要的一点:IPv6 地址是免费的,但 IPv4 地址却要付钱。
其实具体设置过程非常简单。我配置了一台 Debian 设备并选择了“IPv6”,接下来第一个“惊喜”就出现了。这台设备没能获得 IPv6 地址。我只得到了一条 /64 地址,也就是 18,446,744,073,709,551,616。但好消息是,我的小型 ARM 服务器可以通过扩展,在所有公共地址上运行我之前工作过的每家公司的网络基础设施。
这看似有点浪费,但理解了 IPv6 的工作原理之后,大家会发现事实并非如此。因为 IPv6 比 IPv4 多得多,所以就算在网络上设置 1 万台主机也没问题。所以哪怕乍看上去有点浪费,保留所有 IPv6 空间也有其实际意义。所以,用不着考虑有多少地址被发送给了每台设备。
重要提示:控制住自己优化地址利用率的冲动。在跟经验丰富的网络专家交流时,我发现很多人都容易掉进优化地址的坑里。我们都花过很多时间考虑 IPv4 地址块里还剩多少空间,并围绕这个问题搞设计。但在 IPv6 中这个问题根本就不存在,/64 前缀就是我们应在接口上配置的最小前缀。
如果非要使用较小的前缀(有人确实尝试过),比如用 /68 或者 /96,可能会破坏无状态地址的自动配置。在心态上,我们应当将各个站点配置为 /48,这也是地区互联网注册管理机构在分配 IPv6 时的默认设定。而在设计网络组织时,则应考虑半字节边界——这可不是胡说八道,简单来讲,这就是一种让 IPv6 更易于阅读的形式。
假设我们要使用 2402:9400:10::/48,如果希望每台设备只使用 /64 作为平面网络结构,则可按如下方式进行划分:
而 /52 的情况也差不多。
这样,我们就能一目了然看到自己正在查看哪个子网。
好了,现在设备已经准备就绪,接下来做点常规服务器设置操作。
其实这个问题完全可以预见。我的工作或家庭 ISP 都不支持 IPv6,所以我才需要设置自己的服务器,但现在却完全不起作用。好吧,我只能附加一个 IPv4 地址,通过 SSH 登录,再设置 cloudflared 来运行隧道。想必系统会自行处理其中的转换工作。
但 Cloudflare 显然没考虑到这种用法。所以当我删除 IPv4 地址时,隧道意外崩溃了。默认情况下,cloudflared 实用程序使用的是 IPv4,我们需要单独编辑 systemd 服务文件以添加:-edge-ip-version 6。完成之后隧道才能正常启动,我也可以通过 SSH 顺利登录了。
现在我的小服务器已经开始运行,接下来该做具体设置了。我运行了自己的服务器设置脚本,但立马就报错了。它会尝试访问 history 的安装脚本,这是款很棒的 shell 历史记录实用程序,我在自己的所有计算设备上都会用它。它尝试从 GitHub 提取安装文件,但失败了。“这不对吧,GitHub 难道不支持 IPv6 吗?”
确实不支持。这简直让人心态爆炸,支撑整个互联网的软件发布服务居然不能兼容 IPv6……但也难怪,现在微软的心思全都放在人工智能身上,哪有功夫管你什么 GitHub 和 IPv6。最终,我选择使用 TransIP GitHub 代理,效果很好。现在我可以正常访问 GitHub 了。但随后 Python 也报错,显示 urllib.error.URLError:。好吧,我选择放弃。我猜是 Debian 中的 Python 3 版本不兼容 IPv6,但我现在实在没那个心情做故障排查。
接下来是一些基本操作。我想设置 Datadog 来监控这台服务器的运行,其实关注的指标并不多,只是一些历史负载数字。我转向 Datadog,登录并开始执行设置,但它立刻就崩溃了。我运行 curl -L https://s3.amazonaws.com/dd-agent/scripts/install_script_agent7.sh 来实现这个简单设置,而且人家 S3 已经支持 IPv6 了,这到底是哪出的错?
curl -v https://s3.amazonaws.com/dd-agent/scripts/install_script_agent7.sh
* Trying [64:ff9b::34d9:8430]:443...
* Trying 52.216.133.245:443...
* Immediate connect fail for 52.216.133.245: Network is unreachable
* Trying 54.231.138.48:443...
* Immediate connect fail for 54.231.138.48: Network is unreachable
* Trying 52.217.96.222:443...
* Immediate connect fail for 52.217.96.222: Network is unreachable
* Trying 52.216.152.62:443...
* Immediate connect fail for 52.216.152.62: Network is unreachable
* Trying 54.231.229.16:443...
* Immediate connect fail for 54.231.229.16: Network is unreachable
* Trying 52.216.210.200:443...
* Immediate connect fail for 52.216.210.200: Network is unreachable
* Trying 52.217.89.94:443...
* Immediate connect fail for 52.217.89.94: Network is unreachable
* Trying 52.216.205.173:443...
* Immediate connect fail for 52.216.205.173: Network is unreachable
问题不在 S3 或者我的服务器上,因为我可以正常使用 AWS 提供的 S3 存储桶连接测试。
curl -v http://s3.dualstack.us-west-2.amazonaws.com/
* Trying [2600:1fa0:40bf:a809:345c:d3f8::]:80...
* Connected to s3.dualstack.us-west-2.amazonaws.com (2600:1fa0:40bf:a809:345c:d3f8::) port 80 (#0)
> GET / HTTP/1.1
> Host: s3.dualstack.us-west-2.amazonaws.com
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 307 Temporary Redirect
< x-amz-id-2: r1WAG/NYpaggrPl3Oja4SG1CrcBZ+1RIpYKivAiIhiICtfwiItTgLfm6McPXXJpKWeM848YWvOQ=
< x-amz-request-id: BPCVA8T6SZMTB3EF
< Date: Tue, 01 Aug 2023 10:31:27 GMT
< Location: https://aws.amazon.com/s3/
< Server: AmazonS3
< Content-Length: 0
<
* Connection #0 to host s3.dualstack.us-west-2.amazonaws.com left intact
好吧,我打算通过 apt 手动进行设置。
0% [Connecting to apt.datadoghq.com (18.66.192.22)]
他奶奶的……行,Datadog 你滚吧。到这个时候,我终于意识到纯使用 IPv6 根本没有前途。如果不上代理和技术补丁,那原本简单的几乎一切组件都会跟我闹别扭。所以接下来我会尽可能使用 IPv6,但同样辅以 IPv4。
为了从 IPv6 访问 IPv4 资源,我们需要借助 NAT64 服务。我最终用的是 https://nat64.net/。漂亮!所有问题几乎立刻消失,我能够正常访问各种资源了。我其实有点担心,毕竟这只是个业余项目,靠它来接入所有关键互联网资源到底行不行啊?但 IPv6 的兼容性问题实在太多,可行的选项又相当有限,所以我只能祈祷 NAT64 别耍流氓了。
我甚至惊讶于目前能够选择的方案居然如此有限。以下就是我能找到的最佳工具列表:
其中大多数工具似乎已经失效了。Dresel 链接无法工作,Trex 在测试中出现了问题,August Internet 彻底消失,大多数 Go5lab 测试设备离线。Tuxis 倒是可以工作,但在 2019 年推出之后似乎就没升级过。基本上,Kasper Dupont 似乎是互联网上唯一愿意继续支持 IPv6 的技术人。抱拳了,Kasper~
更直白地讲,Kasper 相当于是在用一臂之力支撑整个 IPv6 互联网。
到时这里,我对 Kasper 不禁心生好奇,并给他发邮件提了几个问题。这位老兄也热心给出了回复。
我:我发现公共 NAT64 服务非常有用,你为什么会一直坚持维护这个项目呢?
Kasper:我这么做,主要是想推动 Ipv6 继续发展。有那么几年,我打算在家里搭建纯 IPv6 网络,并发现 DNS64 加 NAT64 的实际表现相当出色。我想让更多人也能有机会用上。在发布第一个 NAT64 网关时,它只是推广 NAT64 扩展的概念验证项目。NAT64 就这样延续了下来,没有太多复杂的故事。
几个月前,我终于在家里用上了原生 IPv6。所以现在,我可以用更类似自己当初的方式帮助目标用户解决问题。
我:NAT64 几乎是互联网上仅存的少数此类免费公共服务之一。能不能聊聊你为什么坚持了下来,这服务的运行成本是多少,总之多跟我说说具体情况吧。
Kasper:这是款个人产品,所以我在不同的地方一共用到七家虚拟机托管服务商。有些是从 Hetzner 购买的,价格是每月 4.51 欧元:https://hetzner.cloud/?ref=fFum6YUDlpJz 其他虚拟机要贵一点,但贵得不多。
在这些虚拟机中,有 4 个用于 NAT64 服务,其他则用于别的 IPv6 过渡相关服务。比如我自己也在其中一个虚拟机上运行这项服务:http://v4-frontend.netiter.com/
我希望以后能跟托管商达成协议,提高服务容量并把它变成能赚钱的业务,这样我就可以全职从事 IPv6 相关工作了。但目前我仅仅是拿出点个人时间鼓捣。我的目标是让纯 IPv4 内容提供商以传输带宽成本的方式支付这部分费用。
我:有没有愿意分享的其他技术细节呢?
Kasper:当然可以,只是这些技术细节可能有点复杂。
我觉得自己这项服务跟其他服务的主要区别,在于我的每个 DNS64 服务器都会自动根据所有网关的健康检查通过 NAT64 前缀进行更新。也就是说,任何单一 NAT64 网关的中断,基本都不会对用户体验造成影响。这对维护也有帮助。在我看来,这可能是 NAT64 服务在同类公共服务中获得认可的核心原因。
NAT64 服务的代码也完全由我自己开发而成,目前作为 Linux 上用户模式的守护进程。我正在考虑把大部分性能关键部分移植成内核模块。
好了,到这里我已经介绍完毕、网站也开始运行了。为了通过 IPv6 拉取 docker 容器,我们需要在镜像名称前添加 registry.ipv6.docker.com/library/ 。例如:image: mysql:8.0 会变成 image: registry.ipv6.docker.com/library/mysql:8.0
Docker 会警告说此设置尚未达到生产就绪状态。我不太确定 Docker 想提醒什么,毕竟如果它停止运行,拉取操作照常执行也就可以了吧?
完成之后,我把自己这个网站设置为 AAA DNS 记录,并允许 Cloudflare 进行代理。也就是说,它们会处理 IPv6 的广告并将流量引向这里。我还做了另一项修改:之前我使用的是 Caddy Web 服务器,但因为现在大部分流量都转移到了 Cloudflare 这边来,所以我决定改用 Nginx。毕竟当主要流量都来自 Cloudflare,那自然得相应调整 SSL 的工作方式。
现在,我已经把 Cloudflare 的原始证书硬加载到了 Nginx 当中,同时设置了经过身份验证的源拉取,这样就可以确定所有流量均通过 Cloudflare 运行。该证书的签名有效期为 15 年,所以我可以放心把它保留在自己的 secret 管理系统当中、不再分心打理。好了,现在我的网站已经重新上线并正常运行。是的,你眼前看到的这篇内容,就是系统能够顺畅工作的最好证明。
我的容器仍无法与 IPv4 资源通信,就算位于具有 IPv6 网桥的 IPv6 网络上也不行。DNS64 解析能正常工作,而且我已经把 fixed-cidr-v6 添加到了 Docker 当中。我可以跟 IPv6 资源正常通信,但 NAT64 转换过程却不起作用。之后我会继续研究可行的办法。
有些朋友可能想 ping 一下试试,但我在添加 NAT 时用到了 ip6tables。
SMTP 服务器问题。我还没找到拥有 AAAA 记录的商用 SMTP 服务。Mailgun 和 SES 都不行,我试过的其他一些小服务也宣告失败。即使 Fastmail 也帮不上忙。
这里咱们先不扯地址不够用之类的闲话。如果能早一点尝试推广 IPv6,那我们的网络基础设施建设方式可能将完全不同。企业之所以经常用到负载均衡器和隧道等技术,并不是真的有什么硬性功能需求,而是希望在私有 IP 范围和公共 IP 地址之间做出某种逻辑划分,并将其保留在 DNS A 记录当中。
如果具体把负载均衡器拆开来看,它其实只负责两项工作。首先将传入的数据包分发到后端服务器上,之后检查这些服务器的运行状态并将不健康的服务器从轮换中剔除。当然,现在很多人也在用负载均衡器处理 SSL 终止和指标等事务,但这些并不是负载均衡器设计上的必要功能。负载均衡有多种实现方式,最常见的包括:
大家应该注意到了,跟公共 IP 地址相比,私有 IP 地址完全用不上这些功能。从计算角度看,将主机配置为仅接受某一个来源(负载均衡器)的流量只是更简单也相对更便宜。但出于这个目标,我们被迫在基础设施层面做出大量设计,例如 VPC、NAT 网关、公共子网和私有子网等等,其实这些原本都没必要、至少不用像现在这么重要。
更讽刺的是,IP 白名单目前是种并不完善的安全实践。它最大的问题就是浪费时间,因为我们使用的都是云服务商所拥有的 IP 地址。但面向未来,IP 的名单的存在仍然意义重大,因为企业会随需求增加而自行购买 /44,包括从美国互联网号码注册机构(ARIN)、Réseaux IP Européens 欧洲网络协调中心(RIPE)或者亚太网络信息中心(APNIC)购买一组 IP。
这样,我们就永远不需要担心“谷歌会不会再多买点 IP 地址”或者“我得关注 GitHub 的支持页面,确保他们不会添加更多 IP 地址”。未来我们将拥有自己的 IP 地址块,在使用期限之内随意用于整个业务体系。容器系统不需要在每个主机上分配内部 IP 地址,因为有公共 IP 地址块可供使用,需要时还能通过标准公共 DNS 轻松发布通告。
当然,我不是说专用网络不好。我的意思是,我们采用的很多网络设计并非出于硬性需求,反而是被“绑架”的设计产物。我猜测未来的应用程序会更多对接开放互联网,而不再完全依赖于私有 VPC 的安全保障。考虑到安全漏洞的基本原理,这样的设计可能更有益于整体安全。
所以,即使大家根本不关心成本和可用性问题,那让组织更多掌握网络功能的所有权和控制权,也必将带来可以量化的巨大价值。
总之,目前的情况实在糟糕。我们要么向云服务商付更多的钱,要么坐视自己的网络服务崩溃。希望那些不想付钱的朋友们能继续推动 IPv6 的普及,但遗憾的是我们居然花了这么多年才达到如今的水平。所有这些问题本来可以逐步解决,但在掌握资源的团队做出实际行动之前,很多朋友心里恐怕还是有个大大的问号。
我真心希望最终结果能更好一些,至少应该给那些希望永久掌握自己 IP 范围的小公司一点机会。而且随着 IPv6 逐步成为主流,也希望它的使用门槛能变得更低一些。反正目前的现状就是两个字:糟糕,出奇的糟糕。
如果你经营着一家小公司,又不想额外花钱使用 IP 地址,那当下唯一的办法就是多留点时间:各位将有无数问题需要解决。
期待看到大家的意见 / 更正 / 驳斥~
原文链接:
领取专属 10元无门槛券
私享最新 技术干货