目录


项目简介

项目名称 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 项目的交叉编译需要特殊的配置,特别是处理依赖库的问题。

适配挑战

  1. 构建系统差异:从 Makefile 转向 Cargo
  2. 交叉编译配置:需要配置 Rust 工具链和目标平台
  3. 依赖库问题:OpenSSL 依赖在交叉编译时难以处理
  4. 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 库。在交叉编译时:

  1. 系统 OpenSSL 不匹配:macOS 上的 OpenSSL 是为 macOS 编译的,不能用于 HarmonyOS
  2. 交叉编译 OpenSSL 复杂:需要为 HarmonyOS 交叉编译 OpenSSL,过程复杂
  3. 依赖链问题: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

关键点

  1. --no-default-features:禁用所有默认 features,包括 with_nativetls
  2. --features with_rustls:启用 rustls 支持
  3. 保留其他功能:with_idnawith_tlswith_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 包配置

构建结果

构建成功后,会生成以下文件:

  1. HNP 包dog.org_dog_1.0.0.hnp

    • HarmonyOS 原生包格式
    • 可以直接安装到 HarmonyOS 设备
  2. 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

实际应用场景

  1. DNS 故障排查

    # 检查域名解析是否正常
    dog example.com
    
    # 使用不同的 nameserver 对比
    dog example.com @8.8.8.8
    dog example.com @1.1.1.1
    
  2. 邮件服务器配置检查

    # 检查 MX 记录
    dog example.com MX
    
  3. 安全查询

    # 使用加密的 DNS-over-HTTPS
    dog example.com @1.1.1.1 -H
    
  4. 脚本集成

    # JSON 格式便于脚本处理
    dog example.com -J | jq '.answers[0].data'
    

总结

适配要点

  1. 构建系统转换:从 Makefile 转向 Cargo,需要理解 Rust 的构建系统
  2. 交叉编译配置:正确配置 Rust 工具链和目标平台
  3. 依赖库选择:使用 rustls 替代 native-tls,避免 OpenSSL 依赖
  4. 动态配置生成:通过脚本动态生成 .cargo/config.toml,适应不同环境

关键决策

  1. 选择 rustls:避免 OpenSSL 交叉编译的复杂性
  2. 动态配置:使用环境变量生成配置文件,提高灵活性
  3. 保留核心功能:虽然禁用了 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: 检查以下几点:

  1. Rust 工具链是否正确安装
  2. 交叉编译目标是否已添加:rustup target add aarch64-unknown-linux-musl
  3. HarmonyOS SDK 路径是否正确
  4. 环境变量是否正确设置

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/

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐