自建 DNS over HTTPS(DoH)并在 macOS 配置使用

这篇文章简单记录自建DNS over HTTPS(DoH)服务的步骤。

架构说明

  1. 上游DNS100.100.100.100:53
  2. DoH服务satishweb/doh-server Docker容器(监听100.100.100.100:1053
  3. 前端代理:Nginx提供HTTPS并反向代理到DoH服务
  4. 客户端:macOS通过配置文件接入

一、部署DoH服务器(Docker容器)

# 停止并删除旧容器
docker stop doh && docker rm doh

# 启动DoH容器
docker run -d --restart unless-stopped \
  --network host \
  --name doh \
  -e UPSTREAM_DNS_SERVER="udp:100.100.100.100:53" \
  -e DOH_HTTP_PREFIX="/dns-query" \
  -e DOH_SERVER_LISTEN="100.100.100.100:1053" \
  -e DOH_SERVER_TIMEOUT="10" \
  -e DOH_SERVER_TRIES="3" \
  -e DOH_SERVER_VERBOSE="true" \
  satishweb/doh-server

关键参数说明

  • UPSTREAM_DNS_SERVER:上游DNS地址(需可被容器访问)
  • DOH_SERVER_LISTEN:容器监听的本地地址和端口
  • DOH_HTTP_PREFIX:DoH请求路径(必须与Nginx配置一致)

二、配置Nginx反向代理

在Nginx站点配置中(如/etc/nginx/sites-available/default)添加:

server {
    listen 443 ssl;
    server_name blog.kelu.org;  # 替换为您的域名

    # SSL证书配置(必需)
    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    # DoH代理配置
    location = /dns-query {
        allow 100.100.100.5;   # 允许访问的客户端IP
        deny all;               # 禁止其他IP
        proxy_pass http://100.100.100.100:1053;  # 指向DoH容器
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # 其他配置...
}

操作命令

sudo nginx -t && sudo systemctl reload nginx  # 测试并重载配置

直接访问地址,验证是否成功:

https://aa.bb.com/dns-query?name=baidu.com&type=A

image-20250626午後51343065

三、客户端配置(macOS)

  1. 手工生成配置文件 doh.mobileconfig

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>PayloadContent</key>
        <array>
            <dict>
                <key>DNSSettings</key>
                <dict>
                    <key>DNSProtocol</key>
                    <string>HTTPS</string>
                    <key>ServerURL</key>
                    <string>https://blog.kelu.org/dns-query</string> <!-- 改为您的域名 -->
                </dict>
                <key>PayloadDescription</key>
                <string>Configures DNS over HTTPS</string>
                <key>PayloadDisplayName</key>
                <string>DoH DNS Server</string>
                <key>PayloadIdentifier</key>
                <string>com.yourdomain.dns</string>
                <key>PayloadType</key>
                <string>com.apple.dnsSettings.managed</string>
                <key>PayloadUUID</key>
                <string>065AB183-5E34-4794-9BEB-B5327CF61F27</string> <!-- 用uuidgen生成 -->
                <key>PayloadVersion</key>
                <integer>1</integer>
            </dict>
        </array>
        <key>PayloadDescription</key>
        <string>Install to enable DNS over HTTPS</string>
        <key>PayloadDisplayName</key>
        <string>Custom DoH Configuration</string>
        <key>PayloadIdentifier</key>
        <string>com.yourdomain.dohprofile</string>
        <key>PayloadUUID</key>
        <string>030E6D6F-69A2-4515-9D77-99342CB9AE76</string> <!-- 用uuidgen生成 -->
        <key>PayloadVersion</key>
        <integer>1</integer>
    </dict>
    </plist>
    
    • 替换 ServerURL 为您的HTTPS地址 - 使用 uuidgen 命令生成新的 PayloadUUID
  2. 安装配置

    • 双击 .mobileconfig 文件导入macOS

      image-20250626午後51135751

      提醒打开系统设定,在设备管理里可以看到:

      image-20250626午後51214021

      双击后安装即可。

四、验证服务

  1. 测试DoH服务

    curl -H 'content-type: application/dns-message' \
      "https://blog.kelu.org/dns-query?dns=q80BAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB" 
    

    正常应返回加密的DNS响应。

  2. 客户端检查

    • 在macOS终端执行 scutil --dns | grep 'nameserver\[0\]'
    • 查看日志:docker logs doh

    日志大概长这个样:

    image-20250626午後55524139


使用 wstunnel 在 macOS 上安全连接 Linux 服务器