DNS完全指南:从入门到安全

DNS 完全指南:从入门到安全

由浅入深,面面俱到


第一部分:DNS 基础入门

从”门牌号”说起

想象一下:你要去朋友家串门,朋友告诉你”深圳市南山区科技园小区3号楼701室”,你很容易找到。但如果你只告诉你”经度114.05,纬度22.54”,你还能找到吗?

IP地址就像这个经纬度——一串数字(形如 192.168.1.1),计算机能识别,但人类记不住。

域名(如 baidu.com)就像”深圳市南山区科技园小区3号楼701室”,人类容易记住。

DNS(Domain Name System,域名系统) 就是那个把”门牌号”翻译成”经纬度”的翻译官。


什么是DNS?

DNS是一个分布式数据库,存储了域名IP地址的映射关系。当你访问 baidu.com 时:

  1. 浏览器问DNS:”baidu.com 的 IP 是多少?”
  2. DNS回答:”103.235.46.39”
  3. 浏览器根据IP去访问服务器

域名的层级结构

域名是倒着读的层级结构:

1
2
3
baidu.com
↑ ↑ ↑
子域 二级域 顶级域
层级 例子 说明
根域名 . 全球13个根服务器
顶级域(TLD) .com .cn .org 通用/国家顶级域
二级域 baidu 注册的域名
子域 www.baidu.com 可自定义创建

第二部分:DNS 查询过程

递归查询 vs 迭代查询

递归查询:你告诉DNS查询器”帮我查”,它跑断腿帮你找到答案。

迭代查询:DNS服务器告诉你”我不知道,去问 .com 服务器”,然后你再去问下一个,一级一级往上问。


完整的查询流程

以访问 www.example.com 为例:

  1. 浏览器缓存 → 查过吗?有就直接返回
  2. 系统缓存 → 查操作系统DNS缓存
  3. 本地DNS服务器 → 通常是ISP提供的(如电信/联通)
  4. 根域名服务器 → 告诉本地DNS:”去问 .com 服务器”
  5. 顶级域服务器 → 告诉本地DNS:”去问 example.com 的DNS服务器”
  6. 权威DNS服务器 → 终于找到!返回 93.184.216.34

整个过程可能只需几十毫秒


第三部分:DNS 记录类型

DNS不仅仅存IP地址,它能存很多种”记录”:

类型 作用 例子
A 域名指向IPv4地址 baidu.com123.125.115.110
AAAA 域名指向IPv6地址 ipv6.example.com::1
CNAME 别名,指向另一个域名 www.baidu.comwww.a.shifen.com
MX 邮件服务器地址 @example.commail.example.com
TXT 文本记录(用于验证/反垃圾) DKIM、SPF验证
NS 授权DNS服务器 告诉谁负责这个域
PTR 反向DNS(IP查域名) 1.1.1.1one.one.one.one
SOA 域名的”出生证明” 主DNS、刷新时间等

第四部分:DNS 缓存

为什么需要缓存?

如果每次访问网站都从头查一遍,全球DNS服务器会被累死。缓存让重复查询快到飞起。


多层缓存

  • 浏览器缓存:几分钟到几小时
  • 操作系统缓存:几分钟
  • 本地DNS服务器:几分钟到几小时(可配置)
  • 路由器缓存

TTL(生存时间)

DNS记录有个TTL值,告诉缓存”多久刷新一次”。通常设置3600秒(1小时)。

💡 小知识:改DNS解析后要等TTL时间才完全生效就是这个原因。


第五部分:公共DNS服务器

提供商 IPv4 IPv6
Google 8.8.8.8 / 8.8.4.4 2001:4860:4860::8888
Cloudflare 1.1.1.1 / 1.0.0.1 2606:4700:4700::1111
阿里云 223.5.5.5 / 223.6.6.6 2400:3200::1
腾讯DNS 119.29.29.29 / 182.254.116.116 -

为什么要换公共DNS?

  • 运营商DNS可能慢、广告注入、劫持
  • 隐私考虑
  • 更快、更可靠

第六部分:DNS 安全深入剖析

⚠️ 本部分是重点,深入讲解各种DNS攻击与防御

6.1 DNS 安全概述

传统DNS协议设计于1983年,几乎没有任何安全考量——查询和响应都是明文的,可以被任意篡改、伪造、重放。这为后来的各种攻击埋下了伏笔。


6.2 DNS 缓存投毒(Cache Poisoning)

攻击原理

DNS系统有多层缓存。攻击者如果能在权威DNS响应到达本地DNS服务器之前,抢先投递一个伪造的恶意响应,就能把假记录塞进缓存。

1
2
3
4
5
正常流程:
用户 → 本地DNS → 权威DNS → 本地DNS(缓存) → 用户

攻击流程:
攻击者 → 本地DNS(抢在权威响应前)→ 缓存污染 → 用户

传统的资源记录ID猜测攻击

DNS查询包含一个16位的事务ID(Transaction ID)源端口号。如果攻击者能猜中这两个字段,就能伪造权威DNS的响应。

1
2
3
4
# 简化的攻击概念
for transaction_id in range(65536):
for port in range(65536):
send_poisoned_response(id=transaction_id, port=port)

为什么能成功?

  • 早期DNS服务器源端口固定(53)
  • 事务ID可预测
  • 没有验证响应是否来自权威服务器

生日攻击(Birthday Attack)

统计学原理:生日悖论告诉我们,23人中就有50%概率同生日。

攻击者同时发起大量不同子域的查询,权威DNS会产生大量响应。攻击者只要命中其中一个,就能污染缓存。


真实案例:2008年 Kaminsky 漏洞

Dan Kaminsky 发现可以通过跳域名(bailiwick)技术绕过原有限制:

  1. 攻击者向目标DNS服务器查询 attacker.example.com
  2. DNS向上级查询 .com 服务器
  3. 攻击者同时向目标DNS发送大量伪造的 .com 权威响应
  4. 猜中事务ID后,整个 example.com 下的记录都能被污染

影响:当时全球绝大多数DNS服务器都受影响,修复方案是增加源端口随机化


现代防御

防御措施 说明
源端口随机化 查询使用随机端口,而非固定53
事务ID随机化 每次查询ID随机
0x20编码 域名大小写随机化,服务器必须匹配
NXDOMAIN重试 污染一个不存在的域名会被立即发现

6.3 DNS 隧道(DNS Tunneling)

原理

DNS查询通常只有几十字节的payload。攻击者利用DNS协议的TXT、CNAME等记录类型,在查询/响应中夹带数据,建立隐蔽通信通道。

1
2
3
           DNS查询/响应
客户端 ←─────────────────→ 恶意DNS服务器
└─ 编码后的数据 ─┘

数据编码

1
2
3
# DNS查询可以被编码为:
# subdomain = "data.encrypted.in.attackerdomain.com"
# 每段base32编码的数据作为子域发送

著名工具

工具 特点
iodine 最流行,支持DNS、NS、TXT等记录类型
dns2tcp 简单,支持TCP通道
dnscat2 支持加密,客户端/服务器架构
N1QL 高级隧道,支持端口转发

应用场景

恶意用途

  • 绕过防火墙,窃取数据
  • 僵尸网络C2通信
  • 渗透测试(红队)

合法用途

  • 在严格网络环境下获取外部DNS
  • 某些IoT设备的通信

检测与防御

检测方法

  • 异常大的DNS查询/响应
  • 异常频繁的TXT记录查询
  • 来自单个客户端的大量不同子域查询
  • 大量MX/NS记录查询

防御措施

  • DNS防火墙,只允许白名单域名解析
  • 限制查询频率
  • 启用DNSSEC验证响应完整性

6.4 DNSSEC(DNS Security Extensions)

设计目标

DNSSEC通过数字签名确保:

  • 数据完整性:响应未被篡改
  • 数据来源认证:响应确实来自权威DNS
  • 不存在性验证:NXDOMAIN也是可信的

密钥体系

1
2
3
4
KSK (Key Signing Key)
└─ 对 ZSK 进行签名
└─ ZSK (Zone Signing Key)
└─ 对 DNS 记录进行签名
密钥类型 作用 更换频率
KSK 签署ZSK,长期 几年一次
ZSK 签署记录,短期 几周/几月

签名流程

  1. ZSK私钥对每条记录签名 → 生成RRSIG(Resource Record Signature)
  2. KSK私钥对ZSK公钥签名 → 生成DNSKEY
  3. 权威服务器把公钥和签名一起发布

验证流程

1
2
3
4
1. 获取域名DNSKEY记录
2. 用DNSKEY验证ZSK签名
3. 用ZSK验证目标记录签名
4. 验证通过 → 信任

信任链

1
2
3
4
5
6
. (根域)
↓ DS记录指向 com. 的 KSK
.com
↓ DS记录指向 example. 的 KSK
example.com
↓ 返回 example.com 的 A记录 + RRSIG

部署现状

  • 根域名 . 已部署DNSSEC
  • .com.net.org 等已部署
  • 国内覆盖率较低,但正在推进

如何验证

1
2
3
4
5
# Linux
dig +dnssec baidu.com A

# 在线验证
https://dnsviz.net/

6.5 DNS 放大攻击(DNS Amplification Attack)

原理

利用DNS的递归查询响应比请求大很多的特性:

  1. 攻击者伪造受害者IP,向DNS服务器发送小查询
  2. DNS服务器返回大响应(放大10-50倍)
  3. 受害者被海量流量淹没
1
2
3
4
5
攻击者 → 小请求(60字节) → DNS服务器

大响应(3000字节)

受害者 ← 被放大50倍攻击

放大倍数

查询类型 请求大小 响应大小 放大倍数
ANY ~60字节 ~3000字节 ~50x
TXT ~60字节 ~1000字节 ~17x
SRV ~60字节 ~500字节 ~8x

真实案例:2016年 Dyn 攻击

2016年10月21日,美国DNS服务商 Dyn 遭受大规模DDoS攻击,导致Twitter、GitHub、Netflix等大量知名网站无法访问。攻击流量峰值达到1.2Tbps,是当时最大的DDoS攻击之一。

攻击者利用了物联网设备(摄像头、路由器等)组成的僵尸网络,这些设备存在默认密码漏洞,被恶意软件感染后用于发起DNS放大攻击。


防御措施

措施 说明
关闭递归查询 DNS服务器只响应授权域名的查询
限制查询来源 只响应特定IP的查询
过滤异常流量 识别并过滤放大倍数过大的查询
RPKI 验证IP源路由前缀,减少IP伪造

6.6 DNS 劫持(DNS Hijacking)

攻击方式

  1. ISP级劫持:运营商在DNS层面注入广告或重定向
  2. 路由器漏洞:通过路由器漏洞修改DNS设置
  3. 恶意软件:修改系统DNS配置
  4. 中间人攻击:在网络层面截获并篡改DNS响应

防御措施

  • 使用可信的DNS服务器(1.1.1.1、8.8.8.8)
  • 检查HTTPS证书
  • 使用DoH/DoT加密DNS查询
  • 定期检查路由器安全更新

6.7 DNS 隐私问题

问题所在

传统DNS查询是明文的,你的ISP能看到:

  • 你访问了哪些网站
  • 访问频率
  • 大致的上网行为

现代解决方案

技术 说明
DoH (DNS over HTTPS) 通过HTTPS加密传输,443端口
DoT (DNS over TLS) 通过TLS加密,853端口
DNSCrypt 加密DNS流量,类似DoH但更早
Oblivious DNS 进一步隐藏客户端IP

主流支持

  • 浏览器:Chrome、Firefox默认支持DoH
  • 操作系统:Windows 11、macOS、Android支持DoH/DoT
  • 公共DNS:Cloudflare、Google、Quad9都支持DoH/DoT

第七部分:实战操作

查看DNS解析

1
2
3
4
5
6
7
# Windows
nslookup baidu.com

# macOS / Linux
dig baidu.com
# 或
host baidu.com

刷新DNS缓存

1
2
3
4
5
6
7
8
# Windows
ipconfig /flushdns

# macOS
sudo dscacheutil -flushcache

# Linux
sudo systemd-resolve --flush-caches

修改本地DNS(Windows)

控制面板 → 网络和共享中心 → 更改适配器设置 → 右键属性 → IPv4 → 使用以下DNS服务器


第八部分:高级话题

8.1 DNS 负载均衡

一个域名对应多个IP,DNS轮询返回不同IP,分散服务器压力。


8.2 地理DNS

根据用户地理位置,返回最近服务器的IP。


8.3 DNS轮询与健康检查

DNS不仅返回IP,还能配合健康检查,剔除故障服务器。


8.4 域名注册商

购买域名要去域名注册商(ICANN认证),如:

  • GoDaddy
  • Namecheap
  • 阿里云万网
  • 腾讯云

注册商帮你管理DNS服务器(也可以用Cloudflare等第三方DNS)。


总结

DNS是互联网的基础设施之一,它的工作原理其实和我们查电话簿、问路差不多:

  1. 记住域名比记住IP简单太多
  2. 分布式层级设计让全球数十亿域名查询成为可能
  3. 缓存机制让速度快到无感
  4. 安全问题日益重要,DoH/DoT/DNSSEC是未来趋势

理解DNS,不仅能帮你解决”上不了网”的日常问题,更能深入理解互联网是如何运转的。


有问题随时问小龙虾!🦞

Wireguard behind NAT

核心诉求

  • 连接回家
  • 能透明访问局域网其他设备
  • 满速,零中转,不依赖vps

WireGuard

WireGuard 是内核态的VPN实现,高性能,简单易用,也有很多平台的客户端。就是配置时稍微有点抽象。

在 OpenWrt 上,

1
opkg update && opkg install wireguard-tools

常用的命令有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@OpenWrt:~# wg -h
Usage: wg <cmd> [<args>]

Available subcommands:
show: Shows the current configuration and device information
showconf: Shows the current configuration of a given WireGuard interface, for use with `setconf'
set: Change the current configuration, add peers, remove peers, or change peers
setconf: Applies a configuration file to a WireGuard interface
addconf: Appends a configuration file to a WireGuard interface
syncconf: Synchronizes a configuration file to a WireGuard interface
genkey: Generates a new private key and writes it to stdout
genpsk: Generates a new preshared key and writes it to stdout
pubkey: Reads a private key from stdin and writes a public key to stdout
You may pass `--help' to any of these subcommands to view usage.

生成密钥

生成密钥并配置到 /etc/config/network

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
config interface 'vpn'
option proto 'wireguard'
option private_key 'mOr+......................................='
option listen_port '51820'
list addresses '192.168.9.1/24'
# list addresses 'fd00:9::1/64'

config wireguard_vpn
option public_key 'I0i4pvS....................................='
option preshared_key 'PIfYY....................................c='
option description 'iPhone'
option route_allowed_ips '1'
list allowed_ips '192.168.9.2/32'

config wireguard_vpn
option public_key 'jW03l....................................vtUk='
option preshared_key 'KReGAU9R....................................AM='
option description 'macOS'
list allowed_ips '192.168.9.3/32'
option route_allowed_ips '1'

config wireguard_vpn
option public_key 'Ko+os....................................mDTg='
option preshared_key 'VmW....................................d1eg='
option description 'jd'
list allowed_ips '192.168.9.4/32'
option route_allowed_ips '1'


config route
option interface 'vpn'
option target '10.10.1.0/24'
option gateway '10.10.1.1'

配置防火墙

允许访问互联网,并伪装来源IP,避免硬路由拦截。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
config redirect 'wg'
option name 'Redirect-WireGuard'
option src 'wan'
option src_dport '51820'
option dest 'lan'
option dest_ip '10.10.1.1'
option family 'ipv4'
option proto 'udp'
option target 'DNAT'

config nat
option name 'WG伪装'
list proto 'all'
option src 'lan'
option src_ip '192.168.9.0/24'
option target 'SNAT'
option snat_ip '10.10.1.2'

把 vpn 接口放到 lan 区域

1
2
3
4
5
6
7
8
config zone
option name lan
list network 'lan'
list network 'MKLAN'
list network 'vpn'
option input ACCEPT
option output ACCEPT
option forward ACCEPT

设置转发

1
2
3
config forwarding                          
option src 'vpn'
option dest 'lan'

大功告成

用客户端连接就可以啦~

在M系列苹果电脑上安装Redroid的完整指引

在M系列苹果电脑上安装Redroid的完整指引

Redroid是一个基于Linux内核的Android运行时环境,可以在Linux系统上运行Android应用。对于M系列苹果电脑用户来说,通过Docker可以轻松运行Redroid,从而在macOS上体验Android应用。本文将详细介绍安装和配置过程。

前置要求

在开始安装之前,请确保您的系统满足以下要求:

  • macOS 12.0 (Monterey) 或更高版本
  • Apple Silicon Mac (M1/M2/M3系列)
  • 已安装Docker Desktop for Mac
  • 至少8GB内存(推荐16GB或更多)
  • 至少10GB可用磁盘空间

安装步骤

1. 安装Docker Desktop

如果还没有安装Docker Desktop,请从官网下载并安装:

1
2
3
4
# 使用Homebrew安装(推荐)
brew install --cask docker

# 或者从官网下载:https://www.docker.com/products/docker-desktop

安装完成后启动Docker Desktop,确保Docker服务正常运行。

2. 拉取Redroid镜像

打开终端,运行以下命令拉取适合Apple Silicon的Redroid镜像:

1
2
3
4
5
# 拉取最新的Redroid镜像
docker pull redroid/redroid:latest

# 或者拉取特定版本的镜像(推荐)
docker pull redroid/redroid:12.0.0-latest

3. 启动Redroid容器

使用以下命令启动Redroid容器:

1
2
3
4
5
6
docker run -itd \
--name redroid \
--privileged \
-p 5555:5555 \
-v /tmp/redroid-data:/data \
redroid/redroid:12.0.0-latest

参数说明:

  • --name redroid: 容器名称
  • --privileged: 给予容器特权模式
  • -p 5555:5555: 端口映射,用于ADB连接
  • -v /tmp/redroid-data:/data: 数据卷挂载,保存应用数据

4. 安装ADB工具

为了与Redroid进行交互,需要安装Android Debug Bridge (ADB):

1
2
3
4
5
# 使用Homebrew安装ADB
brew install android-platform-tools

# 验证安装
adb version

5. 连接到Redroid

启动容器后,使用ADB连接到Redroid:

1
2
3
4
5
# 连接到Redroid
adb connect localhost:5555

# 检查设备状态
adb devices

如果连接成功,您应该看到类似以下的输出:

1
2
List of devices attached
localhost:5555 device

使用Redroid

启动Android界面

连接到Redroid后,您可以通过以下方式启动Android界面:

1
2
# 启动Android界面
adb shell am start -n com.android.launcher3/.Launcher

安装Android应用

您可以通过以下方式安装Android应用:

1
2
3
4
5
# 安装APK文件
adb install /path/to/your/app.apk

# 从Google Play下载的应用通常位于
# ~/Library/Application Support/Google Play/Downloads/

常用ADB命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看已安装的应用
adb shell pm list packages

# 卸载应用
adb shell pm uninstall com.example.app

# 截图
adb shell screencap /sdcard/screenshot.png
adb pull /sdcard/screenshot.png

# 录屏
adb shell screenrecord /sdcard/video.mp4
# 按Ctrl+C停止录屏
adb pull /sdcard/video.mp4

性能优化

内存和CPU配置

对于更好的性能,可以在启动容器时指定资源限制:

1
2
3
4
5
6
7
8
9
docker run -itd \
--name redroid \
--privileged \
--cpus=4 \
--memory=4g \
--memory-swap=4g \
-p 5555:5555 \
-v /tmp/redroid-data:/data \
redroid/redroid:12.0.0-latest

图形加速

Redroid支持硬件加速,但需要额外的配置。对于M系列芯片,建议使用软件渲染:

1
2
3
# 在容器内设置图形渲染模式
adb shell setprop ro.hardware.egl swiftshader
adb shell setprop ro.hardware.vulkan pastel

故障排除

常见问题

  1. 容器启动失败

    1
    2
    3
    4
    5
    6
    # 检查Docker日志
    docker logs redroid

    # 重新创建容器
    docker rm -f redroid
    docker run -itd --name redroid --privileged -p 5555:5555 redroid/redroid:12.0.0-latest
  2. ADB连接失败

    1
    2
    3
    4
    # 重启ADB服务
    adb kill-server
    adb start-server
    adb connect localhost:5555
  3. 应用安装失败

    1
    2
    3
    4
    5
    # 检查APK文件完整性
    adb install -r /path/to/app.apk

    # 查看详细错误信息
    adb logcat

性能问题

如果遇到性能问题,可以尝试:

  1. 增加容器内存分配
  2. 关闭不必要的后台应用
  3. 使用更轻量级的Android版本镜像

高级配置

网络配置

如果需要配置网络代理或VPN:

1
2
3
4
5
# 设置HTTP代理
adb shell settings put global http_proxy host:port

# 清除代理设置
adb shell settings put global http_proxy :0

文件传输

在macOS和Redroid之间传输文件:

1
2
3
4
5
# 从macOS复制文件到Redroid
adb push /path/to/local/file /sdcard/

# 从Redroid复制文件到macOS
adb pull /sdcard/file /path/to/local/

总结

通过以上步骤,您就可以在M系列苹果电脑上成功运行Redroid了。Redroid提供了一个轻量级的Android运行环境,适合开发测试、应用调试或简单的Android应用使用。

注意事项

  • Redroid主要用于开发和测试,不建议用于生产环境
  • 某些需要特殊硬件支持的应用可能无法正常运行
  • 定期备份重要数据,避免数据丢失
  • 关注Redroid的更新,及时升级到最新版本

相关资源

希望这篇指引能帮助您成功在M系列苹果电脑上安装和使用Redroid!

Install Home Assistant on Proxmox VE

在 Proxmox VE(PVE)中安装 Home Assistant OS(HAOS)使用 qcow2 镜像文件是一个相对简单的过程。以下是详细的步骤,基于你已经下载了最新的 haos_ova-<version>.qcow2.xz 文件(如 haos_ova-15.2.qcow2.xz)。我将假设你使用的是 Proxmox VE 8.x,并提供手动安装的步骤,同时确保解决可能的常见问题。


准备工作

  1. 确认环境

    • 你需要有 Proxmox VE 已安装并可访问(通过 Web 界面或 SSH)。
    • 确保已下载最新的 Home Assistant OS qcow2 镜像文件(从 Home Assistant GitHub Releases)。
    • 确保你的存储池(如 local-lvmlocal-zfs)有足够空间存储解压后的 qcow2 文件(解压后约为 2-4GB,建议至少预留 32GB 用于 VM 磁盘)。
  2. 推荐硬件配置

    • CPU:至少 2 核。
    • 内存:至少 4GB(推荐 4-8GB)。
    • 存储:至少 32GB(Home Assistant 推荐)。

安装步骤

1. 上传并解压 qcow2 镜像文件

  1. 将压缩的 qcow2 文件上传到 Proxmox

    • 使用 SSH 或 SCP 将下载的 haos_ova-<version>.qcow2.xz 文件传输到 Proxmox 主机。例如,传输到 /root 目录:
      1
      scp haos_ova-15.2.qcow2.xz root@<proxmox-ip>:/root/
      或者,你可以在 Proxmox 主机上使用 wget 直接下载:
      1
      2
      cd /root
      wget https://github.com/home-assistant/operating-system/releases/download/15.2/haos_ova-15.2.qcow2.xz
  2. 安装 xz-utils(如果未安装)并解压文件

    • 在 Proxmox 主机上,安装解压工具:
      1
      2
      apt update
      apt install xz-utils
    • 解压 qcow2 文件:
      1
      unxz /root/haos_ova-15.2.qcow2.xz
      解压后会生成 haos_ova-15.2.qcow2 文件。
  3. (可选)清理空间

    • 如果空间有限,可以在后续步骤完成后删除原始的 .xz 文件:
      1
      rm /root/haos_ova-15.2.qcow2.xz

2. 创建虚拟机

  1. 登录 Proxmox Web 界面

    • 打开浏览器,访问 https://<proxmox-ip>:8006,登录 Proxmox。
  2. 创建新的虚拟机

    • 点击右上角的 Create VM
    • 配置以下设置:
      • General
        • VM ID:选择一个唯一的 ID(如 100)。
        • Name:设置为 home-assistant 或其他你喜欢的名称。
      • OS
        • 选择 Do not use any media(因为我们稍后会导入 qcow2 镜像)。
      • System
        • BIOS:选择 OVMF (UEFI)(Home Assistant 需要 UEFI 启动)。
        • EFI Storage:选择你的存储池(如 local-lvmlocal-zfs)。
        • Pre-Enroll Keys取消勾选(禁用 Secure Boot,否则可能导致启动失败)。
        • Machine:选择 q35(推荐)。
      • Hard Disk
        • 删除默认的磁盘(点击垃圾桶图标),因为我们将使用导入的 qcow2 镜像。
      • CPU
        • 分配至少 2 核(推荐)。
      • Memory
        • 分配至少 4096 MB(4GB,推荐 4-8GB)。
      • Network
        • 选择 virtio 网卡,桥接到 vmbr0(或你的网络桥接)。
      • Confirm
        • 取消勾选 Start after created(我们需要先导入磁盘)。
        • 点击 Finish 创建 VM。

3. 导入 qcow2 镜像

  1. 使用 qm importdisk 命令导入镜像

    • 在 Proxmox 主机上通过 SSH 或 Web 界面的 Shell 执行:
      1
      qm importdisk <VM-ID> /root/haos_ova-15.2.qcow2 <storage> --format qcow2
      • 替换 <VM-ID> 为你创建的虚拟机 ID(如 100)。
      • 替换 <storage> 为你的存储池名称(如 local-lvmlocal-zfs)。
      • 示例:
        1
        qm importdisk 100 /root/haos_ova-15.2.qcow2 local-lvm --format qcow2
    • 导入完成后,输出的最后一行会显示类似 Successfully imported disk as 'unused0:local-lvm:vm-100-disk-0'
  2. 将导入的磁盘添加到虚拟机

    • 返回 Proxmox Web 界面,选择你的虚拟机(VM ID 如 100)。
    • 进入 Hardware 标签,找到 Unused Disk 0(如 unused0:local-lvm:vm-100-disk-0)。
    • 点击 Edit,设置:
      • Bus/Device:选择 SCSI,端口为 0
      • Discard:如果使用 SSD,勾选此选项以启用 TRIM 支持。
      • 点击 Add
    • 现在磁盘会显示为 Hard Disk (scsi0)
  3. 调整磁盘大小(可选)

    • Home Assistant 推荐至少 32GB 磁盘空间。如果导入的 qcow2 磁盘较小,可以扩展:
      • Hardware 标签,选择 Hard Disk (scsi0),点击 Resize disk
      • 输入增加的容量(例如,输入 26 表示增加 26GB,使总大小达到约 32GB)。
  4. 配置 EFI 磁盘

    • Home Assistant 需要 EFI 磁盘以支持 UEFI 启动。
    • Hardware 标签,点击 Add > EFI Disk
    • 选择存储池(如 local-lvm),取消勾选 Pre-Enroll Keys,点击 OK
  5. 设置启动顺序

    • 进入虚拟机的 Options 标签,双击 Boot Order
    • 勾选 scsi0(Home Assistant 磁盘),取消勾选其他选项(如 ide2net0)。
    • 点击 OK 保存。
  6. 启用 QEMU Guest Agent(可选但推荐)

    • Options 标签,双击 QEMU Guest Agent,勾选 Enabled
    • 这有助于 Proxmox 监控和管理 VM。

4. 启动虚拟机并验证

  1. 启动虚拟机

    • 在 Proxmox Web 界面,选择你的虚拟机,点击 Start
  2. 检查控制台

    • 打开虚拟机的 Console(在 Web 界面)。
    • 如果启动成功,Home Assistant 会显示一个欢迎界面,并提供访问地址,如 http://homeassistant.local:8123http://<VM-IP>:8123
  3. 访问 Home Assistant

    • 在浏览器中输入 http://<VM-IP>:8123http://homeassistant.local:8123(如果你的网络支持 mDNS)。
    • 按照提示设置管理员账户、位置等信息,完成 Home Assistant 初始化。

5. 清理(可选)

  • 导入完成后,可以删除 Proxmox 主机上的原始 qcow2 文件以释放空间:
    1
    rm /root/haos_ova-15.2.qcow2

常见问题及解决方法

  1. 启动失败,显示 “Access Denied” 或 UEFI 错误

    • 原因:可能是启用了 Secure Boot 或未正确配置 EFI 磁盘。
    • 解决
      • 确保在创建 VM 时选择了 OVMF (UEFI),并取消勾选 Pre-Enroll Keys
      • 如果仍失败,在 VM 启动时按 Esc 进入 UEFI 菜单,导航到 Device Manager > Secure Boot Configuration,禁用 Attempt Secure Boot
    • 检查是否正确设置了启动顺序(仅 scsi0 启用)。
  2. 导入磁盘失败,提示文件不存在

    • 原因:可能是路径错误或文件名拼写错误(如 .qcow2 误写为 .gcow2)。
    • 解决
      • 使用 ls /root 确认文件存在且名称正确。
      • 确保解压命令 (unxz) 已成功执行。
      • 示例错误修复:qm importdisk 100 /root/haos_ova-15.2.qcow2 local-lvm --format qcow2
  3. 无法访问 Web 界面

    • 原因:可能是网络配置错误或防火墙阻止了端口 8123。
    • 解决
      • 确保 VM 的网络桥接(vmbr0)正确配置。
      • 检查 Proxmox 主机或网络的防火墙规则,允许端口 8123。
      • 使用 VM 控制台查看分配的 IP 地址,或尝试 http://homeassistant.local:8123(需要 mDNS 支持)。
      • 如果 IP 不显示,检查网络是否分配了 DHCP 地址,或考虑设置静态 IP。
  4. 磁盘性能问题

    • 原因:未启用 Discard 或未优化存储设置。
    • 解决
      • 如果使用 SSD,确保在添加磁盘时勾选 Discard
      • 使用 virtio-scsi-pci 作为 SCSI 控制器以提高性能。
  5. SSH 访问 Home Assistant

    • Home Assistant OS 默认不启用 SSH。你需要在 Home Assistant Web 界面中安装 SSH & Web Terminal 插件:
      • 进入 Settings > Add-ons > Add-on Store,安装 SSH & Web Terminal
      • 配置并启用 SSH 访问。
    • 或者,使用 Proxmox 的 VM 控制台进行调试。

额外建议

  • 备份:安装完成后,配置 Proxmox 备份到外部存储(如 NFS 或 Proxmox Backup Server),以便在需要时恢复 VM。
  • 更新:定期检查 Home Assistant OS 的新版本,下载新的 qcow2 镜像并重复上述步骤以升级(或使用 Home Assistant 内置更新功能)。
  • 脚本自动化(可选):如果你不想手动执行这些步骤,可以使用社区提供的脚本(如 tteck/Proxmox),但请仔细审查脚本内容以确保安全。

示例命令总结

假设 VM ID 为 100,存储为 local-lvm,Home Assistant 版本为 15.2

1
2
3
4
5
6
7
8
9
10
# 解压镜像
apt install xz-utils
cd /root
unxz haos_ova-15.2.qcow2.xz

# 导入磁盘
qm importdisk 100 /root/haos_ova-15.2.qcow2 local-lvm --format qcow2

# (在 Web 界面配置 VM 后)启动 VM
qm start 100

参考资料

万兆光纤内网的初体验

为啥要折腾

家里在装宽带时,为了更美观让电信师傅把光纤拉到了餐厅的吊顶上面,然后再通过网线拉到两个房间。但从去年开始,预埋的网线可能是因为质量问题,无法达到千兆满速,有时甚至从NAS上拷贝文件,还不如外网下载快…… 所以寻思优化内网质量,初步方案有两个:2.5G网线方案、10G万兆光纤方案。

2.5G内网方案

这个方案比较简单自然,因为我的NAS有两个2.5G网口,支持链路聚合;工作用的小主机,也有几个2.5G网口,瓶颈其实是在网线和交换机上。

网线比较简单,为了布线方便,直接购买了山泽的超细铜线: https://item.jd.com/3109393.html 走墙角的话,几乎可以做到隐形效果。

交换机就纠结了,最便宜的水星五口2.5G交换机,也要118块,不支持国补 (https://item.jd.com/100119130137.html);而4*2.5G + 2*万兆光口,支持 VLAN、端口聚合、网管交换机的水星 SE106 Pro,国补后也在 120+ 左右,这不是逼着人上光纤方案嘛?

万兆光纤方案

SFP+传输介质选择

首先遇到的问题是 SFP+ 是什么东西?

名称 SFP+高速线缆 10GBASE-T电口模块 SFP+光模块
传输介质 双绞线 双绞线 光缆
连接器类型 一体化 RJ45 LC
传输距离 7m 30m 大于100m
布线系统 铜缆布线 光缆布线
传输速率 10Gbps 10Gbps 10Gbps
  • SFP+高速线缆只有7m,不满足需求直接淘汰。
  • 万兆电口有UP主反映,发热量巨大,稳定性差。
  • 基本锁定 SFP+ 光模块方案。

光线缆

分为三种:

  • AOC光线缆:光模块和光纤一体化,定长,两端为光收发器,短距离可替代光模块和光纤。
  • 光跳线:一定长度的光纤搭配光连接器构成,需搭配匹配的光模块。
  • 尾纤:一端有连接头,另一端是光缆纤芯的断头,需通过熔接和其他光缆纤芯相连。

家庭内部一般推荐选择AOC光线缆,简单、可靠,不需要考虑连接器、光模块、单模多模这些复杂参数。

光纤类型

光纤按传输模式分为单模光纤(Single Mode Fiber)和多模光纤(Multi Mode Fiber)。光以一特定的入射角度射入光纤,在光纤和包层间发生全发射,当直径较小时,只允许一个方向的光通过,即为单模光纤;当光纤直径较大时,可以允许光以多个入射角射入并传播,此时就称为多模光纤。

一般来说,单模光纤纤芯更细,干扰更小,支持更长距离和更高带宽,但对激光器要求更高,总体成本更高;多模光纤光源成本低、功耗小,适合短距离高速传输。

AOC光线缆中,多模光纤(OM3/OM4/OM5)占大多数,成本低,功耗小,适合家庭这种短距离互联。

闲鱼二手市场,Finisar 菲尼萨 AOC 万兆光纤线,7米的价格在 10元左右。京东主流品牌则在 100元出头。

可以根据线缆的颜色分辨不同类型的光纤。

光纤类型 标准外皮颜色 典型应用场景
单模光纤 (SMF) 黄色 长距离传输(如城域网、骨干网)
多模光纤 (OM1) 橙色 短距离(≤ 1Gb/s,传输距离约275米)
多模光纤 (OM2) 橙色 短距离(≤ 10Gb/s,传输距离约550米)
多模光纤 (OM3) 水蓝色 高速短距(10G/40G/100G,传输距离300米)
多模光纤 (OM4) 紫色 超高速短距(40G/100G/400G,传输距离550米)
多模光纤 (OM5) 青柠绿 多波长复用(SWDM,支持400G/800G)
特种光纤 黑色/其他 抗弯曲、耐高温等特殊场景

光模块连接器

如果选择光跳线方案,需要考虑光模块和连接器。

一、按物理结构分类(连接器类型)

不同连接器主要在尺寸、锁定机制、适用场景上存在差异:

连接器类型 特点 适用场景 常见端面类型
FC - 金属套圈,螺纹旋转锁定
- 高稳定性,抗振动
电信网络、单模长距离传输 PC / APC
ST - 卡口式锁定(类似BNC接头)
- 常用于多模光纤
旧式局域网、监控系统 PC
SC - 方型插拔式,推拉锁定
- 结构简单,易插拔
数据通信、PON网络 PC / APC / UPC
LC - 小型化设计(SC的一半尺寸)
- 高密度连接
数据中心、高密度布线(如SFP模块) UPC / APC
MTRJ - 双芯一体式(收发一体)
- 塑料材质,紧凑设计
短距离多模通信(如企业网) PC

关键区别

  • 尺寸:LC < SC < FC ≈ ST < MTRJ(双芯)。
  • 锁定方式:FC(螺纹) vs. ST(卡口) vs. SC/LC(插拔) vs. MTRJ(卡扣)。
  • 密度:LC > SC > MTRJ > ST > FC。

二、按端面研磨方式分类

端面研磨方式直接影响反射损耗(回波损耗),需根据场景选择:

端面类型 特点 反射损耗 颜色标识 适用场景
PC - 球面研磨
- 较早的标准
~ -40 dB 蓝色/米色 普通多模光纤(OM1/OM2)
UPC - 超物理接触(更精细的球面研磨)
- 低反射
~ -55 dB 蓝色 高速单模/多模(OM3/OM4)
APC - 8°斜面研磨
- 反射光从纤芯逸出,回损最低
~ -65 dB 绿色 高要求单模(如CATV、5G)

关键区别

  • 反射损耗:APC > UPC > PC(数值越小,反射越少)。
  • 颜色标识:APC端面通常为绿色,UPC为蓝色,PC为米色或黑色。
  • 兼容性:APC与UPC/PC端面不能混接(斜面与平面不匹配)。

三、连接器与端面组合的典型应用

  1. FC/APC:单模长距离传输(如光纤到户FTTH)。
  2. LC/UPC:数据中心高速模块(100G/400G光模块)。
  3. SC/APC:广电网络(CATV)或5G前传网络。
  4. ST/PC:旧式监控系统或多模局域网。

家庭一般选择 SC大方口、LC小方口,这两种接头的光模块也最便宜,闲鱼上直接选购即可。

万兆交换机

下篇继续。

Docker Swarm in Alpine

Docker Swarm in Alpine

Install alpine

  1. Boot with alpine ISO
  2. Run setup-alpine and follow the instructions
  3. Reboot when ready.

Install docker

Make sure you have community repository enabled.

/etc/apk/repositories

1
2
http://mirrors.ustc.edu.cn/alpine/v3.19/main
http://mirrors.ustc.edu.cn/alpine/v3.19/community
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# install docker
apk add docker

# add openrc service manager
apk add openrc

# run docker at boot
rc-update add docker boot

# check docker service status
rc-service docker status

# start/restart docker if necessary
rc-service docker start
rc-service docker restart

Init docker swarm

1
docker swarm init

Use the command on the screen to join this swarm, or run docker swarm join-token manager to recall the join command anytime.

On other server, install docker and run following command:

1
docker swarm join --token SWMTKN-1-58ke7scnx4zolgfoce8r4ijnehci78ac9nl48g3txrf4bydvdo-by9hhrndcvq9eqk5hblb92dee 10.10.1.50:2377

docker mirror

1
2
mkdir /etc/docker
vi /etc/docker/daemon.json

cat /etc/docker/daemon.json

1
2
3
4
5
6
{
"registry-mirrors": [
"https://docker.1ms.run",
"https://docker.xuanyuan.me"
]
}

Install portainer

1
2
3
4
5
6
apk add curl
curl -L https://downloads.portainer.io/ce-lts/portainer-agent-stack.yml -o portainer-agent-stack.yml
docker stack deploy -c portainer-agent-stack.yml portainer

# check the service list
docker service list

If you receive 0 replicas, check your network or docker mirror config.

1
2
3
ID             NAME                  MODE         REPLICAS   IMAGE                        PORTS
xr2c6kip60l4 portainer_agent global 0/1 portainer/agent:lts
jsf5xzk210f0 portainer_portainer replicated 0/1 portainer/portainer-ce:lts *:8000->8000/tcp, *:9000->9000/tcp, *:9443->9443/tcp

If everything goes well, you will receive:

1
2
3
ID             NAME                  MODE         REPLICAS   IMAGE                        PORTS
xr2c6kip60l4 portainer_agent global 1/1 portainer/agent:lts
jsf5xzk210f0 portainer_portainer replicated 1/1 portainer/portainer-ce:lts *:8000->8000/tcp, *:9000->9000/tcp, *:9443->9443/tcp

Now you can visit https://10.10.1.50:9443/ to init admin.

App Templates

Navigate to Settings - General on portainer web console, set App Templates URL to https://storage.360buyimg.com/blogimages/portainer_templates.json, then you can see application templates list on Templates - Application.

给子域名增加SSL自动续期

给子域名增加SSL自动续期

写给腾讯云的一个笔记。

背景

现在免费 SSL 的有效期全面下调至 90 天,自动续期成为必须。atzlinux.com 的多个子域名,用于各下载镜像使用,这就涉及到这些子域名的SSL证书的自动续期问题。

工具选择

个人推荐 acme.sh ,https://github.com/acmesh-official/acme.sh

国内运营商给家庭宽带的 80 端口全部屏蔽了,HTTP验证的路走不通,只能采用 DNS 验证的方式。而 acme.sh 集成了主流的 DNS 验证插件,可以非常简单的完成DNS验证和证书的续期。

权限控制

各下载镜像在 DNS 验证时,需要用到DNS提供商侧的密钥,这个密钥一般可以管理整个域名下的全部 DNS 记录,风险极高。
好在腾讯云提供了「域名共享」的细粒度权限管控能力,能把一个子域名共享给另外一个腾讯云主账号,授权其管理该子域名及下级孙域名。

操作步骤

一、域名共享(主域名账号)

在腾讯云解析管理下,增加域名共享

subdomain-grant

二、子账号策略创建(子域名账号)

考虑到子域名的账号下还有其他的资产,可以创建一个子账号,仅授予对应域名的权限。

首先,创建一个自定义策略:
subdomain-policy

也可以直接使用 JSON 文件创建,自己修改其中的 uin 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"statement": [
{
"action": [
"dnspod:*"
],
"effect": "allow",
"resource": [
"qcs::dnspod::uin/8******2:domain/mike.atzlinux.com"
]
}
],
"version": "2.0"
}

三、子账号账号创建(子域名账号)

然后创建子账号,绑定刚建好的自定义策略

subdomain-accoumt

四、获取 API 密钥(子域名账号)

在子账号的详情页中,点击 API 密钥 Tab,新建密钥。复制保存好。

subdomain-apikey

五、安装 acme.sh 并生成证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 安装
curl https://get.acme.sh | sh -s [email protected]

# 保存 API 密钥
cat <<EOF >> ~/.acme.sh/acme.sh.env
export Tencent_SecretId="XXXXXXXX"
export Tencent_SecretKey="XXXXXXXXX"
EOF

# 申请证书
acme.sh --issue --dns dns_tencent -d mike.atzlinux.com -d *.mike.atzlinux.com --debug

# 部署证书到 Nginx
acme.sh --install-cert -d mike.atzlinux.com \
--key-file /path/to/keyfile/in/nginx/key.pem \
--fullchain-file /path/to/fullchain/nginx/cert.pem \
--reloadcmd "service nginx reload"

成功后,acme.sh 会自动增加 crontab,定期续期证书,证书更新成功后,会自动重启 Nginx 使之生效。

六、验证证书有效性

使用 curl 命令确保证书已经更新:

1
2
3
4
5
6
7
8
$ curl -v -I https://mike.atzlinux.com:58888/ 2>&1 | grep -A6 'Server certificate'
* Server certificate:
* subject: CN=mike.atzlinux.com
* start date: Feb 11 01:57:39 2025 GMT
* expire date: May 12 01:57:38 2025 GMT
* subjectAltName: host "mike.atzlinux.com" matched cert's "mike.atzlinux.com"
* issuer: C=US; O=Let's Encrypt; CN=E5
* SSL certificate verify ok.

或者使用浏览器查看。

Nginx的安全配置

Nginx的安全配置

2025年,WEB服务的安全有哪些变化吗?

自动申请证书

见下一篇笔记。

证书使用建议

注意选用 fullchain 证书,单证书证书容易造成中间证书不识别的问题。

1
2
ssl_certificate /etc/nginx/ssl/hk2.fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/hk2.key;

禁用低版本的协议

只启用 TLS v1.3 和 TLSv1.2

1
ssl_protocols      TLSv1.2 TLSv1.3;

控制使用的算法白名单

1
2
3
ssl_ecdh_curve X25519:prime256v1:secp384r1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;

生成专有的DH参数

1
2
cd /etc/ssl/certs
openssl dhparam -out dhparam.pem 4096
1
ssl_dhparam /etc/ssl/certs/dhparam.pem;

启用OCSP装订

用新协议检查证书的吊销情况。

1
2
3
4
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

CA白名单

配置仅白名单的CA才能为某个域名

1
ssl_trusted_certificate /etc/nginx/ssl/hk2-ca.cer;

安全相关头

1
2
3
add_header Strict-Transport-Security max-age=31536000;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

Gualys SSL Labs A+

Gualys SSL Labs A+

OpenWrt on Time Cloud

目标

这个小盒子主要是满足了几个小功能:

  1. 从外地连回家中内网
  2. 家中科学上网
  3. Windows激活
  4. 文件共享
  5. 对外提供Web服务

实现方法有很多种,这里记录下我的实践。

OpenWrt

我使用的硬件是2017年149元购入的迅雷下载宝,小巧、省电、足够强大。256M RAM,16MB Flash,主频880MHz,Ramips/mt7621 架构,软件包架构 mipsel_24kc,芯片是联发科的 MediaTek MT7621A。并且它带有千兆网口、SDCard插槽、USB 3.0接口,又非常容易刷机,可玩性十足。

官方固件:https://openwrt.org/toh/hwdata/thunder/thunder_timecloud

官方固件好在安全,没有人夹带私货,但毛病是不够精简,16MB Flash装完系统后没啥空间装软件了。所以之前我是基于官方源码自己定制编译,移除大量用不上的功能,并增加常用的软件包,比如SDCard支持、文件系统支持等。

最近比较懒了,所以就直接用了网友的构建服务: https://openwrt.ai/

需要移除定制的包:

1
-luci-app-fileassistant -luci-app-advancedplus -nano -odhcp6c -odhcpd-ipv6only -ppp -ppp-mod-pppoe -luci-app-upnp kmod-sdhci kmod-sdhci-mt7620

配置信息,替换 localStorage 中的 op-custom-info 值:

1
models=Thunder+Timecloud&box-model=s905d&cpackages=-luci-app-fileassistant+-luci-app-advancedplus+-nano+-odhcp6c+-odhcpd-ipv6only+-ppp+-ppp-mod-pppoe+-luci-app-upnp+kmod-sdhci+kmod-sdhci-mt7620+wireguard-tools+vlmcsd&passwall=on&ipaddr=10.10.1.2&theme=bootstrap&kernel_v=6.1.10&webserver=nginx&side=on&gateway=10.10.1.1&efi=on&save=on

构建,下载固件刷机完事。

SSH Public Key Authentication

Why Public Key Authentication

A weak password is dangerous while a strong password is hard to remember.

For security and convience sake, we should disable password authentication and use Public Key Authentication instead.

Public Key Authentication in OpenSSH is easy

Copy Public Key to remote host

OpenSSH has a built-in command to do this:

1
ssh-copy-id -p 22 [email protected]

This will copy the default public key to remote server, and append to the ~/.ssh/authorized_keys file.

If you want to specify a key other that the default one, try the -i option:

1
ssh-copy-id -i ~/.ssh/id_ed25519 [email protected]

Note the permission of the private key should be readable only for you, e.g chmod 600 ~/.ssh/id_ed25519.

Login with the Public Key Authentication

You can simply type:

1
ssh [email protected]

The ssh client will attempt the keys to find the correct one.

1
2
3
4
5
~/.ssh/id_rsa
~/.ssh/id_dsa
~/.ssh/id_ecdsa
~/.ssh/id_ed25519
~/.ssh/id_xmss

Disable password authentication

Set configs below in /etc/ssh/sshd_config, and restart the sshd with /etc/init.d/sshd restart

1
2
PasswordAuthentication no
PubkeyAuthentication yes

Public Key Authentication in Dropbear SSH

Dropbear is a lightweight ssh server for embedded devices, and it’s the default ssh server on a OpenWrt router.

When you are using Dropbear ssh server, ssh-copy-id won’t work.

Set the public key using LuCI

If you have a LuCI installed, it’s easy to add a key using the web interface. Navigate to System - Administration - SSH-Keys to make it happen.

System - Administration - SSH-Keys

Set from the command-line

1
echo `YOUR PUBLIC CONTENT` >> /etc/dropbear/authorized_keys