2024-06-28 02:09:00
最近家里的 Wi-Fi 设备更新换代,我第一次体验到了 6 GHz Wi-Fi,第一次在手机上见到千兆网速。本文记录一下前因后果。
IEEE 的命名品位实在是太差了,各代 Wi-Fi 标准的名称都是晦涩难记的数字和字母。我真不知道我以前是怎么记住这些术语的。总算从 2019 年推出的 Wi-Fi 6 开始,他们增加了一套更好记的宣传名称,并追认了 Wi-Fi 5 和 Wi-Fi 4。以下为对照表:
宣传名称 | 实际名称 | 年份 |
---|---|---|
Wi-Fi 8 | 802.11bn | 2028 |
Wi-Fi 7 | 802.11be | 2024 |
Wi-Fi 6E | 802.11ax | 2020 |
Wi-Fi 6 | 802.11ax | 2019 |
Wi-Fi 5(追认) | 802.11ac | 2014 |
Wi-Fi 4(追认) | 802.11n | 2008 |
Wi-Fi 3(民间追认) | 802.11g | 2003 |
Wi-Fi 2(民间追认) | 802.11a | 1999 |
Wi-Fi 1(民间追认) | 802.11b | 1999 |
Wi-Fi 0(民间追认) | 802.11 | 1997 |
值得注意的是,Wi-Fi 6 和 Wi-Fi 6E 虽然宣传名称不同,推出年份也不同,但实际的标准名称都是 802.11ax。在有些地方(比如 Android),也会把 Wi-Fi 6E 显示为 Wi-Fi 6,但 Wi-Fi 6E 和 Wi-Fi 6 有个本质区别:Wi-Fi 6E 支持 6 GHz 频率。
以前我家住小公寓,只有一层,所以一个 AP 就够了。去年搬进了双层屋,逐渐就觉得一个 AP 不是很够了。就算 AP 的发射功率再强,但如果客户端的天线不够劲的话,照样会出现连接性问题。搬家之后 AP 及其他网络设备都是放在一楼光纤接入的旁边的,在二楼用电脑无线上网,但是对于一些收发能力较弱的设备,就较容易出现断线的问题。
最近我买了新的电子书阅读器 Kobo Libra Colour,发现其在二楼有书房里很难连上 Wi-Fi;家属用 Nintendo Switch 打 Splatoon 3 联机经常掉线——我们终于决定买第二个 AP 了。
之前家里用的网络设备几乎都是 Ubiquiti / UniFi 的,现在还是打算继续买他们家的。看看 UniFi 又出了什么新货?
参考上文的对照表,很容易理解 UniFi 的产品线命名:AC 就是 Wi-Fi 5,而 U6 和 U7 分别对应 Wi-Fi 6 和 Wi-Fi 7。我家之前用的是 U6 Pro,支持 Wi-Fi 6 但不支持 Wi-Fi 6E。看到 U7 Pro 只比 U6 Pro 贵了一点点,于是就买了 U7 Pro——虽然家里并没有支持 Wi-Fi 7 的设备。购物车 (1)。
UniFi 的 AP 都是通过 PoE 供电。我之前是通过一个 PoE Adapter 给从普通交换机里出来的网线加上电,但现在有两个 AP 了,是不是干脆买个 PoE 交换机更好呢?再看看 UniFi 有啥 PoE 交换机?
算了一下功率,感觉最便宜 Lite 8 PoE 就够用了。购物车 (2)。
想要在把 AP 装到二楼,还要考虑网线的问题。我思索再三还是放弃了拆墙布线的计划,打算走明线。量了一下,在 Amazon 上买了个爆款 50 ft 网线。购物车 (3)。
虽然从上文的商品页截图看起来各 AP 长得都差不多,但实际到手之后发现 U7 Pro 比 U6 Pro 厚了不少:
配置 UniFi 设备我已经驾轻就熟了——怎么 adoption failed 呢?后来发现是我的 controller 软件版本太老了。我用的是 linuxserver.io 维护 Docker 镜像。他们维护了两个不同的版本:
我使用的前者已经停止维护了,而迁移到后者需要重做 MongoDB,再导入/导出。
需要注意的是 6 GHz 并不是默认打开的,需要在设置里启用,并且把 SSID 的安全性改成 WPA3。
总之最终是跑起来了。现在网络设备柜里是这样的:
最先成功连上 6 GHz Wi-Fi 的是我的 Google Pixel 7 手机:
图中我是用的外部测速网站,所以受到运营商带宽的限制。我家的带宽套餐的名义带宽是 940 Mbps,所以这样的速度已经算是跑满了。以前这样的速度只有在插了网线、有线上网的电脑上才能见到,这是我第一次在无线上网的手机上见到!
家属的 iPhone 15 Pro 也是支持 Wi-Fi 6E 的,但是却怎么也跑不出相应的速度。忘记网络之后重新输入一次密码之后总算跑出了应有的速度。我的猜测是因为 Wi-Fi 6E 需要 WPA3 加密所以要重新输入密码重新协商,而 Android 是每次连接的时候自动协商的,所以无需重新输入密码就可以自动连上。
iOS 不像 Android 那样直接是否使用 6 GHz 频率,但是如果支持 Wi-Fi 6E 的话,会在 SSID 设置里显示一个「Wi-Fi 6E Mode」选项。
这是我第一次体验 Wi-Fi 6E 和 6 GHz Wi-Fi。在此之前,我体验过最快的无线上网速度也就 500 Mbps 左右,视周围无线干扰环境,大部分情况下实际值都比这个要低;而有线上网的话,1000 Mbps 是目前最常见的。因此,我之前一直喜欢有线上网多于无线上网;搬家之前,家里几乎所有能插网线的设备(电脑、电视机、打印机)全部都是通过有线上网,哪怕它们同时也具有无线上网功能。
这次的体验颠覆了我的认知:原来无线上网也能跑满 1000 Mbps 的带宽!Wi-Fi 6 和 Wi-Fi 6E 的技术细节几乎是一样的,后者主要是多了 6 GHz 支持,但我是真没想到 6 GHz 对实际带宽的影响如此之大。UniFi AP 可以调查周围的无线环境,其扫描结果显示,我家周围的邻居们已经把 2.4 GHz 和 5 GHz 的信道挤满了,而 6 GHz 信道里,一个 SSID 都没有!我家的 Wi-Fi 是 6 GHz 信道的唯一用户!Wi-Fi 标准的最大速率都是在无干扰的情况下的理论值,这也算是尽可能贴近理论值了吧。
可惜的是,由于设备限制,我现在并不能测出这 Wi-Fi 6E 在我家最大能跑到多大的带宽——虽然 U7 Pro 是 2.5 GbE (2500 Mbps) 的速率,但家里的交换机和路由器都是 GbE (1000 Mbps) 速率的。如果我在下单的时候买的是 $640 的 2.5 GbE 的 PoE 交换机呢?依然不够,因为测速不仅需要一个客户端,还需要一个服务器,我还得再有一个带 2.5 GbE 网卡的服务器才行。我的 home server 已经插了 NVMe 扩展卡之后已经没有空间插 2.5 GbE 的网卡了……
等 2.5 GbE 设备更普及一些我再考虑升级交换机吧。
正如上文所说,我一直对有线上网有执念,能有线上网就尽量有线上网。搬家之后由于场地限制,很难实现全屋有线上网。现在无线上网的带宽达到千兆了,我对有线上网就没那么执念了。
实际应用的话,大概就是 Steam 购买新游戏到能玩上之间的等待下载时间减半吧……
更新:买了 Google Pixel 9,补一张 Wi-Fi 7 的图:Screenshot_20240823-232530.png
由于上文所述原因,目前 Wi-Fi 7 和体验和 Wi-Fi 6E 的体验是没有差异的…
2024-05-23 01:02:26
最近帮家属装修她的博客,我发现装修博客比写博客有意思多了,于是也动起了装修自己博客的念头。本文记录了我把博客的评论系统从 Disqus 更换为 Twikoo 的过程。
本博客的搭建工具/平台经历了三个阶段:
静态博客相比 WordPress 虽然有诸多优点,但最大的问题在于评论系统很难做成静态的。我刚把博客做成静态的时候想着干脆不做评论系统了,读者如果想留言就寄送电子邮件。后来考察了一番,还是加了一个 Disqus 评论系统,但默认不加载,需要访客点击启用——我看到那一堆慢吞吞的 JavaScript 加载动画实在是心烦。
用了几年 Disqus 之后,这货逐渐走上了 enshittification 的道路。免费用户的网站将被 Disqus 强制插入广告,不仅占地面积很大,且内容多为猎奇 clickbait。请看友人的博客上被 Disqus 插入的巨幅猎奇广告:
出于未知原因,我的 Disqus 继承了一个祖父计划,因此没有广告:
但我依然对 Disqus 不满。尤其是 2021 年时,有至少十个月,甚至可能长达一年的时间,Disqus 的邮件通知完全是坏的。现在想来,难道是因为 COVID-19 的影响,Disqus 的某些基础设施崩坏了而无人发现或无法修复?
在 2022 年初的时候 Disqus 的邮件系统修好了,我又能收到邮件了——但所有的邮件都会进 Spam!直到本文写作时为止,Disqus 给我发的邮件还是会被 Gmail 归到 Spam 里。哪怕我一遍一遍点 Not Spam 也没有用:
因为 Disqus 越来越烂,我就想找替代品,但 Disqus 又没有烂到完全不能用(尤其是我有无广告祖父计划),所以我也没有太强的动力去折腾更换。两年前,家属使用 Hugo 重建博客,也面临了评论系统选择的难题。家属并没有无广告 Disqus 账号,也不想为了评论系统交 $12/mo 的天价保护费去广告,那就自建吧?
「家属重建博客」和上文提到的「友人发现他的博客被 Disqus 插入巨幅广告」这两件事是差不多时间发生的,当时我和友人也讨论了一下自建博客评论系统的选择。最终友人为自己的博客搭建了 Golang 写的 Remark42,我为家属的博客搭建了 Python 写的 Isso,我自己的博客则继续用 Disqus。
两年后的现在,我帮家属博客装修的时候发现:友人的 Remark42 不知何时挂了,家属博客的 Isso 虽然还在跑着但是有内存泄露问题,只有 Disqus 依然在苟活。这时候我突然想通了一件事:
静态博客的优点就是无状态、轻量,不需要操心操作系统和软件更新的问题,运维成本极低;如果再自己维护一个评论系统,就把这些优点全部抵消了!
如何解决这个问题呢?像 Disqus 这样的全托管平台也是有的,但是我是不敢用的。自建平台又往往需要在自己的服务器上跑一个 Python / Node.js / Golang 程序,怎么办呢?
在对比调研各种评论系统的过程中我发现了一个全新的视角:serverless 部署。仔细想想,评论系统的后台其实需要处理的事件并不多,无非就是发表评论、拉取评论列表、编辑或删除自己发的评论,最多就是再加个邮件通知功能。这些功能都是可以在一个 HTTP 请求里完成的,这不是正是 serverless computing 最擅长的赛道吗?用 serverless 的评论系统,我就不需要担心运维问题,也不需要占用自己服务器的 RAM,同时又维持了自己对数据的掌控。
经过一些对比,我最终选择了 Twikoo 评论系统。这一评论系统支持运行在多个 serverless 平台上,使用 MongoDB 作为存储,支持消息推送和邮件通知。根据 GitHub 上的信息,作者还是一个大学生,应该是 00 后吧。顺便,Twikoo 用的消息推送 SDK 也是同一作者写的。年轻有为啊!
Twikoo 被许多简体中文独立博客所采用,搭建教程一大把。不少 serverless 平台提供一定的免费额度,足够运行 Twikoo 了,照着官方教程很快就能搭一个出来。我又写了一个脚本,把 Isso 的 SQLite 里的评论转成 Twikoo 的 JSON 格式再导入——家属的博客就这样从 Isso 迁移到了 Twikoo 评论系统。
发现了 Twikoo 的好,我也想给自己的博客换上。但作为一个 System Reboot Engineer,我对 serverless 平台的要求更高一些,我想要 IaC。家属的 Twikoo 是搭建在 Netlify 上的,而我一直在用 AWS 全家桶,为什么不试试在 AWS Lambda 上跑呢?尤其是两年前 AWS Lambda 增加了 Function URL 功能,不需要配置 API Gateway 了,使用起来更方便了。
Twikoo 本来没有专门对 AWS Lambda 做适配,于是我根据 AWS Lambda Function URL 的文档给上游贡献了一些代码,使它成功地在 AWS Lambda 上跑起来了。
AWS Lambda Function URL 的地址形如 https://axtoiiithbc3vetyqfgq7ozalu0cnkii.lambda-url.us-west-2.on.aws/
,真的太长太丑了!反正我的博客本来就在用 AWS CloudFront,干脆加到博客的 wzyboy.im
域名下,这样还能减少一次 CORS preflight 请求!
七年前我从 WordPress 迁移到静态博客的时候,没有迁移评论。后来用上了 Disqus 评论,我也没把 WordPress 评论导入进去。但是现在既然用上了一个数据操作更加方便的平台(指可以直连 MongoDB 进行操作),我就想把 WordPress 和 Disqus 的评论都导入到 Twikoo 里。
Twikoo 支持导入 WordPress 的评论,然而我的 WordPress 早在七年前就已经停服了。我一直留着数据库备份,与其把整个 WordPress 复活再用插件把评论导出,不如直接对数据库进行操作,导出成 Twikoo 的格式而不是 WordPress 的格式。于是我把七年前的数据库备份导入 MariaDB,再快速糊了一个 Python 脚本 将 wp_comments
表里评论导出成 Twikoo 使用的 JSON 格式,然后在 Twikoo 的管理界面导入进去。
Twikoo 也支持导入 Disqus 的评论。我从 Spam 里捞出 Disqus 给我发的评论导入邮件之后,一键导入 Twikoo,才发现这里面居然还有不少垃圾评论(在 Twikoo 里显示为隐藏评论,只有管理员能看到)。这里面有些是真的垃圾评论,有些是 Disqus 误报的。我在 Twikoo 里对这些垃圾评论进行了处理。另外 Disqus 导出的 XML 里不包含 email 字段,无法从 Gravatar 拉取头像。别人的评论没办法,我自己的评论还是可以二次处理一下的。于是把刚刚清理过后的评论再次导出,把我发表的评论都加上我自己的邮箱等信息,然后清空 MongoDB 重新导入,这样就有头像了。
至此,旧评论全部导入到了 Twikoo 里。一共从 WordPress 导入了 1734 条评论,从 Disqus 导入了 211 条评论。其中 WordPress 的评论也包括了 2009 年从 Blogger 导出的评论。
Twikoo 默认打开了展示 User-Agent 的功能,会显示评论者的操作系统和浏览器信息。翻看一下老评论,看到各种 Windows XP、Google Chrome 5.x、Android 1.2 啥的,感觉好怀念!仿佛回到了十几年前,一大批 WordPress 独立博客如雨后春笋遍地蓬勃生长的时代,那时候不少博客都装了一个显示评论者操作系统和浏览器信息的插件。
在我写作本文的时候我刚好读到一篇文章,讲因为中国大陆独特网络环境——内容审查、封闭花园、移动互联网兴起导致传统网页衰落——简体中文互联网上公开的内容,尤其是较旧的内容,正在快速消亡。本博客虽然近年来更新不多,但也已经存续了 15 年,我将尽我所能让它继续存在下去,不要轻易消亡。通过复活 2009 至 2017 年间的旧评论,我也希望能为对抗 link rot尽一份绵薄之力。
那么,欢迎在全新的评论系统里留下评论。《隐私声明》也已更新。
2024-05-10 23:46:38
本文记录一下我最近从 LUKS 迁移到 LUKS + LVM 的过程。整理是最好的复习!
Device mapper 是 Linux 里将块设备映射成虚拟块设备的框架。
dm-crypt 是用 DM 进行透明加密的组件。例如:将 /dev/sda2
映射成 /dev/mapper/cryptsda2
,则往 /dev/mapper/cryptsda2
这个块设备写入的数据会被加密后实际写入下层的 /dev/sda2
块设备里。
LUKS 是以 dm-crypt 为基础,增加了密钥管理功能的加密实现。
我的笔记本电脑是这样的分区结构:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme0n1 259:0 0 476.9G 0 disk
├─nvme0n1p1 259:1 0 512M 0 part /boot
├─nvme0n1p2 259:2 0 450.0G 0 crypt /
└─nvme0n1p3 259:3 0 26.4G 0 crypt [SWAP]
一个引导分区(p1),一个主分区(p2),一个交换分区(p3)。其中主分区是用 LUKS 加密的,需要我每次开机时输入密码进行解锁;交换分区是以 plain dm-crypt 加密的,其密钥来自 /dev/urandom
提供的随机数据。交换分区以随机密钥进行加密是一种常见做法,密钥只存在于 RAM 里,关机之后交换分区就完全无法解密了,防止 RAM 里的敏感数据留在交换分区里被读取——尤其是在异常关机的时候。
这样的加密交换分区有一个问题:无法休眠,确切地讲是能休眠,但是永远醒不来——因为断电之后密钥已经被丢弃了,所以重新开机的时候系统无法读取交换分区里的数据,所以无法恢复到之前的状态。
由于我的笔记本电脑几乎一直是插着电用,所以十几年来很少用到休眠的功能(更别提以前 Linux 休眠醒来之后网卡、扬声器等容易出 bug);偶尔要带出门的话,短时间我就睡眠,长时间我就直接关机。直到最近,由于一连串巧合,我的笔记本电脑没有插电,电池耗尽,系统自动尝试进入休眠状态——成功了,然后就再也醒不来了。
更糟糕的是,systemd 在系统启动时会等待交换分区出现,但因为永远等不到,所以会浪费两分钟等待直到超时。由于「从休眠中醒来」这个任务没有完成,所以下次重启电脑的时候,systemd 还会再等两分钟超时,周而复始。
我实在是不知道如何清除掉这个 flag 让它不要再等。最终我想了个解决方案:systemd 是根据 UUID 去找交换分区的,那我新建一个喂给它不就行了?于是我从日志里找到 systemd 苦等的 UUID,再用 mkswap -U that_uuid
建立一个 swap,再重启一次,果然它就不再等了。事成之后要记得 wipefs
擦掉分区签名,否则以后就一直是明文交换分区了。
结果这样的事情又发生了几次,每次我都要重启几次来修复。痛定思痛,我决定一劳永逸地解决这个问题,不然每次(不小心)触发休眠就会很麻烦。
我调研了多种方法,在虚拟机里尝试了一番,发现最简单的方法是用 LUKS + LVM。
LVM 也是基于 DM 的组件,主要用于在块设备上映射出多个逻辑卷(LV),这些 LV 类似于分区,但是不受分区表的限制,可以灵活地调整,甚至可以提供快照等功能。由于我的某些执念,我一直不愿意将两个 DM 套娃使用,因此我笔记本电脑上只有 LUKS,而 NAS 上只有 LVM。实际在虚拟机里测试了一下,发现 DM 叠叠乐也没什么大不了的,因此也就接受了。至于是将 LVM 叠在 LUKS 上,还是将 LUKS 叠在 LVM 上——当然是前者,因为后者和我现在的处境没什么太大的区别,并不能解决加密交换分区的问题。
所以我的分区调整计划是(对照前文的分区结构):
根据我在虚拟机里的试验,这样调整过后,开机时系统会先解开 LUKS,然后按需求(全新启动还是从休眠中恢复)读取 root 和/或 swap。
在折腾这些分区之前得先备份数据。我的主分区是 450 GiB,但只有 235 GiB 数据在里面。我有块 500 GB 的 SSD 移动硬盘可以暂存数据,这块移动硬盘里最大的一个分区是 377 GiB,倒是够存;但这分区没有加密,而且是 exFAT 文件系统,因此不适合把笔记本电脑里的数据直接复制进去。
那我把整个 LUKS 容器给 dd 进去?这就又太大了,而且由于加密数据块的信息熵极高,所以再怎么压缩也是塞不下的。要不在移动硬盘里创建一个 LUKS 容器然后把文件系统整个倒进去?但是我的笔记本电脑用的是 Ext4 文件系统,似乎并没有像 xfs_copy
那样只复制有用数据块的工具。我灵机一动,想到可以用 BorgBackup 直接直接读取 LUKS 解密后的明文块设备,由于 Borg repo 是加密的,所以可以存到不加密的移动硬盘里。
BorgBackup 甚至专门有个文档解释了这种用法:
zerofree
把 Ext4 文件系统里的没用的数据块归零——这工具比 dd if=/dev/zero
更环保、高效borg create --read-special repo::archive /dev/mapper/luks-xxxx
备份 Ext4 所在的块设备,那些被归零的数据块几乎不会占用存储空间borg extract --stdout repo::archive | dd of=/dev/mapper/xxxx
恢复 Ext4 到新的块设备上由于以下操作都是需要对系统分区进行操作,所以我是启动进 archiso 里操作的。在退出主系统之前,先把 /etc/fstab
和 /etc/crypttab
里即将没用的条目给注释掉,防止调整完后进系统时 systemd 又在那儿苦等。
第 2 步完成之后的分区调整命令(根据记忆默写;忘记屏摄了):
# 擦除 p2 上的 LUKS 签名防止被 cryptsetup 误读
wipefs -a /dev/nvme0n1p2
# 删除 p2 p3 并建立新的 p2
sgdisk -d 2 -d 3 -n 2 /dev/nvme0n1
# 在 p2 上创建 LUKS 容器
cryptsetup luksFormat /dev/nvme0n1p2
# 加载 LUKS 容器
cryptsetup open /dev/nvme0n1p2 lukslvm
# 初始化 LVM 并创建两个 LV
pvcreate /dev/mapper/lukslvm
vgcreate arch /dev/mapper/lukslvm
lvcreate -n root -l 450G lukslvm
lvcreate -n swap -L 100%FREE lukslvm
此时应该已经有 /dev/mapper/arch-root
和 /dev/mapper/arch-swap
两个 LV 了。它们的下层设备是 /dev/mapper/lukslvm
这个 LUKS 容器,而 LUKS 容器的下层设备是 /dev/nvme0n1p2
这个 SSD 的分区。这就是 DM 叠叠乐!
此时执行第 3 步,将之前备份的 Ext4 写入到 /dev/mapper/arch-root
上。写入成功后 file -sL /dev/mapper/arch-root
或 blkid
应该能观察到和原先一样的 UUID。
上述操作中,第 2 步耗时 53 分钟,450 GiB 的文件系统(已用 235 GiB)最终被去重和压缩成 162 GiB 的 Borg repo;第 3 步将压缩后的文件系统写回 450 GiB 的块设备里,耗时 143 分钟。
恢复完成之后,需要调整一下 boot loader 传递给内核的参数:
options rd.luks.uuid=5834fee0-d5f5-4985-aef1-c55d50bd069c rd.luks.options=discard root=UUID=e15bf41d-3922-49a8-abc2-7640f66e318c rw
其中 rd.luks.uuid=
是 LUKS 容器(上文的 /dev/mapper/lukslvm
)的 UUID,因为重建了容器,所以这个值需要更新;而 root=
是主分区的 UUID,因为我整个 Ext4 导出到导入,一个字节都没有动过,所以这个值是不变的。
除了更新内核参数,还要确保 initrd 里有 LVM 相关的组件。调整完成之后,退出 archiso 重启,成功进系统!
现在分区布局变成了这样:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme0n1 259:0 0 476.9G 0 disk
├─nvme0n1p1 259:1 0 512M 0 part /boot
└─nvme0n1p2 259:2 0 476.4G 0 part
└─luks-5834fee0-d5f5-4985-aef1-c55d50bd069c 254:0 0 476.4G 0 crypt
├─arch-root 254:1 0 450G 0 lvm /
└─arch-swap 254:2 0 26.4G 0 lvm [SWAP]
试试休眠……成功了!试试唤醒……也成功了!
再也不用小心翼翼害怕休眠了!
2024-01-18 18:38:26
以往都是在一年的最后几天写年度总结,但这篇 2023 年度总结却是拖到 2024 年才写。
2022 年年末的时候,由于不满 Elon Musk 对 Twitter 的管理,我像许多 Twitter 难民一样,将发表微博客的平台由 Twitter 转移到了 Fediverse。现在我使用 Fediverse 已经一年多了,感觉良好。我的 Fediverse 实例是自建的,计划是像本博客一样,至少运营十年。实例没有向公众开放注册,而是靠朋友之间口口相传,慢慢地增加了少量(不到十人)的用户入驻。有种盖了个楼自己先住进去,然后亲朋好友也都搬来成为邻居的感觉!
在 Fediverse 上,每条帖子不再限制只能 140 个字,因此有时候我本想水一篇博客,最终只是在 Fediverse 上发了一条较长的微博客。
2023 年四月份的时候,我和家属人生中第一次买房。七月份的时候搬家,之后就忙着各种装修和改造。以前租房的时候,想在墙上挂个东西也会受到房东的限制;现在有了自己的房子,自然是想怎么改造就怎么改造。趁着政府有补贴,我们把天然气取暖换成了电力驱动的热泵空调,把储水式热水器也换成了效率更高的即热式热水器。我自学了一些电工知识,拆开了家里各种开关盒和插座盒,甚至爬到阁楼上增加了新的电路,把家里的开关换成了智能开关,还在房间的天花板上钻孔并安装了吸顶灯。卧室的衣帽间看着也不顺眼,于是我们买了电动工具,把墙垛拆掉,改成了独立衣柜。更大一些的工程,则是请工人来更专业、更有效率地完成。
第一次买房和第一次装修,波折是少不了的。下半年花了很多时间和精力在这些事情,使得我大部分时间处在一个现实生活忙碌的状态。
综合上面两点及一些其他原因,2023 年我有好几个想写个博客的选题,最终未能成文:
整个流程的时间跨度太大,细节过多,无从下手,而且感觉与本博客的整体基调不搭,最终没写。
我一直在用 BackBlaze B2 作为便宜的对象存储,2023 年我尝试了一下它的旗舰产品——整机备份服务。尝试的原因是主要是我有一些重要性较低的数据不值得搞多重备份,但又不能没有备份,我就想着只搞一份异地备份。这些数据体积又较大,传统按容量收费的服务不是很划算。想到我本来就在用 BackBlaze B2,不如试试它不限容量的 Computer Backup 服务。
BackBlaze Computer Backup 是一个订阅制服务,每个授权可用于一台计算机,存储空间是无限的(所有插在电脑上的硬盘都可以备份,包括移动硬盘但不包括网络存储)。需要取回数据的时候,可以免费下载 zip 压缩包,也可以让他们给你快递一个移动硬盘(可退还)。我用了一下感觉体验很不错,新用户引导简洁明快,客户端也小巧灵动。唯一的缺点是不支持 Linux。
当时的价格是 $70/y,现在已经涨价到 $90/y 了如果有感兴趣的读者可以使用我的注册链接获取一个月免费试用(我也可以拿一个月免费时间)。
上一次配台式机还是 2016 年的事情了,时隔七年多,我趁着 Black Friday 配置了一台新的台式机。本来想多拍一些美美的照片,水一篇博客,但是因为装修问题,房间里比较乱,最后拼好了也懒得再拍照了。
我对电脑硬件不是很在行,在选购配件的过程中得到了不少友人的指点与帮助,在此特别感谢 @OrcaXS 的指导。
早在 Valve 刚推出 Proton 这个 Linux Gaming 大杀器的时候,我就听说 Linux 的游戏性能比 Windows 更好了,但是我一直没有正经试过——因为从 2008 年开始,我的 Linux 电脑一直是集显或是「亮机卡」,无论是什么操作系统都是没法好好玩游戏的。2023 年我配置了一台新的台式机,有了强劲的显卡(RTX 4070 Ti),也许可以考虑体验一下 Linux Gaming?友人向我推荐了 Bazzite 这个新鲜玩意儿。
Bazzite 的理念挺先进的,用 Fedora Kinoite 提供的 immutable 系统作为基础,增加一堆 Linux Gaming 所需的软件,还加上 Steam Deck 的 UI,拼出一个稳健且易用的系统。Bazzite 比起桌面操作系统,更像是个手机/游戏机的固件,整个系统作为一个整体升级,极大地减少各软件包之间 ABI 兼容性以及手动安装闭源显卡驱动的痛苦,实在出现问题了还能一键回滚。
然而我插了一块旧 SSD 到新电脑上,安装 Bazzite 实际试了下,发现 rpm-ostree 虽然理念先进,但实际上速度好慢哦。NVIDIA 的垃圾闭源驱动和 Wayland 相性也不好;开源驱动又不支持我的显卡。而且我用 Bazzite 不就是为了减少折腾获得一个开箱即用的体验吗?要是花了过多时间在折腾上,就有点本末倒置了。
算了算了,不折腾了。
2023 年我没有读什么新的小说,只是重读了几本以前读过的小说,还读了一些之前读的轻小说的续作。随着新的一季《无职转生》动画的上映,我把《无职转生》的轻小说从第 8 卷推到了第 20 卷。感想:第 15 卷开始剧情变得好看很多了。
影视方面,我看了不少 MCU 里的电视剧,印象最佳的是 WandaVision,之后的感觉一部不如一部。我还是挺喜欢 Marvel 的作品的,从 2008 年的 Iron Man 开始,我每一部 MCU 电影都没有错过,有些甚至专门去看了首映场。但近几年我感觉 MCU 电影的质量愈发下降了。最近的 The Marvels 我还没看,但是听说也是大烂片。
Steam 统计我 2023 年玩得时间最长的游戏——依然是 Factorio。年末假期的时候,我和几位朋友一起联机,开了一个五人局,还是挺欢乐的。
类似 Factorio 的工厂游戏 Satisfactory 在 2023 年末推出了 Early Access Update 8,加之打折,我便购入玩了一段时间。Early Access 多人模式的 bug 较多,且游戏内的剧情部分还在 WIP 感觉有点无聊,最终没有玩多久,还是回到了 Factorio 的怀抱。
《原神》我 AFK 了一段时间,但 4.0 版本枫丹上线之后,我又回归了——主线剧情还是想跟进一下的。HoYoverse 的新作《崩坏:星穹铁道》也在 2023 年正式开服了。我玩了几个月,感觉是比《原神》更轻松的叙事;一旦习惯了回合制战斗的设定,还挺好玩的。然而下半年由于现实生活的忙碌,我逐渐 AFK 了。
2023-08-23 06:17:07
说来惭愧,我直到最近,2023 年了,才终于正式用上了原生 IPv6 网络(之前只用过 Hurricane Electric 和 Cloudflare 的隧道)。十几年根深蒂固的 IPv4 思维让我在了解和学习 IPv6 的过程中充满了惊奇和欣喜。响应「整理是最好的复习」号召,我决定将我学到的知识整理成这篇博客文章。
本文试图用小黄鸭也能听懂的方式,从较为简单的 IPv4 基础知识开始由浅入深地讲到 IPv6。
IP 地址对于计算机来说是一串 0 和 1 组成的二进制数字。IPv4 地址是 32 bit 的,即由 32 个 0 和 1 组成。对于人类来说,常用的写法是把这 32 个 bit 分成 4 组,每组 8 bit,转成十进制,中间用点隔开——即所谓的「点分十进制」。因为每组是 8 bit,所以每个十进制数字的范围在 0 到 255 之间。
比如 Google 的 IPv4 地址(之一):
142.251.215.238
点分十进制用对人类比较友好的方式,简明地表达了从最小的 0.0.0.0 到最大的 255.255.255.255 一共 42 亿个地址。
一群计算机组成一个网络,这个网络中最小的地址用来表示这个网络本身。比如以下 256 个地址组成了一个网络:
142.251.215.0
142.251.215.1
142.251.215.2
...
142.251.215.253
142.251.215.254
142.251.215.255
……则用 142.251.215.0 表示这个网络本身。
CIDR 用来简明地表示一个 IP 地址与其在的网络的关系。上述网络中的某个地址 142.251.215.42 可以表示为:
142.251.215.42/24
其中 /24 代表前缀长度。在这个例子的 256 个地址中,点分十进制的前三段都是相同的,变化的只是最后一段。前三段每段是 8 bit,总共是 24 bit 用于表示网络,因此前缀长度是 /24。前缀长度越大,固定的 bit 越多,变化的 bit 越少,这个网络就越小。此处前缀长度是 /24,则可变的部分是 8 bit,总共 256 个地址,符合预期。
在 IPv4 中,用 CIDR 可以表示从 /0 到 /32 各种大小的网络,其中 /0 代表整个 IPv4 地址空间,/32 代表大小为 1 的网络。
IPv6 地址的写法与 IPv4 不同,似乎没有一个专门的名称。硬要和 IPv4 对应的话,我会把它叫作「冒号分隔的十六进制」。IPv6 地址是 128 bit 的,长度是 IPv4 地址的 4 倍,人类将其分成 8 组,每组 16 bit,转成十六进制数字,再用冒号隔开。
比如 Facebook 的 IPv6 地址(之一):
2a03:2880:f101:0083:face:b00c:0000:25de # 注意其中有 face:b00c 这样的彩蛋
每段开头的零可以省略,并且连续的全部是零的段可以用双冒号省略,比如:
2001:0db8:0000:0000:0000:0000:0000:0042
……可以简写成
2001:db8::42
CIDR 的写法与 IPv4 是一样的,即在地址后面加上斜线和数字代表前缀长度。由于 IPv6 有 128 bit,所以前缀长度从 /0 到 /128 不等。
IPv4 地址由 32 个 bit 组成,所以总地址空间是 2³²,约等于 42 亿,去掉一些保留地址,实际可用的数量要少一些。理想环境下,每台能上网的设备都应该分到一个 IP 地址,但现在全球网民数量都不止 42 亿,更别提很多人还有多个上网设备,还有很多非人类的上网设备(IoT),所以这 42 亿地址是肯定不够用的。为了解决这个问题,人类发明了 NAT 这种邪恶的存在。
在理想世界里,每个家庭根据上网设备的数量分到一个对应大小的网络,家庭网络管理员把将这个网络里的地址分发给各个上网设备使用。在互联网的田园时代,当年的网民们就是这么分的。比如 1990 年时候 Apple 公司分得了 17.0.0.0/8 这个网络。根据上文的知识计算可得,这个网络有约 1678 万个 IP 地址,非常巨大。像这样巨大的网络,美国国防部分到了 14 个。还有很多类似的大网络被互联网起源地美国的公司和大学等机构瓜分(后来有些机构退还了一些)。
一共 42 亿地址,早年财大气粗地分配,后来全球网民数量又爆炸式增长,所以 IPv4 地址数量很快就不够分了。一个家庭没法再根据上网设备数量分配到对应数量的地址了,取而代之的是,运营商给一个家庭只分配一个地址,然后由路由器给家里的上网设备分配一套另一个网络里的地址只用于家庭内部通信。当家里的设备需要和外界通信的时候,就紧巴巴地共享运营商给的那个地址。这种情况下,家里那套地址就被称为内网地址,外部的地址就被称为外网地址或公网地址。理论上内网地址用什么都可以,但如果正好和公网某个网站相同,那就冲突了,所以内网地址通常是使用保留地址如 192.168.0.0/16 里的地址。这些保留地址不会被任何公网网站使用,因此不会有冲突的风险。
为什么 NAT 的邪恶的?因为上述多个设备可怜兮兮地共享一个地址的方案只能用于访问别人,不能用于被别人访问。生活在 NAT 背后的设备在网络上低人一等,它们无法直接被外网设备访问,而要通过端口转发、NAT 打洞、反向代理等各种辅助方式才能有限程度地被访问到。
NAT 只是暂时缓解 IPv4 不够的问题。刚刚说到运营商给每个家庭只分配一个公网地址,当这户人家不上网的时候,这个地址甚至可以被分配给别的家庭。但随着接入信息高速公路的家庭数量越来越多,运营商连每个家庭一个公网地址都给不起了。最终 CGNAT 被开发出来了——运营商层面再做一次 NAT。
什么比 NAT 更邪恶?多层 NAT。
小时候一直听说 IPv6 地址空间非常庞大,类似「整个宇宙每一颗沙粒都能分到一个地址」这种类比。但我实际学习了 IPv6 的应用之后,我发现 IPv6 地址空间的确是很大,但并不是每个地址都能用来分给沙粒。
IPv4 组建的家庭网络常见的前缀长度是 /24,这样的网络有 256 个地址,可供 200 多台设备上网。由于不同的设备必须使用不同的地址,网络管理员需要精准地管理这些地址。DHCP 通常被用于自动分配 IPv4 地址。新接入网络的设备(比如通过 Wi-Fi 接入的手机)向 DHCP 服务器(通常在路由器上)请求一个地址,DHCP 服务器从地址池里挑选一个空闲的地址租给上网设备,并保证该在其租期内不分配给其他设备,以免造成冲突。
IPv6 组建的家庭网络中常见的前缀长度是 /64,这也是标准规定的最小的网络尺寸。这样的网络有 2⁶⁴ = 18446744073709551616 ≈ 1.84 × 10¹⁹ 个地址。地址数量是如此之多,以至于根本不需要 DHCP 那样的中心化管理机制!目前 IPv6 常见的地址分配方式是 SLAAC,即让上网设备自己随机生成一个,然后再检测一下这个地址是不是已经有人用了。由于 /64 的 IPv6 网络实在是太大了,所以只要生成算法够随机,第一次生成的地址几乎一定是没人用的。
支持 IPv6 的运营商会分配一个 /64 甚至 /56 的网络给家庭路由器,于是 128 bit 的前一半就确定了。家庭路由器通过 PD (prefix delegation) 向家里的设备宣布「请在这个 /64 网络里随机挑选一个地址」,设备随机生成了后一半的地址,拼上路由器给的前一半,就得到了完整的 128 bit 的 IPv6 地址。设备有了这个地址之后,就可以开始上网了。并且这个地址是全球唯一的公网地址,一切仿佛回到了互联网田园时代那样,每个设备都有公网地址,每个设备在网络上都能被访问到!
习惯了贫瘠的 IPv4 地址空间的我,第一次了解到 SLAAC 的时候非常震惊。在 IPv4 里,家庭路由器能分到一个珍贵的公网地址已经很不容易了,想要更多的地址往往要加钱。而在 IPv6 里,运营商直接给路由器发 /56 的网络,即 256 个 /64 网络,而一个 /64 网络就有 2⁶⁴ 个地址,是整个 IPv4 地址空间(2³²)的无数倍,大到可以在里面随机挑选地址用而不碰撞,并且所有的地址都是公网地址…… o_O
NAT 的一个副产物是天然防火墙。生活在 NAT 后面的内网设备不能直接被公网设备访问到,默认也就阻隔了绝大多数来自公网的网络攻击。NAT 的这一副产物在家庭网络中有一定的好处,但同时也惯坏了一些人(比如我),觉得躲在 NAT 后面,不需要防火墙也可以躲避来自互联网的网络攻击。
然而 IPv6 网络是没有 NAT 的(严格来说有,但不是脑子正常的人应该配的)。一切就像田园时代的互联网一样,每台上网设备都有一个全球唯一的 IP 地址,所有设备理论上都能访问到其他设备。为了不让坏人访问家里设备,网络管理员应当在路由器上配置 IPv6 防火墙,只放行合法的流量。
但从另一个角度来说,只要防火墙允许,任意两个 IPv6 设备之间都可以互联。想在家里搭个网站不再需要搞端口转发或反向代理之类的东西了,只要有 IPv6 地址,然后在防火墙上加一条规则就行了——前提是你的网站的访客也得使用 IPv6。
上文说到,家庭网络中上网设备的 IPv6 地址由路由器给的前半段,加上自己随机生成的后半段组成。在早期标准中,后半段是由网卡的 MAC 地址衍生的。由于网卡地址是固定的,最终生成出来的 IPv6 地址也是固定的。对于机房里的一台服务器来说,这样生成出来的地址填到 DNS 里,就可以让全球的上网设备通过 IPv6 访问自己了。
这对服务器来说是省配置的好事,但对普通网民来说就不一定了。由于后半段固定,哪怕网民更换运营商,或是移动到别的网络(如手机和笔记本电脑使用不同场所的 Wi-Fi),其 IPv6 地址的后半段都是一样的,这使得网站可以长期追踪用户。
为了解决这个隐私问题,现在主流操作系统一般使用双地址来解决这个问题——一个相对固定的 IPv6 地址用来供别人访问,一个随机生成并定期更换的 IPv6 地址用来上网。
IPv6 的「冒号分隔的十六进制」写法要比 IPv4 的「点分十进制」长不少,但同时,CIDR 的计算变得更加容易了。在点分十进制里,每段是 8 bit,因此只有当前缀长度是 8 的倍数的时候,网络与主机的分割线才划在「点」的位置。除了 /24 和 /16 这种阅读起来比较舒服的前缀长度,诸如 /20 和 /28 这种也是很常见网络 IPv4 前缀长度。由于这时候这时候分割线并不在点的位置,分出来的子网也就没那么直观了。我每次都记不住而用 ipcalc(1)
去算。
IPv6 有 128 bit,所以大家分网的时候也没那么抠门,从最小的 /64 往上,至少都是每次 8 bit 增长,只要是 4 的倍数,都能干净地分割到字符边界,阅读和计算起来很方便。
SLAAC 生成的地址是随机的,往往不怎么能简写。对于一些网络服务,比如 DNS 来说,往往需要一个简短又好看的地址方便人类记忆,这时候往往就是从庞大的地址空间里手动指定一个 IPv6 地址了。比如 Google Public DNS 的 IPv6 地址是:
# 简写
2001:4860:4860::8888
2001:4860:4860::8844
# 完整写法
2001:4860:4860:0000:0000:0000:0000:8888
2001:4860:4860:0000:0000:0000:0000:8844
通过选取有大量连续零的地址,Google 获得了简写较短的 IPv6 地址。其最后一段的 8888
和 8844
则是对应其 IPv4 地址 8.8.8.8
和 8.8.4.4
,更加方便记忆。
由于 IPv6 地址通常使用十六进制数字书写,这 a-f
六个英文字母也可以被用来整活。比如上述 Facebook 的地址就嵌入了 face:b00c
这样的彩蛋。
对于想在手动指定的 IPv6 地址上整活的读者来说,可以参考 Hexspeak 获取灵感。