mcpField
D
dotnet-devcert-trust

dotnet-devcert-trust

github.com/aaronontheweb开发1.2k445 次安装今天更新
代码仓库

关于 dotnet-devcert-trust

面向 .NET 开发者的 Linux 开发证书信任诊断与修复指南,涵盖证书存储检查、发行版专属恢复步骤及 Aspire TLS 问题排查。

主要功能

  1. 01五步证书信任诊断
  2. 02验证系统 CA 证书包
  3. 03检查环境变量与符号链接
  4. 04按 Linux 发行版恢复信任
  5. 05排查 Aspire TLS 问题

适用场景

  1. 01修复 Aspire Redis 的 UntrustedRoot 错误
  2. 02恢复 localhost HTTPS 证书信任
  3. 03配置 Linux .NET HTTPS 开发环境

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/aaronontheweb/dotnet-skills --skill dotnet-devcert-trust

安装后在 Claude Code 中输入/dotnet-devcert-trust确认已加载。

详细介绍

Linux 上的 .NET 开发证书信任

何时使用此技能

在以下情况下使用此技能:

  • Aspire 中的 Redis TLS 连接因 UntrustedRoot 或 RemoteCertificateNameMismatch 而失败
  • dotnet dev-certs https --check --trust 返回退出代码 7
  • HTTPS localhost 连接因证书验证错误而失败
  • 运行 dotnet dev-certs https --clean 后需要恢复信任
  • 为 .NET HTTPS 开发设置新的 Linux 开发机器
  • Aspire 仪表板或服务间 gRPC 调用因 TLS 错误而失败
  • 从 Aspire < 13.1.0 升级(该版本默认不会在 Redis 上使用 TLS)

问题所在

在 Windows 和 macOS 上,dotnet dev-certs https --trust 会自动处理所有事情——生成证书、将其安装到用户存储区,并将其添加到系统信任存储区。在 Linux 上,它几乎毫无用处。该命令会生成证书并将其放入用户存储区,但:

  1. 它不会将证书导出到系统 CA 目录
  2. 它不会运行 update-ca-certificates 来重建 CA 捆绑包
  3. 它不会将证书添加到浏览器信任存储区(NSS/NSSDB)
  4. --trust 标志会静默地成功,但证书仍不受信任

这意味着 .NET 应用程序、OpenSSL、curl 和浏览器都会拒绝该开发证书——即使 dotnet dev-certs https --check 报告证书存在。

为什么此问题会在 Aspire 13.1.0 及更高版本中出现

在 Aspire 13.1.0 之前,Redis 连接使用明文。从 13.1.0 开始,Aspire 默认在 Redis 上启用 TLS。如果你的开发证书未在系统级别受信任,Redis 连接会立即失败,并显示:

System.Security.Authentication.AuthenticationException:
  The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot

Linux 证书信任的工作原理

了解其架构可避免盲目照搬的调试方法:

┌─────────────────────────────────────────────────────┐
│ Application (.NET, curl, OpenSSL)                   │
│   reads: /etc/ssl/certs/ca-certificates.crt         │
│          (consolidated CA bundle)                    │
└──────────────────────┬──────────────────────────────┘
                       │ built by
┌──────────────────────▼──────────────────────────────┐
│ update-ca-certificates                              │
│   reads from:                                        │
│     /usr/share/ca-certificates/      (distro CAs)   │
│     /usr/local/share/ca-certificates/ (local CAs)   │
│   writes to:                                         │
│     /etc/ssl/certs/ca-certificates.crt (bundle)     │
│     /etc/ssl/certs/*.pem (individual symlinks)      │
└─────────────────────────────────────────────────────┘

重要提示:将 .crt 文件放入 /usr/local/share/ca-certificates/ 是必要的,但还不够。必须运行 update-ca-certificates,以重建 /etc/ssl/certs/ca-certificates.crt 中的整合捆绑包。应用程序读取的是捆绑包,而不是单个文件。

5 点诊断步骤

按顺序运行这些检查。遇到第一个 FAIL 时停止,先应用对应的修复,再继续。

检查 1:开发证书是否存在
dotnet dev-certs https --check
echo "Exit code: $?"
退出代码含义操作
0用户存储区中存在证书PASS — 继续
非零没有有效的开发证书运行 dotnet dev-certs https
检查 2:系统信任存储区——单个证书且权限正确
ls -la /usr/local/share/ca-certificates/ | grep -iE 'dotnet|aspnet'
结果含义
仅有 dotnet-dev-cert.crt,权限为 -rw-r--r--(644)PASS
存在多个证书文件、权限不正确或过期的 aspnet* 文件FAIL

之前操作遗留的常见过期文件:

文件问题
aspnetcore-dev.crt通常以 0600 权限创建(update-ca-certificates 无法读取)
aspnet/https.crt旧版命名约定,指纹可能与当前开发证书不同
权限为 0600 的 dotnet-dev-cert.crt名称正确,但权限不正确

修复:

# Remove ALL stale cert files
sudo rm -f /usr/local/share/ca-certificates/aspnetcore-dev.crt
sudo rm -rf /usr/local/share/ca-certificates/aspnet/

# Ensure correct permissions on the dev cert (if it exists)
sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
检查 3:CA 捆绑包中是否包含证书

这是最常见的失败项。证书文件存在,但从未添加到捆绑包中。

openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \
  /usr/local/share/ca-certificates/dotnet-dev-cert.crt
结果含义
dotnet-dev-cert.crt: OKPASS — 证书位于整合捆绑包中
error 20 at 0 depth lookup: unable to get local issuer certificateFAIL — 从未重建捆绑包
error 2 at 0 depth lookup: unable to get issuer certificateFAIL — 同一问题,不同的 OpenSSL 版本

修复:

sudo update-ca-certificates
# Expected output includes "1 added" or similar

# Re-verify
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \
  /usr/local/share/ca-certificates/dotnet-dev-cert.crt
检查 4:环境变量覆盖

SSL 环境变量可能会将证书查找重定向到系统捆绑包之外:

echo "SSL_CERT_DIR=${SSL_CERT_DIR:-<unset>}"
echo "SSL_CERT_FILE=${SSL_CERT_FILE:-<unset>}"
echo "DOTNET_SSL_CERT_DIR=${DOTNET_SSL_CERT_DIR:-<unset>}"
echo "DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=${DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER:-<unset>}"
结果含义
全部为 <unset>PASS
任一变量已设置FAIL — 可能会重定向证书查找

**修复:**从 shell 配置文件(~/.bashrc、~/.zshrc、~/.profile)中移除有问题的变量,然后启动新的 shell。

检查 5:符号链接完整性

以前删除的证书留下的过期符号链接可能会让 OpenSSL 产生混淆:

find /etc/ssl/certs/ -xtype l 2>/dev/null | head -5
结果含义
没有输出通过
列出失效的符号链接失败

修复方法:

sudo update-ca-certificates --fresh
# Rebuilds ALL symlinks from scratch

完整恢复流程

如果有多项检查未通过,或你想从头开始,请运行以下完整流程:

#!/usr/bin/env bash
set -euo pipefail

echo "=== .NET Dev Certificate Trust Recovery ==="

# Step 1: Remove ALL stale certificate files
echo "--- Removing stale certificate files ---"
sudo rm -f /usr/local/share/ca-certificates/aspnetcore-dev.crt
sudo rm -rf /usr/local/share/ca-certificates/aspnet/
sudo rm -f /usr/local/share/ca-certificates/dotnet-dev-cert.crt

# Step 2: Clean and regenerate dev cert
echo "--- Regenerating dev certificate ---"
dotnet dev-certs https --clean
dotnet dev-certs https

# Step 3: Export as PEM and install to system trust store
echo "--- Installing to system trust store ---"
dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
rm /tmp/dotnet-dev-cert.crt

# Step 4: Rebuild CA bundle (CRITICAL — most commonly missed step)
echo "--- Rebuilding CA bundle ---"
sudo update-ca-certificates

# Step 5: Verify
echo "--- Verifying ---"
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \
  /usr/local/share/ca-certificates/dotnet-dev-cert.crt

echo "=== Done! Restart your .NET application. ==="

将其保存为 ~/fix-devcert.sh,需要时运行 bash ~/fix-devcert.sh。

特定发行版说明

Ubuntu / Debian

上述流程针对 Ubuntu/Debian 编写,可直接使用。

  • CA 目录: /usr/local/share/ca-certificates/
  • 证书包命令: sudo update-ca-certificates
  • 证书包输出: /etc/ssl/certs/ca-certificates.crt
  • 证书格式: 必须使用带 .crt 扩展名的 PEM 格式
Fedora / RHEL / CentOS

Fedora 使用 update-ca-trust,而不是 update-ca-certificates:

# Export cert
dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.pem --format PEM --no-password

# Install to Fedora trust store (different directory!)
sudo cp /tmp/dotnet-dev-cert.pem /etc/pki/ca-trust/source/anchors/dotnet-dev-cert.pem
sudo chmod 644 /etc/pki/ca-trust/source/anchors/dotnet-dev-cert.pem
rm /tmp/dotnet-dev-cert.pem

# Rebuild trust bundle
sudo update-ca-trust

# Verify
openssl verify /etc/pki/ca-trust/source/anchors/dotnet-dev-cert.pem

主要区别:

Ubuntu/DebianFedora/RHEL
CA 目录/usr/local/share/ca-certificates//etc/pki/ca-trust/source/anchors/
重建命令update-ca-certificatesupdate-ca-trust
证书包路径/etc/ssl/certs/ca-certificates.crt/etc/pki/tls/certs/ca-bundle.crt
扩展名.crt.pem(可使用任意扩展名)
Arch Linux

Arch 使用与 Fedora 相同的 update-ca-trust 方式:

sudo cp /tmp/dotnet-dev-cert.pem /etc/ca-certificates/trust-source/anchors/dotnet-dev-cert.pem
sudo chmod 644 /etc/ca-certificates/trust-source/anchors/dotnet-dev-cert.pem
sudo update-ca-trust
WSL2

WSL2 运行独立的 Linux 内核,并拥有自己的证书存储区,与 Windows 主机分开。标准的 Ubuntu/Debian 流程适用,但请注意:

  1. 共享文件系统(/mnt/c/) — Windows 文件系统中的证书文件具有 Windows 权限,可能不是 644。请务必先将文件复制到 Linux 原生路径。
  2. systemd 未运行 — 某些较旧的 WSL2 配置没有 systemd,而 update-ca-certificates 钩子可能依赖它。如果命令卡住,请改试 sudo dpkg-reconfigure ca-certificates。
  3. Docker Desktop 集成 — 如果使用 Docker Desktop 的 WSL2 后端,容器会继承 WSL2 发行版的 CA 证书包。在 WSL2 中修复信任问题也会修复容器中的问题。

Aspire 特定注意事项

Redis TLS(Aspire 13.1.0+)

Aspire 13.1.0 默认在 Redis 上启用 TLS。如果你看到:

UntrustedRoot

出现在 Redis 连接错误中,说明系统级别不信任开发证书。请运行上述完整恢复流程。

Aspire Dashboard HTTPS

Aspire Dashboard 使用开发证书进行 HTTPS 连接。如果浏览器中出现 Dashboard 证书警告,说明证书不在浏览器的信任存储区中。开发期间可以点击警告继续访问——优先处理系统级信任(Redis、gRPC 等所需)。

ASPIRE_ALLOW_UNSECURED_TRANSPORT

设置 ASPIRE_ALLOW_UNSECURED_TRANSPORT=true 是一种权宜之计,并非修复方法。它会禁用服务间通信的 TLS,因此:

  • 掩盖底层信任问题
  • 与生产环境行为不一致
  • 可能导致与生产环境中不同的问题

请改为修复证书信任问题。

证书生命周期

开发证书自创建之日起有效期为 1 年。证书过期时:

  1. dotnet dev-certs https --check 会报告没有有效证书
  2. 运行完整恢复流程以生成新证书
  3. /usr/local/share/ca-certificates/ 中的旧证书文件会被替换
  4. update-ca-certificates 会在证书包中用新证书替换旧证书

无需重启系统。 应用会在下一次 TLS 握手时使用新的证书包(请重启应用)。

自动化:CI/CD 管道

在 Linux 运行器上的 CI/CD 中,通常很少需要开发证书(一般会使用真实证书进行测试,或在测试框架中禁用 TLS 验证)。不过,如果集成测试需要受信任的开发证书:

GitHub Actions
- name: Trust .NET Dev Certificate
  run: |
    dotnet dev-certs https
    dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
    sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
    sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
    rm /tmp/dotnet-dev-cert.crt
    sudo update-ca-certificates
Azure DevOps
- script: |
    dotnet dev-certs https
    dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
    sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
    sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
    rm /tmp/dotnet-dev-cert.crt
    sudo update-ca-certificates
  displayName: 'Trust .NET Dev Certificate'

常见问题

1. 已放置证书,但从未重新生成证书包

症状: /usr/local/share/ca-certificates/ 中存在证书文件,但 openssl verify 验证失败。

原因: 放置文件后没有运行 update-ca-certificates。

修复方法: sudo update-ca-certificates

这是最常见的错误。CA 目录是生成证书包过程的输入,而不是证书包本身。

2. 证书文件过期且权限错误

症状: 运行 update-ca-certificates 后报告添加了 0 个证书。

原因: 权限为 0600 的证书文件无法被 update-ca-certificates 读取(该命令以 root 身份运行,但可能通过会检查文件是否对所有用户可读的进程读取文件)。文件权限必须为 644。

修复方法: sudo chmod 644 /usr/local/share/ca-certificates/*.crt

3. 不同会话留下了多个证书文件

症状: update-ca-certificates 添加了多个证书,但应用仍然失败。

原因: 先前运行 dotnet dev-certs https --clean 并重新生成证书后,旧证书文件仍留在 CA 目录中。旧证书的指纹与当前开发证书不匹配。

修复方法: 删除所有 dotnet* 和 aspnet* 文件,然后重新导出当前证书。

4. 清理并重新生成后指纹不匹配

症状: openssl verify 验证通过,但 .NET 仍报告 UntrustedRoot。

原因: /usr/local/share/ca-certificates/ 中的证书是从之前的开发证书导出的。运行 dotnet dev-certs https --clean && dotnet dev-certs https 后,生成了指纹不同的新证书。系统信任的是旧证书,而不是新证书。

修复方法: 重新导出并安装:

dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password
sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
sudo update-ca-certificates
5. 使用 --trust 并假定其生效

症状: dotnet dev-certs https --trust 返回退出代码 0,但实际上没有信任任何证书。

原因: 在 Linux 上,--trust 会尝试将证书添加到 OpenSSL 信任存储,但不会调用 update-ca-certificates。从 dotnet 的角度看,此操作“成功”了,但证书包并未改变。

修复方法: 在 Linux 上不要依赖 --trust。请按照此技能中的手动流程操作。

快速参考

# Generate dev cert (if missing)
dotnet dev-certs https

# Export as PEM
dotnet dev-certs https --export-path /tmp/dotnet-dev-cert.crt --format PEM --no-password

# Install to system trust (Ubuntu/Debian)
sudo cp /tmp/dotnet-dev-cert.crt /usr/local/share/ca-certificates/dotnet-dev-cert.crt
sudo chmod 644 /usr/local/share/ca-certificates/dotnet-dev-cert.crt
sudo update-ca-certificates

# Verify trust
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \
  /usr/local/share/ca-certificates/dotnet-dev-cert.crt

# Check cert details
openssl x509 -in /usr/local/share/ca-certificates/dotnet-dev-cert.crt -noout -subject -dates -fingerprint

# Nuclear option: full clean + rebuild
dotnet dev-certs https --clean && dotnet dev-certs https

相关技能

  • dotnet-skills:aspire-configuration — Aspire AppHost 配置,包括 TLS 设置
  • dotnet-skills:aspire-service-defaults — 服务默认设置,包括 HTTPS 配置

评论

支持 Markdown