FreeBSD 中文社区 2025 第二季度问卷调查
FreeBSD 中文社区(CFC)
VitePress 镜像站QQ 群 787969044视频教程Ⅰ视频教程Ⅱ
  • FreeBSD 从入门到追忆
  • 中文期刊
  • 状态报告
  • 发行说明
  • 手册
  • 网络文章集锦
  • 笔记本支持报告
  • Port 开发者手册
  • 架构手册
  • 开发者手册
  • 中文 man 手册
  • 文章
  • 书籍
  • FreeBSD 中文期刊
  • 编辑日志
  • 2025-123 下游项目
    • FreeBSD 发布工程:新主管上任
    • GhostBSD:从易用到挣扎与重生
    • BSD Now 与将来
    • 字符设备驱动教程(第三部分)
    • 学会走路——连接 GPIO 系统
    • FreeBSD 中对 SYN 段的处理
    • FreeBSD 2024 年秋季峰会
  • 2024-1112 虚拟化
    • 字符设备驱动程序教程(第二部分)
    • 面向 Linux 和 Windows 用户的 bhyve
    • Xen 与 FreeBSD
    • Wifibox:一种嵌入式虚拟化无线路由器
    • 嵌入式 FreeBSD:Fabric——起步阶段
    • DGP:一种新的数据包控制方法
    • 会议报告:我在都柏林的 EuroBSDCon 体验
  • 2024-0910 内核开发
    • 字符设备驱动程序教程
    • VPP 移植到了 FreeBSD:基础用法
    • 利用 Kyua 的 Jail 功能提升 FreeBSD 测试套件的并行效率
    • FreeBSD 上的 Valgrind
    • 嵌入式 FreeBSD:探索 bhyve
    • TCP/IP 历险记:FreeBSD TCP 协议栈中的 Pacing
    • 实用软件:实现无纸化(Paperless)
  • 2024-0708 存储与文件系统
    • FreeBSD 中的 NVMe-oF
    • FreeBSD iSCSI 入门
    • 使用 ZFS 原生加密保护数据
    • 嵌入式 FreeBSD:打造自己的镜像
    • TCP LRO 简介
    • 基于 Samba 的时间机器备份
  • 2024-0506 配置管理对决
    • 基本系统中的 mfsBSD
    • rdist
    • Hashicorp Vault
    • 在 GitHub 上向 FreeBSD 提交 PR
    • 悼念 Mike Karels
    • 2024 年 5-6 月来信
    • 嵌入式 FreeBSD 面包板
    • TCP/IP 历险记:TCP BBLog
    • 实用软件:开发定制 Ansible 模块
  • 2024-0304 开发工作流与集成
    • FreeBSD 内核开发工作流程
    • FreeBSD 与 KDE 持续集成(CI)
    • 更现代的内核调试工具
    • 从零开始的 ZFS 镜像及 makefs -t zfs
    • 提升 Git 使用体验
  • 2024-0102 网络(十周年)
    • FreeBSD 中的 RACK 栈和替代 TCP 栈
    • FreeBSD 14 中有关 TCP 的更新
    • if_ovpn 还是 OpenVPN
    • SR-IOV 已成为 FreeBSD 的重要功能
    • FreeBSD 接口 API(IfAPI)
    • BATMAN:更优的可移动热点网络方式
    • 配置自己的 VPN——基于 FreeBSD、Wireguard、IPv6 和广告拦截
    • 实用软件:使用 Zabbix 监控主机
  • 2023-1112 FreeBSD 14.0
    • LinuxBoot:从 Linux 启动 FreeBSD
    • FreeBSD 容器镜像
    • 现在用 Webhook 触发我
    • 新的 Ports 提交者:oel Bodenmann (jbo@freebsd.org)
  • 2023-0910 Port 与软件包
    • 回忆录:与 Warner Losh(@imp)的访谈
    • 在你自己的仓库中定制 Poudriere 源
    • Wazuh 和 MITRE Caldera 在 FreeBSD Jail 中的使用
    • PEP 517
    • CCCamp 2023 旅行报告
  • 2023-0708 容器与云
    • 在 Firecracker 上的 FreeBSD
    • 使用 pot 和 nomad 管理 Jail
    • 会议报告:C 与 BSD 正如拉丁语与我们——一位神学家的旅程
    • 抒怀之旅:与 Doug Rabson 的访谈
    • 基于 Jail 的广告拦截教程
    • 我们收到的来信
  • 2023-0506 FreeBSD 三十周年纪念特刊
    • CheriBSD 近十多年的历程
    • AArch64:成为 FreeBSD 新的一级架构
    • 岁月如梭:我个人的时间线
    • 安装 FreeBSD 1.0:回顾 30 年前
    • ZFS 是如何进入 FreeBSD 的呢?
    • 我不是来自约克郡的,我保证!
    • 回忆录:采访 David Greenman Lawrence
    • FreeBSD 和早期的 Unix 社区
    • 早期的 FreeBSD 移植
    • FreeBSD 30 周年:成功的秘诀
    • FreeBSD 在日本:回忆之旅与今日之实
  • 2023-0304 嵌入式
    • CheriBSD port 和软件包
    • 让我们来试试 ChatGPT
    • GPU 直通
  • 2023-0102 构建 FreEBSD Web 服务器
    • ZFS 的原子 I/O 与 PostgreSQL
    • 虚拟实验室——BSD 编程研讨会
    • ZFS 简介
    • 会议报告:落基山庆祝女性计算机科学家
    • 进行中的工作/征求反馈:数据包批处理
    • 基金会与 FreeBSD 桌面
  • 2022-1112 可观测性和衡量标准
    • 在 FreeBSD 的 DDB 内核调试器中编写自定义命令
    • DTrace:老式跟踪系统的新扩展
    • 基于证书的 Icinga 监控
    • 活动监控脚本(activitymonitor.sh)
    • 实用 IPv6(第四部分)
    • EuroBSDCon 会议报道
    • 实用 Port:Prometheus 的安装与配置
    • 书评:《用火解决问题:管理老化的计算机系统(并为现代系统保驾护航)》Kill It with Fire: Manage Aging Computer Systems (and Future Proof Modern Ones)
  • 2022-0910 安全性
    • CARP 简介
    • 重构内核加密服务框架
    • PAM 小窍门
    • SSH 小窍门
    • 实用 IPv6(第三部分)
    • 书评:Understanding Software Dynamics(深入理解软件性能——一种动态视角)—— Richard L. Sites 著
    • 访谈:保障 FreeBSD 安全性
    • MCH 2022 会议报告
  • 2022-0708 科研、系统与 FreeBSD
    • 在 FreeBSD 上构建 Loom 框架
    • 教授本科生 Unix 课程
    • FreeBSD 入门研讨会
    • 实用 IPv6(第二部分)
    • 在 2022 年及以后推广 FreeBSD
    • 进行中的工作/征求反馈:Socket 缓冲区
    • FreeBSD 开发者峰会报告
    • 支持 Electromagnetic Field 2022
  • 2022-0506 灾难恢复
    • 使用 FreeBSD 构建高弹性的私有云
    • LLDB 14 —— FreeBSD 新调试器
    • 实用 IPv6(第一部分)
    • 利用 netdump(4) 进行事后内核调试
    • 进行中的工作/征求反馈:FreeBSD 启动性能
    • 实用 Port:在 OpenZFS 上设置 NFSv4 文件服务器
  • 2022-0304 ARM64 是一级架构
    • FreeBSD/ARM64 上的数据科学
    • Pinebook Pro 上的 FreeBSD
    • 嵌入式控制器的 ACPI 支持
    • 进行中的工作/征求反馈:Lumina 桌面征集开发人员
    • 实用 Port:如何设置 Apple 时间机器
  • 2022-0102 软件与系统管理
    • 为 FreeBSD Ports 做贡献
    • 使用 Git 贡献到 FreeBSD Ports
    • CBSD:第一部分——生产环境
    • 将 OpenBSD 的 pf syncookie 代码移植到 FreeBSD 的 pf
    • 进行中的工作/征求反馈:mkjail
    • 《编程智慧:编程鬼才的经验和思考》(The Kollected Kode Vicious)书评
    • 会议报告:EuroBSDCon 2021 我的第一次 EuroBSDCon:一位新组织者的视角
  • 2021-1112 存储
    • 开放通道 SSD
    • 构建 FreeBSD 社区
    • 与完美操作系统同行 27 年
    • 进行中的工作/征求反馈:OccamBSD
    • 通过 iSCSI 导入 ZFS ZIL——不要在工作中这样做——就像我做的那样
  • 2021-0910 FreeBSD 开发
    • FreeBSD 代码审查与 git-arc
    • 如何为 FreeBSD 实现简单的 USB 驱动程序
    • 内核开发技巧
    • 程序员编程杂谈
  • 2021-0708 桌面/无线网
    • 通往 FreeBSD 桌面的直线路径
    • FreeBSD 13 中的人机接口设备 (HID) 支持
    • Panfrost 驱动程序
    • 用 Git 更新 FreeBSD
    • FreeBSD 的新面孔
    • 想给你的桌面加点佐料?
  • 2021-0506 安全
    • 七种提升新安装 FreeBSD 安全性的方法
    • copyinout 框架
    • 使用 TLS 改善 NFS 安全性
    • Capsicum 案例研究:Got
    • 对 Jail 进行安全扫描
  • 2021-0304 FreeBSD 13.0
    • 展望未来
    • FreeBSD 13.0 工具链
    • FreeBSD 13.0 中有新加载器吗?
    • TCP Cubic 准备起飞
    • OpenZFS 中的 Zstandard 压缩
    • 会议报告:FreeBSD 供应商峰会
    • Git 不够吗?
  • 2021-0102 案例研究
    • Tarsnap 的 FreeBSD 集群
    • BALLY WULFF
    • Netflix Open Connect
    • FreeBSD 的新面孔
    • 写作学者的 FreeBSD
    • 在世界之巅
  • 2020-1112 工作流/持续集成(CI)
    • FreeBSD Git 快速入门
    • 使用 syzkaller 进行内核 Fuzzing
    • Mastering Vim Quickly 书评
    • 线上会议实用技巧
    • 在控制台上进行网络监控
  • 2020-0910 贡献与入门
    • 采访:Warner Losh,第 2 部分
    • 代码审查
    • 撰写良好的提交消息
    • 如何在不是程序员的情况下做出贡献——成为 FreeBSD 译者
    • 如何成为文档提交者
    • 谷歌编程之夏
    • 为 FreeBSD 期刊撰写文章
    • 你为什么使用 FreeBSD
    • FreeBSD 的新面孔
  • 2020-0708 基准测试/调优
    • FreeBSD Friday
    • 采访:Warner Losh,第 1 部分
    • 构建和运行开源社区
    • 在 FreeBSD 上轻松搭建我的世界(Minecraft)服务器
    • FreeBSD 的新面孔
  • 2020-0506 网络性能
    • 内核中的 TLS 卸载
    • 访谈:Michael W Lucas
    • FreeBSD 桌面发行版
    • 使用 Poudriere 进行 Port 批量管理
    • FreeBSD 的新面孔
由 GitBook 提供支持
LogoLogo

FreeBSD 中文社区(CFC) 2025

在本页
  • 获得 IPv6 互联网访问的另一种方法
  • Hurricane Electric IPv6 Tunnel Broker
  • 服务账户注册
  • 网络参数
  • 在你的 FreeBSD 设备上的配置
  • 在 /etc/rc.conf 中配置
  • 在基本工具中使用 IPv6
  • 一般规则与注意事项
  • 更多实际示例
  • 在 /etc/resolv.conf 中配置 DNS 服务器
  • NFS 与 /etc/exports
  • Sendmail
  • Syslogd
  • 总结
  • 附注
在GitHub上编辑
导出为 PDF
  1. 2022-0910 安全性

实用 IPv6(第三部分)

上一页SSH 小窍门下一页书评:Understanding Software Dynamics(深入理解软件性能——一种动态视角)—— Richard L. Sites 著

最后更新于1个月前

  • 原文链接:

  • 作者:佐藤広生

上期专栏介绍了 IPv6 的典型部署示例,适用于只有一台上行路由器的小型网络,例如家庭网络。但其中没有涉及某些复杂的配置(比如 DHCPv6/PPPoE),因为在此之前我们需要先掌握一些 IPv6 的技术知识。在深入讨论这些复杂情况之前,让我们先通过配置你的 FreeBSD 设备来进一步了解 IPv6。本专栏将重点讨论以下两个主题:当你的 ISP 无法提供 IPv6 互联网访问时该如何处理,以及如何在 FreeBSD 基本系统中配置必备的 IPv6 实用工具。

获得 IPv6 互联网访问的另一种方法

上期专栏中的部署场景假设你的 ISP 提供 IPv6 服务。在这种情况下,你的 ISP 与家庭网络之间的路由器会拥有一个 IPv6 全球单播地址(GUA¹)。你只需配置一个或多个 IPv6 地址,并将 IPv6 默认路由地址指向该路由器即可。

那么,如果你无法获得 IPv6 服务该怎么办?虽然提供 IPv6 服务给终端用户的 ISP 数量在不断增加,但截至 2022 年,大多数 ISP 的 IPv6 服务仍然属于可选项,并非其主要服务之一。获得 IPv6 互联网访问的一种方法是使用隧道连接。图 1 展示了“隧道传输”的工作原理:

  • 网络 A 是一个拥有 IPv6 互联网访问的 IPv6 网络;

  • 网络 B 是一个孤立的 IPv6 网络。

如果两个网络的终端都拥有 IPv4 地址,它们就可以通过 IPv4 互联网互相连接。隧道传输是一种协议转换技术,它将一个数据包封装在另一种协议的载荷中传输。也就是说,IPv6 数据包可以通过 IPv4 协议(如 IPv4 TCP 或 IPv4 UDP)进行传输。如果你熟悉 VPN(虚拟专用网络)的概念,那么你可以将隧道传输视作 VPN 的技术基础。待隧道建立,网络 B 上的主机便可以通过网络 A 访问 IPv6 互联网。

图 1:通过 IPv4 通信连接的 IPv6 网络

几个隧道服务支持 IPv6-over-IPv4 隧道传输,而且这些服务大多是免费的。其中一个可靠的服务——Hurricane Electric IPv6 Tunnel Broker,将在下面的小节中进行说明。

Hurricane Electric IPv6 Tunnel Broker

Hurricane Electric 是一家总部位于加利福尼亚的互联网服务提供商,主要提供互联网中转、数据中心托管以及主机服务。他们的网络覆盖规模堪称全球最大。通常,在文章中介绍这种具体的互联网服务是不合适的,因为信息很快就会过时。不过,HE 的 IPv6 隧道传输服务已持续维护了 20 多年,对于那些没有原生 IPv6 访问的人来说,它一直是一个不错的测试环境。因此,作者推荐将其作为实验性获取 IPv6 互联网访问的一种方式。虽然你不能假设其可靠性和性能与 ISP 提供的原生 IPv4 互联网连接完全相同,但 HE 的服务表现良好,至少对个人使用来说足够。而且,另一个优点是 HE 提供一个 /48 的 IPv6 地址前缀。/48 是 ISP 推荐的前缀长度,以便其终端用户可以利用 16 位划分享有多个局域网(LAN);然而,许多 ISP 仅提供一个或两个 /64 前缀。

接下来,让我们看看如何在你的 FreeBSD 设备上配置隧道传输。

服务账户注册

隧道传输使用你网络中的一个端点和 HE 网络中的另一个端点。在这两者之间,将通过 IPv4 互联网建立一个虚拟网络。你这边的端点,即 FreeBSD 设备,将作为 IPv6 路由器。作为前提,你的 FreeBSD 设备必须拥有一个全球可达的 IPv4 地址。该隧道传输使用协议号为 41 的 IP 数据包。这个协议号与 IPv6 相同,因此数据包过滤防火墙不太可能会阻止它们。你必须避免使用 IPv4 私有地址空间(10.0.0.0/8、172.16.0.0/12 或 192.168.0.0/16)进行 IPv4 网络地址转换(NAT)。

网络参数

在“Tunnel Details”(隧道详情)页面上,会显示四个 IP 地址,分别为“Server IPv4 Address”(服务器 IPv4 地址)、“Server IPv6 Address”(服务器 IPv6 地址)、“Client IPv4 Address”(客户端 IPv4 地址)和“Client IPv6 Address”(客户端 IPv6 地址)。

  • Server IPv4 Address 是 HE 那边端点的地址;

  • Server IPv6 Address 则是你网络中应使用的 IPv6 默认路由器地址;

  • Client IPv6 Address 是你端点的地址。

请注意,你需要了解两个网络——一个是两个路由器之间的网络(该网络是虚拟的),另一个是你的局域网(LAN)。详见图 2。图中黄色圆圈代表一个接口。这两个网络由你的路由器分隔开,该路由器在本配置中同时作为两个端点,因此你将获得两个 IPv6 前缀。你可以看到服务器和客户端的 IPv6 地址位于同一子网前缀中,即这就是两个端点之间的虚拟网络。你的 IPv6 局域网的前缀显示为“Routed IPv6 Prefixes”。你可以将其配置到路由器的 LAN 侧。默认情况下,你会获得一个 /64 前缀。点击“Routed /48 prefix”按钮后,除了 /64 前缀之外,你还会获得一个 /48 前缀。

图 2:HE 的网络与你的网络之间的隧道传输

现在你已经可以开始配置你的 FreeBSD 设备了。

在你的 FreeBSD 设备上的配置

在“隧道详情”页面中,有一个“示例配置”标签页,你可以看到一个适用于 FreeBSD 4.4 或更高版本的配置示例,如下所示:

# ifconfig gif0 create
# ifconfig gif0 tunnel IPV4-CLIENT IPV4-SERVER
# ifconfig gif0 inet6 IPV6-CLIENT IPV6-SERVER prefixlen 128
# route -n add -inet6 default IPV6-SERVER
# ifconfig gif0 up

诸如 IPV4-CLIENT 这样的关键字表示那四个参数。这个示例并没有错误,但下面这个版本更好。

# ifconfig gif0 create
# ifconfig gif0 inet tunnel IPV4-CLIENT IPV4-SERVER
# ifconfig gif0 up
# ping6 ff02::1%gif0
(按 Ctrl-C)
# ifconfig gif0 inet6 IPV6-CLIENT IPV6-SERVER prefixlen 128
# route -n add -inet6 default IPV6-SERVER
# ifconfig bge0 inet6 ROUTED-IPV6-PREFIX/64
# sysctl net.inet6.ip6.forwarding=1

同样地,一个具有相同传输协议的 IPv6 数据包由三部分组成,不同之处在于第一部分。

如果我们将 IPv6 数据包视为 IPv4 数据包的数据,那么我们就可以通过 IPv4 网络传输 IPv6 数据包。在发送端,一台路由器构建一个包含 IPv6 数据包的 IPv4 数据包;而在接收端,另一台路由器提取出其中的 IPv6 数据包。当使用 gif(4) 接口时,这一过程就发生在 HE 的路由器和你的路由器之间。实际上,将 IPv6 数据包封装到 IPv4 数据包中,是通过在 IPv6 数据包前面加上一个 IPv4 头来完成的,如图 3 所示,因为传输层的头部几乎都是相同的。

要配置此接口,你需要两组地址。首先,必须使用命令 ifconfig gif0 create 创建一个新的 gif(4) 接口。接着,可以使用 ifconfig(8) 工具中的“tunnel”关键字,并为两个端点配置地址来设置隧道传输。第一个地址是你的,第二个地址是 HE 的。

图 3:gif(4) 接口中使用的封装

之后,一个虚拟网络就建立起来了。请注意,这个虚拟网络没有连接状态,比如“已连接”或“已断开”。数据包仅在两个 IPv4 地址之间按需以“IP 数据报”的形式发送。一个 IPv6 数据包会被封装(如图 3 所示),作为 IPv4 数据包发送到 HE 的端点,并在 HE 的网络中被解封。虽然 IPv4 数据包可能在互联网的某处丢失,但错误恢复是由上层协议完成的,即 IP 数据报内部的 IPv6 数据包。用于隧道传输的地址通常被称为“外层协议地址”,在此案例中,外层协议是 IPv4。

要检查虚拟网络是否正常工作,你可以发送一个 IPv6 ping。在示例配置的第二行之后,输入 ifconfig gif0 up,然后使用 gif0 自动配置的链路本地地址(LLA)尝试发送 IPv6 ping。

# ifconfig gif0 create
# ifconfig gif0 tunnel IPV4-CLIENT IPV4-SERVER
# ifconfig gif0 up
# ping6 ff02::1%gif0
PING6(56=40+8+8 bytes) fe80::80c8:4a75:123a:8a32%gif0 --> ff02::1%gif0
16 bytes from fe80::80c8:4a75:123a:8a32%gif0, icmp_seq=0 hlim=64 time=0.084 ms
16 bytes from fe80::4a52:2e06%gif0, icmp_seq=0 hlim=64 time=4.765 ms(DUP!)
16 bytes from fe80::80c8:4a75:123a:8a32%gif0, icmp_seq=1 hlim=64 time=0.081 ms
16 bytes from fe80::4a52:2e06%gif0, icmp_seq=1 hlim=64 time=2.738 ms(DUP!)
ˆC
--- ff02::1%gif0 ping6 statistics ---
2 packets transmitted, 2 packets received, +2 duplicates, 0.0% packet loss
round-trip min/avg/max/std-dev = 0.081/1.917/4.765/1.970 ms

如果你收到“(DUP!)”响应,则说明虚拟网络运行正常。这是因为你应该会收到来自 HE 那边路由器的回复以及来自 gif0 接口本身的回复。如果你未收到来自端点另一侧的响应,请仔细检查两个端点之间配置的 IPv4 地址以及数据包过滤规则。

接下来,你需要配置用于通信的实际 IPv6 地址。这可以通过 ifconfig(8) 工具完成,如示例配置的第六行所示。该行配置了一个仅包含两个 IPv6 节点的点对点网络。此时,你可以向 IPV6-SERVER 发送 IPv6 ping。

如果你仅希望从该设备访问 IPv6 互联网,上述配置就足够了。此时,你的 FreeBSD 设备就可以作为一个 IPv6 主机节点工作。如果要使其成为你 /64 和 /48 局域网的路由器,则需要将默认的 IPv6 路由配置为指向 IPV6-SERVER,并启用 IPv6 数据包转发功能。示例中的下一部分就是用来实现这一点的。

# route -n add -inet6 default IPV6-SERVER
# ifconfig bge0 inet6 ROUTED-IPV6-PREFIX/64
# sysctl net.inet6.ip6.forwarding=1

该配置假设面向局域网 (LAN) 的接口为 bge0。ROUTED-IPV6-PREFIX 是 HE 服务分配给你的前缀,你应该同时拥有 /64 和 /48。你可以在同一接口上配置两者,也可以分配到不同的接口。

在这里,你需要考虑一个问题:应该使用什么 IID⁵?也就是 LAN 上路由器的地址。

你可能已经注意到,在隧道接口上使用的 IPv6 地址的 IID 分别是 ::1 和 ::2,这是一种可行的策略。然而,作者建议为简化起见,使用全零地址。如果你从 HE 获得了 2001:db8::/48,可以选择该范围内的一个 /64 网络,例如 2001:db8:1::/64,并将其配置为路由器地址。此时,IID 设为全零。

这可能会让你感到不安,因为在 IPv4 中,全零的主机地址具有特殊含义。虽然 RFC 或其他规范未明确定义,但一些传统网络实现将其视为广播地址,而非单播地址。然而,在 FreeBSD 上,全零主机地址不会有任何问题。但如果你是在 20 世纪学习的 TCP/IP 网络,可能已经习惯性地避免使用它。在 IPv6 中,全零 IID 是完全合法的。实际上,使用全零地址作为路由器地址还有其他优点,不过这些将在后续专栏中进一步讨论。

在配置了默认路由器和 LAN 上的路由器地址后,你就可以配置 LAN 上的主机了。你可以参考上一期专栏,了解可以采取的选项。建议在 bge0 上运行 rtadvd(8) 以启用自动配置。

在 /etc/rc.conf 中配置

待确认 IPv6 隧道可以正常工作,你应该将手动输入的配置添加到 /etc/rc.conf。

cloned_interfaces="gif0"
ifconfig_gif0="inet tunnel IPV4-CLIENT IPV4-SERVER"
ifconfig_gif0_ipv6="inet6 IPV6-CLIENT IPV6-SERVER prefixlen 128"
ipv6_defaultrouter="IPV6-SERVER"
ipv6_gateway_enable="YES"
ifconfig_bge0="inet6 ROUTED-IPV6-PREFIX/64"

在重启之前,你可以使用 service(8) 命令来检查其是否正常工作。例如,执行以下命令:

这两个 ping6 命令用于检查隧道端点的可达性以及默认路由器的配置。

# service routing start
# service netif restart gif0
# ping6 ff02::1%gif0
# ping6 IPV6-SERVER

就是这样!现在,你可以在你的 LAN 内搭建支持 IPv6 的互联网服务器了,因为配置的 IPv6 地址可以从 IPv6 互联网访问。

关于 ipv6_defaultrouter,还有一点需要补充说明。虽然上述示例使用 IPV6-SERVER,但它也可以是 HE 端的 LLA(链路本地地址),你可以通过 ping 查看,或者将其设置为 -interface gif0。

  • 不推荐使用 HE 端的 LLA,因为当 HE 更换设备时,该地址可能会发生变化。建议仅在手动配置并在自己控制范围内的情况下,才将 LLA 用于静态路由。

  • 推荐的方式是 -interface gif0,这样可以简化配置。由于 gif0 被配置为点对点接口,因此可以直接使用本地的接口名称来指定到 HE 端路由器的路由。这样,即使 IPV6-SERVER 地址发生变化,你的配置仍然有效。

在基本工具中使用 IPv6

本专栏的另一个主题是 FreeBSD 基本系统中的软件 IPv6 配置示例。获得 IPv6 互联网访问权限后,我们可以让软件开始使用 IPv6。

一般规则与注意事项

从用户的角度来看,IPv6 最显著的区别是地址的表示法。除此之外,TCP 和 UDP 的工作方式与 IPv4 基本相同。因此,你可以先尝试将配置文件中的 IPv4 地址替换为 IPv6 地址。

第一期专栏以 OpenSSH 为示例,让我们看看需要做哪些更改。

sshd(8) 守护进程的配置存储在 /etc/ssh/sshd_config 文件中。你可以直接编辑该文件,但使用命令行参数修改配置可以保持默认的配置文件不变。例如,可以将以下行添加到 /etc/rc.conf 以部分修改配置:

sshd_enable="YES"
sshd_flags=" \
 -oPort=22 \
 -oUsePAM=no \
"

让我们回到 IPv6 配置的主题。sshd(8) 守护进程默认会在 IPv4 和 IPv6 上监听 tcp/22 端口。你可以在 /etc/ssh/sshd_config 中看到以下内容:

所有这些行都被注释掉了,但这实际上意味着它们默认是启用的:

#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

“::”是一个 IPv6 地址,这个全零地址被称为“未指定的 IPv6 地址”(unspecified IPv6 address)。需要注意的是,它同时是全零的子网前缀和全零的 IID,而不是前面章节中提到的全零 IID。这个特殊的 IPv6 地址表示“任何 IPv6 地址”,因此 sshd(8) 守护进程会监听此设备上配置的所有 IPv6 地址。

像这样,一些软件在配置文件中直接使用原始的 IPv6 地址。在这种情况下,你可以直接用 IPv6 地址替换 IPv4 地址,无需额外的考虑。sshd(8) 足够智能,能够区分所使用的地址族(IPv4 或 IPv6)。如果你想要限制 sshd(8) 仅监听特定的 IPv6 地址,可以使用选项 -oListenAddress 。

sshd_enable="YES"
sshd_flags=" \
 -oPort=22 \
 -oUsePAM=no \
 -oListenAddress=2001:db8::1 \
"

尽管在配置文件中,IPv6 地址应按照 RFC 5952⁶ 推荐的格式书写,但几乎所有软件都接受冗余表示,例如 2001:0db8:0000:0000:0000:0000:0000:0001。此外,如果使用的是 LLA(链路本地地址),必须添加 %zoneid 部分。

然而,一些软件不会直接使用原始的 IPv6 地址,因为这样会破坏与 IPv4 的向后兼容性。以 syslogd(8) 为例:

syslogd_enable="YES"
syslogd_flags="-s -cc -b [fe80::f4:a6ff:fe43:50b%epair5b]"

以下是作者在其 FreeBSD 设备上使用的配置之一。syslogd(8) 守护进程提供 -b 选项,用于选择监听的地址和端口号。它会监听指定地址,并接受来自 UDP 数据包的日志信息。在 IPv4 中,地址的格式为 -b address:service,其中 service 可以是端口号,也可以是 /etc/services 文件中列出的服务名称。因此,如果直接使用原始的 IPv6 地址,syslogd(8) 守护进程无法区分哪个冒号用于分隔“地址”和“服务”部分。

为了解决此问题,syslogd(8) 守护进程采用 [ipv6-address]:service 这样的格式,即 IPv6 地址必须用方括号括起来。如果地址中包含 %zoneid,它也必须放在方括号内。这种格式在使用“地址:端口”表示法的软件中很常见。

尽管方括号格式适用于支持它的软件,但需要注意的是,方括号在 /bin/sh 等 shell 程序中是元字符。实际上,上述 syslogd(8) 配置示例可能无法正常工作,因为方括号有时会被解释为元字符。如果字符串匹配某个文件或目录名称,一对方括号可能会被替换,导致配置意外失败。因此,推荐使用另一种可行的写法,如下所示:

syslogd_enable="YES"
syslogd_flags=" \
 -b 192.168.0.10 \
 -a 192.168.0.0/24 \
 -a [fe80::ffff:2:200%bridge0]:* \
-b [fe80::ffff:1:202%bridge0] \
 -a [fe80::%bridge0]/64 \
"

你会看到 -a 选项的参数包含 *,这表示守护进程接受来自任何 UDP 端口的连接。然而,* 可能会匹配一个或多个文件名,并在命令行解析时被替换。你可能会想到使用 \ 转义 *,但这是否有效取决于 shell 变量的解析方式。因此,当软件要求使用方括号格式时,需要特别注意路径名扩展问题。当然,如果该格式出现在配置文件中,则不会有问题。

另一个需要注意的点是如何使用 "/64" 这样的格式来指定前缀长度。在上述示例中,前缀长度位于方括号之外,这是因为前缀长度并不是 IPv6 地址的一部分。原始地址、zone ID 部分以及方括号的位置有时可能会令人困惑。请记住,[fe80::/64%bridge0] 和 [fe80::%bridge0/64] 这两种写法都是错误的。

最后一个容易踩坑的地方是使用主机名指定地址的情况。通常,你可以在需要指定地址的地方直接使用主机名。主机名通常由系统可用的名称服务解析,而一个主机名可能会对应多个地址,因为 DNS 支持返回多个 A 记录和 AAAA 记录。在这种情况下,一些软件可能需要明确指定要使用的地址类型和地址族。然而,目前并没有统一的方法来指定主机名的地址族。因此,如果你打算使用主机名,最好确保该主机名唯一,并且只解析到一个地址。

更多实际示例

在 /etc/resolv.conf 中配置 DNS 服务器

为简单起见,递归 DNS 服务器的配置通常应该由 RA(Router Advertisement,路由通告)消息来处理,上一期的专栏已经介绍过相关内容。然而,如果你的 DNS 服务器位于同一链路上,你可以手动添加一个 LLA,并像下面这样指定它:

nameserver fe80::ffff:1:35%bge0

手动配置 LLA 的一个原因是你可以在不同的网络上使用相同的地址,从而大大简化管理。

然而,在 /etc/resolv.conf 中使用 LLA 并不适用于依赖 LDNS 库但不使用 FreeBSD libc 解析函数的软件。这意味着 drill(1) 工具无法在 /etc/resolv.conf 中使用 LLA,而使用 IPv6 GUA 则没有问题。此外,dhclient(8) 也不支持 LLA。

作为一种变通方法,你需要在 nameserver 行中使用 IPv4 地址或 IPv6 GUA⁷。

NFS 与 /etc/exports

/etc/exports 文件使用原始 IPv6 地址格式,并支持 network 关键字的前缀长度表示法。示例如下:

/a/ftproot -alldirs -maproot=0:0 -network 2001:db8:1::/64
/a/ftproot -to -alldirs -maproot=nobody:nobody -network fe80::%lagg0/10

请注意,NFS 并不完全支持 LLA,因为 RPC 库在处理 IPv6 地址时不会包含 zone ID。尽管第二行可以被指定,并且其语法是正确的,但实际上并不起作用⁸。IPv6 GUA 则可以正常工作。因此,目前应避免在 NFS 中使用 LLA,该问题预计会在 FreeBSD 14 中得到修复。

Sendmail

Sendmail 也使用原始 IPv6 地址格式,并支持为每个地址指定地址族关键字。示例如下:

sendmail_enable="YES"
sendmail_flags="-L sm-mta -bd -q30m \
 -ODaemonPortOptions=Family=inet,address=127.0.0.1,Name=MTA \
 -ODaemonPortOptions=Family=inet6,address=::1,Name=MTA6,M=O \
 -ODaemonPortOptions=Family=inet,address=0.0.0.0,Port=587,Name=MSA,M=E \
 -ODaemonPortOptions=Family=inet6,address=::,Port=587,Name=MSA6,M=O \
 -ODaemonPortOptions=Family=inet,address=0.0.0.0,Port=465,Name=MSA,M=s \
 -ODaemonPortOptions=Family=inet6,address=::,Port=465,Name=MSA6,M=s \
"

你可以安全地同时使用具有单个 IPv4 和单个 IPv6 地址的主机名,因为可以使用“Family=”关键字进行指定。

MSA⁹ 使用的传输配置由 /etc/mail/FreeBSD.submit.mc 文件中的以下行处理:

dnl If you use IPv6 only , change [127.0.0.1] to [IPv6:::1]
FEATURE(‘msp’, ‘[127.0.0.1]’)dnl

在这个配置文件中,sendmail 采用了一种修改后的方括号格式,因为 sendmail 需要对 IPv4 也使用方括号格式。如果要使用 IPv6,则必须使用 [IPv6:raw-ipv6-address] 这种格式。

Syslogd

上一节已经介绍了命令行选项。在配置文件 /etc/syslog.conf 中,可以使用原始 IPv6 地址格式来指定远程主机。以下是一个示例,它用于从运行 ISC BIND 的 jail 环境接收日志:

+fe80::e:1ff:fec5:e80b%bridge100
!-named
*.notice;authpriv.none;kern.debug;lpr.info;mail.crit;news.err; /var/log/ns/messages
!named
*.* /var/log/ns/named.log
!*
+@

总结

本文介绍了如何使用隧道服务接入 IPv6 互联网,并配置 FreeBSD 基本系统中的关键软件以支持 IPv6。使用 gif(4) 接口进行隧道连接并不特定于 Hurricane Electric IPv6 Tunnel Broker,它也可以用于构建自定义的虚拟网络。然而,这种方法可能过于原始,不适用于实际用途——它不支持加密或自动配置。

FreeBSD 提供了一整套丰富的网络实验工具。在用户态程序的 IPv6 配置中,通常只需要在配置文件中将 IPv4 地址替换为 IPv6 地址即可,但本文列出了一些需要注意的陷阱。此外,也有一些软件无法正确处理 IPv6 LLA(Link-Local Address)。建议你在自己的设备上尝试 IPv6,如果发现问题,请向作者或 FreeBSD 项目反馈。

在下一期文章中,将会介绍更多软件配置,以及 NDP(邻居发现协议),这是一项 IPv6 核心协议,你应当熟悉它的工作原理。


附注

  1. GUA 代表 Global Unicast Address(全局单播地址),可在 IPv6 互联网中路由。

  2. 记住,IPv6 GUA 由 前缀(prefix) 和 IID(Interface IDentifier,接口标识符) 组成,IID 通常为 64 位。如果你的前缀是 48 位,你可以使用 16 位的子网编号,在 LAN 内创建 65,536 个子网;如果前缀是 64 位,你只能创建一个子网。

  3. 该协议定义在 RFC 4213《IPv6 主机和路由器的基本过渡机制》中。

  4. LLA 代表 Link-Local Address(链路本地地址)。在执行 ifconfig gif0 up 之后,系统会自动配置一个 LLA。详情请参考前一期文章。

  5. IID 代表 Interface Identifier(接口标识符),用于 IPv6 地址的低位部分,每个主机的 IID 都是唯一的。长度通常设为 64 位,但理论上任何长度 ≤ 128 −(子网前缀长度) 都是允许的。

  6. IPv6 地址的文本表示规则已在第一期文章中介绍。详情请参考 RFC 5952《IPv6 地址文本表示法的推荐规范》。

  7. 作者正在研究这些问题,并希望在不久的将来修复它们。

  8. 作者同样在研究此问题。

  9. MSA 代表 Mail Submission Agent(邮件提交代理),它负责将邮件提交给 MTA(Mail Transfer Agent,邮件传输代理)。sendmail 既可以作为 MSA,也可以作为 MTA。


佐藤広生 是东京工业大学的助理教授,研究方向包括 晶体管级集成电路设计、模拟信号处理、嵌入式系统、计算机网络 以及 通用软件技术。他曾是 FreeBSD 核心团队 成员(2006-2022),自 2008 年起担任 FreeBSD 基金会 董事会成员,并自 2007 年以来一直主持 AsiaBSDCon——这一 BSD 操作系统在亚洲的重要国际会议。

访问 并创建你的服务账户。之后,在网页界面中选择“create regular tunnel”(创建常规隧道)。输入你端点的 IPv4 地址,并选择 HE 提供的其中一个端点。你网络中的所有 IPv6 数据包,在到达 IPv6 互联网之前,都会先传送到 HE 的网络,因此你应选择离你最近的端点。例如,作者住在东京,那么选择 HE 的东京端点最佳。点击“create tunnel”按钮后,你在 HE 这边的端点就会被配置。你需要点击两次,因为第一次点击时,系统会从 HE 的网络发送 IPv4 ping 数据包以检查该端点是否正常工作。请确保你的防火墙没有阻止传入的 ICMP 回显请求/应答。HE 端点列表中会显示 IPv4 源地址。

https://www.tunnelbroker.net/
Pragmatic IPv6 (Part 3)