You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于DNS反向代理根据CNAME源域名返回对应TXT记录的可行性及实现方法问询

关于DNS反向代理根据CNAME源域名返回对应TXT记录的可行性及实现方法问询

首先明确说:这种需求是可以实现的,但得绕开DNS标准里的一些限制,或者调整下实现思路——毕竟CNAME记录本身有个硬性规则:设置了CNAME的域名不能同时存在其他记录(比如TXT),所以直接给sample.somedomain.com设CNAME再绑TXT是不符合标准的,递归DNS服务器只会去查CNAME指向的mydomain.example.com的记录。

下面分两种可行的实现路径给你讲:


一、推荐方案:放弃CNAME,直接用自定义DNS代理托管目标域名

这是最符合DNS标准、也最容易实现的方式:

  • 把sample.somedomain.com和test.anotherdomain.com的权威DNS服务器指向你搭建的自定义DNS代理
  • 代理服务器收到TXT查询请求时,直接根据原始查询域名返回对应的TXT内容

举个具体的实现例子,用Python的dnspython库写个轻量代理:

  1. 先安装依赖:pip install dnspython
  2. 写个简单的代理脚本:
import dns
from dns import resolver, message
from dns.query import udp, tcp
import socket

UPSTREAM_DNS = '8.8.8.8'  # 上游公共DNS服务器
LISTEN_PORT = 53

# 自定义TXT记录映射,末尾要加域名根点"."
TXT_RECORDS = {
    'sample.somedomain.com.': ['"sample-specific-TXT-content"'],
    'test.anotherdomain.com.': ['"test-specific-TXT-content"']
}

def handle_dns_request(data, addr, sock):
    try:
        request = message.from_wire(data)
        response = message.make_response(request)
        response.flags |= message.AA  # 标记为权威应答

        qname = request.question[0].name.to_text()
        qtype = request.question[0].rdtype

        if qtype == dns.rdatatype.TXT and qname in TXT_RECORDS:
            # 返回预设的自定义TXT记录
            for txt_content in TXT_RECORDS[qname]:
                response.answer.append(dns.rrset.from_text(qname, 300, dns.rdataclass.IN, 'TXT', txt_content))
        else:
            # 非目标域名的请求转发到上游DNS处理
            if request.flags & message.TC:
                upstream_response = tcp(request, UPSTREAM_DNS)
            else:
                upstream_response = udp(request, UPSTREAM_DNS)
            response = upstream_response

        sock.sendto(response.to_wire(), addr)
    except Exception as e:
        print(f"Error handling request: {e}")

def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind(('0.0.0.0', LISTEN_PORT))
    print(f"DNS proxy running on port {LISTEN_PORT}")
    while True:
        data, addr = sock.recvfrom(512)
        handle_dns_request(data, addr, sock)

if __name__ == '__main__':
    main()
  1. 启动脚本后,把sample.somedomain.com和test.anotherdomain.com的NS记录指向运行这个代理的服务器IP,这样所有针对这两个域名的TXT查询都会返回你预设的内容。

二、基于CNAME的特殊实现(不推荐,需自定义扩展)

如果你一定要保留CNAME指向mydomain.example.com的结构,那需要你的DNS代理服务器能追踪原始查询的域名——但这里有个问题:标准DNS递归查询中,当递归服务器发现sample.somedomain.com是CNAME后,会直接查询mydomain.example.com的TXT,这时候你的代理收到的查询请求域名是mydomain.example.com,根本不知道原始请求是来自sample还是test。

要解决这个,只能做特殊处理:

  1. 让所有客户端直接使用你的代理作为递归DNS服务器,这样代理能看到原始的查询域名(比如客户端直接查sample.somedomain.com的TXT)
  2. 在代理中添加逻辑:当收到sample.somedomain.com的TXT查询时,忽略它的CNAME记录,直接返回对应的TXT内容(相当于“绕过”CNAME跳转)

比如用PowerDNS的Lua脚本后端实现这个逻辑:

function pdns_records(dq)
    -- 只处理TXT类型查询
    if dq.qtype == pdns.TXT then
        local qname = dq.qname:toString()
        -- 根据原始查询域名返回对应TXT记录
        if qname == "sample.somedomain.com." then
            return { { content = '"sample-TXT-content"', qtype = pdns.TXT, ttl = 300 } }
        elseif qname == "test.anotherdomain.com." then
            return { { content = '"test-TXT-content"', qtype = pdns.TXT, ttl = 300 } }
        end
    end
    -- 其他类型/域名的查询,返回nil让PowerDNS用默认逻辑处理
    return nil
end

然后配置PowerDNS使用这个Lua后端,同时确保客户端的DNS设置指向你的PowerDNS服务器。


你之前尝试失败可能的原因

  • 没有捕获到原始查询域名:如果你的代理只是作为mydomain.example.com的权威DNS,那收到的查询都是针对mydomain的,根本不知道是哪个CNAME跳转过来的
  • 违反了CNAME和其他记录共存的规则:你可能尝试给设了CNAME的域名同时加TXT记录,这在DNS标准里是不允许的,递归服务器会直接忽略TXT记录

备注:内容来源于stack exchange,提问作者venkat S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 12:48:15