dog 在 HarmonyOS 上的构建与适配
dog是一个基于Rust编写的现代化命令行DNS客户端工具,支持DNS-over-TLS和DNS-over-HTTPS协议,提供彩色输出和JSON格式支持。本文介绍了dog的主要特性、使用方法及其在HarmonyOS上的适配过程,包括环境准备、构建脚本配置和关键问题解决方案。通过禁用原生TLS依赖,使用纯Rust实现的rustls库,成功完成了跨平台构建,最终生成了可在HarmonyOS上运行的二
目录
- 项目简介
- dog 是什么
- dog 的主要特性
- dog 的使用方法
- HarmonyOS 适配过程
- 环境准备
- 构建脚本详解
- 关键问题解决
- OpenSSL 依赖问题
- HNP 包配置
- 构建结果
- 使用示例
- 总结
- FAQ
- 相关链接
项目简介
| 项目名称 | dog |
|---|---|
| 开源协议 | EUPL |
| 源码版本 | v1.0.0 |
| 目标平台 | aarch64-linux-ohos |
| 依赖项 | OpenHarmony SDK、Rust(rustup/cargo) |
| 操作系统平台 | OpenHarmony PC |
| 源码地址 | https://gitcode.com/nutpi/dog |
你要我帮你把这个表格转换成 Markdown 可直接复制 的版本吗?
dog 是一个现代化的命令行 DNS 客户端工具,使用 Rust 语言编写,是传统 dig 命令的现代化替代品。它提供了彩色输出、支持 DNS-over-TLS 和 DNS-over-HTTPS 协议,并能输出 JSON 格式。
仓库地址: git@gitcode.com:nutpi/dog.git
版本: v1.0.0
Tag: v1.0.0-harmonyos
dog 是什么
dog 是一个命令行 DNS 客户端,类似于传统的 dig 命令,但提供了更现代化的功能和更好的用户体验。
主要优势
- 彩色输出:自动使用颜色区分不同类型的 DNS 记录
- 现代化协议:支持 DNS-over-TLS (DoT) 和 DNS-over-HTTPS (DoHT)
- JSON 输出:支持 JSON 格式输出,便于脚本处理
- 友好的命令行接口:使用直观的命令行参数语法
- 高性能:Rust 编写,单二进制文件,运行速度快
- 跨平台:支持 Windows、macOS、Linux 等平台
与 dig 的对比
| 特性 | dig | dog |
|---|---|---|
| 彩色输出 | ❌ | ✅ |
| DNS-over-TLS | ❌ | ✅ |
| DNS-over-HTTPS | ❌ | ✅ |
| JSON 输出 | ❌ | ✅ |
| 友好的参数 | ❌ | ✅ |
| 单二进制文件 | ❌ | ✅ |
dog 的主要特性
1. 多种 DNS 协议支持
- UDP:传统的 DNS over UDP(默认)
- TCP:DNS over TCP
- TLS:DNS-over-TLS (DoT),加密的 DNS 查询
- HTTPS:DNS-over-HTTPS (DoHT),通过 HTTPS 进行 DNS 查询
2. 丰富的查询选项
- 支持所有标准 DNS 记录类型(A、AAAA、MX、NS、TXT、CNAME 等)
- 支持自定义 nameserver
- 支持 EDNS 选项
- 支持事务 ID 设置
3. 输出格式
- 默认格式:彩色、格式化的输出
- 短格式:只显示第一个结果
- JSON 格式:机器可读的 JSON 输出
- 时间统计:显示查询耗时
4. 国际化支持
- 支持 IDNA(国际化域名)
- 正确处理 Unicode 域名
dog 的使用方法
基本用法
# 查询域名的 A 记录(默认)
dog example.net
# 查询 MX 记录
dog example.net MX
# 使用指定的 nameserver
dog example.net MX @1.1.1.1
# 使用 TCP 协议
dog example.net MX @1.1.1.1 -T
# 使用 DNS-over-TLS
dog example.net @1.1.1.1 -S
# 使用 DNS-over-HTTPS
dog example.net @1.1.1.1 -H
常用选项
查询选项
# 指定查询类型
dog example.net -t MX
# 指定 nameserver
dog example.net -n 8.8.8.8
# 指定查询类(IN、CH、HS)
dog example.net --class=IN
协议选项
# 使用 UDP(默认)
dog example.net -U
# 使用 TCP
dog example.net -T
# 使用 DNS-over-TLS
dog example.net -S
# 使用 DNS-over-HTTPS
dog example.net -H
输出选项
# 短格式(只显示第一个结果)
dog example.net -1
# JSON 输出
dog example.net -J
# 显示查询耗时
dog example.net --time
# 禁用颜色
dog example.net --color=never
实际使用示例
# 查询 Google 的 A 记录
dog google.com
# 查询 Gmail 的 MX 记录
dog gmail.com MX
# 使用 Cloudflare 的 DNS-over-HTTPS 查询
dog example.com @1.1.1.1 -H
# 查询 TXT 记录(常用于 SPF、DKIM 等)
dog example.com TXT
# JSON 格式输出,便于脚本处理
dog example.com -J
# 查询 IPv6 地址
dog example.com AAAA
# 使用自定义 nameserver 查询
dog example.com @8.8.8.8
# 显示查询耗时
dog example.com --time
HarmonyOS 适配过程
项目特点
dog 是一个 Rust 项目,使用 Cargo 作为构建系统。与之前适配的 C/C++ 项目不同,Rust 项目的交叉编译需要特殊的配置,特别是处理依赖库的问题。
适配挑战
- 构建系统差异:从 Makefile 转向 Cargo
- 交叉编译配置:需要配置 Rust 工具链和目标平台
- 依赖库问题:OpenSSL 依赖在交叉编译时难以处理
- TLS 实现选择:需要在 native-tls(OpenSSL)和 rustls(纯 Rust)之间选择
环境准备
1. 系统要求
- macOS(本文示例)或 Linux
- Rust 工具链(rustc 和 cargo)
- HarmonyOS SDK
- Python 3(用于构建脚本)
2. 安装 Rust 工具链
# 检查 Rust 版本
rustc --version
cargo --version
# 如果未安装,使用 rustup 安装
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
3. 安装交叉编译目标
# 添加 aarch64-unknown-linux-musl 目标
rustup target add aarch64-unknown-linux-musl
注意:HarmonyOS 使用 musl libc,因此选择 aarch64-unknown-linux-musl 作为目标平台。
4. 环境变量设置
构建脚本会自动设置以下环境变量:
export CC=${COMPILER_TOOLCHAIN}clang
export CXX=${COMPILER_TOOLCHAIN}clang++
export AR=${COMPILER_TOOLCHAIN}llvm-ar
export RANLIB=${COMPILER_TOOLCHAIN}llvm-ranlib
export STRIP=${COMPILER_TOOLCHAIN}llvm-strip
构建脚本详解
build_ohos.sh 完整代码
export TREE_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/dog.org/dog_1.0.0
# 创建安装目录
mkdir -p ${TREE_INSTALL_HNP_PATH}/usr/bin
mkdir -p ${TREE_INSTALL_HNP_PATH}/usr/share/man/man1
# 设置 Rust 交叉编译目标
# HarmonyOS 使用 musl libc,目标架构是 aarch64
export CARGO_TARGET_DIR=${PWD}/target
export TARGET=aarch64-unknown-linux-musl
# 配置 cargo 使用 HarmonyOS 工具链
export CC_aarch64_unknown_linux_musl=${CC}
export CXX_aarch64_unknown_linux_musl=${CXX}
export AR_aarch64_unknown_linux_musl=${AR}
export RANLIB_aarch64_unknown_linux_musl=${RANLIB}
export STRIP_aarch64_unknown_linux_musl=${STRIP}
# 设置链接器
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=${CC}
# 创建 .cargo 配置目录
mkdir -p .cargo
# 动态生成 .cargo/config.toml
SDK_PATH=${OHOS_SDK:-/Users/jianguo/Desktop/ohosdk}
cat > .cargo/config.toml << EOF
[target.aarch64-unknown-linux-musl]
linker = "clang"
rustflags = [
"-C", "link-arg=--target=aarch64-linux-ohos",
"-C", "link-arg=--sysroot=${SDK_PATH}/native/sysroot",
"-C", "link-arg=-fuse-ld=lld",
"-C", "link-arg=--ld-path=${SDK_PATH}/native/llvm/bin/ld.lld",
"-C", "link-arg=-Wl,--no-as-needed",
]
EOF
# 清理之前的构建
cargo clean 2>/dev/null || true
# 构建 release 版本
# 使用 --no-default-features 禁用默认 features(包括 with_nativetls)
# 然后启用 with_idna, with_tls, with_https, with_rustls
cargo build --release --target ${TARGET} \
--no-default-features \
--features with_idna,with_tls,with_https,with_rustls \
--verbose
# 检查构建产物
BINARY_PATH=${CARGO_TARGET_DIR}/${TARGET}/release/dog
if [ ! -f "${BINARY_PATH}" ]; then
echo "Error: Binary not found at ${BINARY_PATH}"
exit 1
fi
# 安装二进制文件
cp ${BINARY_PATH} ${TREE_INSTALL_HNP_PATH}/usr/bin/dog
chmod +x ${TREE_INSTALL_HNP_PATH}/usr/bin/dog
# 构建并安装 man pages(如果 pandoc 可用)
if command -v pandoc &> /dev/null; then
pandoc --standalone -f markdown -t man man/dog.1.md \
> ${TREE_INSTALL_HNP_PATH}/usr/share/man/man1/dog.1 2>/dev/null || true
fi
# 复制 hnp.json 并打包
cp hnp.json ${TREE_INSTALL_HNP_PATH}/
pushd ${TREE_INSTALL_HNP_PATH}/../
${HNP_TOOL} pack -i ${TREE_INSTALL_HNP_PATH} -o ${ARCHIVE_PATH}/
tar -zvcf ${ARCHIVE_PATH}/ohos_dog_1.0.0.tar.gz dog_1.0.0/
popd
脚本关键点解析
1. 目标平台设置
export TARGET=aarch64-unknown-linux-musl
选择 aarch64-unknown-linux-musl 的原因:
- HarmonyOS 使用 musl libc 而不是 glibc
- 目标架构是 aarch64(ARM64)
- Rust 标准库支持此目标平台
2. 工具链配置
export CC_aarch64_unknown_linux_musl=${CC}
export CXX_aarch64_unknown_linux_musl=${CXX}
export AR_aarch64_unknown_linux_musl=${AR}
Cargo 使用特定格式的环境变量来配置交叉编译工具链:
CC_<target>:C 编译器CXX_<target>:C++ 编译器AR_<target>:归档工具RANLIB_<target>:归档索引工具STRIP_<target>:符号剥离工具
3. 动态生成配置文件
SDK_PATH=${OHOS_SDK:-/Users/jianguo/Desktop/ohosdk}
cat > .cargo/config.toml << EOF
[target.aarch64-unknown-linux-musl]
linker = "clang"
rustflags = [
"-C", "link-arg=--target=aarch64-linux-ohos",
"-C", "link-arg=--sysroot=${SDK_PATH}/native/sysroot",
...
]
EOF
动态生成配置文件的好处:
- 使用环境变量中的 SDK 路径
- 避免硬编码路径
- 适应不同的构建环境
4. Features 选择
cargo build --release --target ${TARGET} \
--no-default-features \
--features with_idna,with_tls,with_https,with_rustls
关键点:
--no-default-features:禁用默认 features(包括with_nativetls)with_rustls:使用纯 Rust 实现的 TLS,避免 OpenSSL 依赖
关键问题解决
问题 1:构建系统错误
错误信息:
make: *** No rule to make target `clean'. Stop.
make: *** No targets specified and no makefile found. Stop.
原因:dog 是 Rust 项目,不使用 Makefile,应该使用 Cargo。
解决方案:将构建脚本从 make 改为 cargo build。
问题 2:OpenSSL 依赖问题
错误信息:
error: failed to run custom build command for `openssl-sys v0.9.61`
Could not find directory of OpenSSL installation, and this `-sys` crate cannot
proceed without this knowledge.
原因:dog 的默认 features 包含 with_nativetls,它依赖系统的 OpenSSL 库。在交叉编译时,很难找到或配置正确的 OpenSSL 库。
解决方案:使用 rustls 替代 native-tls。
OpenSSL 依赖问题
问题分析
dog 项目的默认 features 配置:
[features]
default = ["with_idna", "with_tls", "with_https", "with_nativetls"]
with_nativetls 使用 native-tls crate,它依赖于系统的 OpenSSL 库。在交叉编译时:
- 系统 OpenSSL 不匹配:macOS 上的 OpenSSL 是为 macOS 编译的,不能用于 HarmonyOS
- 交叉编译 OpenSSL 复杂:需要为 HarmonyOS 交叉编译 OpenSSL,过程复杂
- 依赖链问题:OpenSSL 的依赖链很长,容易出错
解决方案:使用 rustls
rustls 是纯 Rust 实现的 TLS 库,不依赖系统的 OpenSSL:
优势:
- ✅ 纯 Rust 实现,无需系统库
- ✅ 交叉编译友好
- ✅ 更小的二进制文件
- ✅ 更好的安全性(内存安全)
劣势:
- ❌ 编译时间稍长(需要编译 TLS 实现)
- ❌ 功能可能不如 OpenSSL 全面(但对于 DNS 客户端足够)
实现方法
修改构建命令:
# 之前(会失败)
cargo build --release --target ${TARGET}
# 之后(成功)
cargo build --release --target ${TARGET} \
--no-default-features \
--features with_idna,with_tls,with_https,with_rustls
关键点:
--no-default-features:禁用所有默认 features,包括with_nativetls--features with_rustls:启用rustls支持- 保留其他功能:
with_idna、with_tls、with_https
验证
构建成功后,可以验证功能:
# 检查二进制文件
file target/aarch64-unknown-linux-musl/release/dog
# 在 HarmonyOS 设备上测试
dog example.com
dog example.com @1.1.1.1 -H # DNS-over-HTTPS
dog example.com @1.1.1.1 -S # DNS-over-TLS
HNP 包配置
hnp.json
{
"type":"hnp-config",
"name":"dog",
"version":"1.0.0",
"install":{}
}
这是一个简单的 HNP 包配置,定义了包的基本信息。
安装目录结构
dog_1.0.0/
├── usr/
│ ├── bin/
│ │ └── dog # 可执行文件
│ └── share/
│ └── man/
│ └── man1/
│ └── dog.1 # 用户手册(如果可用)
└── hnp.json # HNP 包配置
构建结果
构建成功后,会生成以下文件:
-
HNP 包:
dog.org_dog_1.0.0.hnp- HarmonyOS 原生包格式
- 可以直接安装到 HarmonyOS 设备
-
Tar 归档:
ohos_dog_1.0.0.tar.gz- 压缩的 tar 归档
- 包含完整的安装目录结构
构建输出示例
==========================================
Build completed successfully!
==========================================
HNP Package: /path/to/archive/dog.org_dog_1.0.0.hnp
Tar Archive: /path/to/archive/ohos_dog_1.0.0.tar.gz
Installation Path: /path/to/data/service/hnp/dog.org/dog_1.0.0
==========================================
使用示例
在 HarmonyOS 上使用 dog
安装 HNP 包后,可以在 HarmonyOS 设备上使用 dog:
# 基本 DNS 查询
dog example.com
# 查询 MX 记录
dog example.com MX
# 使用 Cloudflare 的 DNS-over-HTTPS
dog example.com @1.1.1.1 -H
# 使用 Google 的 DNS-over-TLS
dog example.com @8.8.8.8 -S
# JSON 格式输出
dog example.com -J
# 查询 IPv6 地址
dog example.com AAAA
# 显示查询耗时
dog example.com --time
# 短格式输出
dog example.com -1
实际应用场景
-
DNS 故障排查:
# 检查域名解析是否正常 dog example.com # 使用不同的 nameserver 对比 dog example.com @8.8.8.8 dog example.com @1.1.1.1 -
邮件服务器配置检查:
# 检查 MX 记录 dog example.com MX -
安全查询:
# 使用加密的 DNS-over-HTTPS dog example.com @1.1.1.1 -H -
脚本集成:
# JSON 格式便于脚本处理 dog example.com -J | jq '.answers[0].data'
总结
适配要点
- 构建系统转换:从 Makefile 转向 Cargo,需要理解 Rust 的构建系统
- 交叉编译配置:正确配置 Rust 工具链和目标平台
- 依赖库选择:使用
rustls替代native-tls,避免 OpenSSL 依赖 - 动态配置生成:通过脚本动态生成
.cargo/config.toml,适应不同环境
关键决策
- 选择 rustls:避免 OpenSSL 交叉编译的复杂性
- 动态配置:使用环境变量生成配置文件,提高灵活性
- 保留核心功能:虽然禁用了
native-tls,但通过rustls保留了 TLS/HTTPS 支持
优势
- 单二进制文件:dog 编译后是单个可执行文件,部署简单
- 高性能:Rust 编写,运行速度快
- 功能完整:支持所有主要 DNS 协议和记录类型
- 现代化:支持 DNS-over-TLS 和 DNS-over-HTTPS
适用场景
- DNS 故障排查和诊断
- 网络配置验证
- 安全 DNS 查询(DoT/DoHT)
- 脚本自动化(JSON 输出)
- 学习和理解 DNS 协议
FAQ
Q1: 为什么选择 aarch64-unknown-linux-musl 作为目标平台?
A: HarmonyOS 使用 musl libc 而不是 glibc,因此选择 musl 变体。架构是 aarch64(ARM64),这是 HarmonyOS 的主要架构。
Q2: 为什么使用 rustls 而不是 native-tls?
A: native-tls 依赖系统的 OpenSSL 库,在交叉编译时很难配置。rustls 是纯 Rust 实现,不需要系统库,交叉编译友好。
Q3: 使用 rustls 会影响功能吗?
A: 对于 DNS 客户端的使用场景,rustls 完全足够。它支持 TLS 1.2 和 1.3,可以正常使用 DNS-over-TLS 和 DNS-over-HTTPS。
Q4: 如何验证构建的二进制文件?
A: 可以使用 file 命令检查:
file target/aarch64-unknown-linux-musl/release/dog
应该显示类似:ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), ...
Q5: 构建失败怎么办?
A: 检查以下几点:
- Rust 工具链是否正确安装
- 交叉编译目标是否已添加:
rustup target add aarch64-unknown-linux-musl - HarmonyOS SDK 路径是否正确
- 环境变量是否正确设置
Q6: Man pages 是必需的吗?
A: 不是必需的。Man pages 是可选的,只有在系统安装了 pandoc 时才会构建。即使没有 man pages,dog 也可以正常使用。
Q7: 可以在其他架构上构建吗?
A: 当前配置针对 aarch64 架构。如果需要支持其他架构(如 x86_64),需要修改目标平台和相应的工具链配置。
Q8: 如何更新 .cargo/config.toml 中的 SDK 路径?
A: 构建脚本会从 OHOS_SDK 环境变量读取 SDK 路径,并动态生成配置文件。如果需要修改,设置 OHOS_SDK 环境变量即可。
相关链接
- dog 官方网站:https://dns.lookup.dog/
- dog GitHub 仓库:https://github.com/ogham/dog
- HarmonyOS 适配仓库:https://gitcode.com/nutpi/dog
- Rust 交叉编译文档:https://rust-lang.github.io/rustup/cross-compilation.html
- rustls 项目:https://github.com/rustls/rustls
- Cargo 配置文档:https://doc.rust-lang.org/cargo/reference/config.html
- HarmonyOS 开发者文档:https://developer.harmonyos.com/
- PC代码仓
欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/
更多推荐

所有评论(0)