Python DNS 替代方案

Python DNS 替代方案

我有几个在 OpenStack 上运行 Debian/GNU Linux 的虚拟机。解析它们的内部 IPv4 地址时,我得到了一些奇怪的结果:

# ip -c addr show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 10.201.2.214/16 brd 10.201.255.255 scope global dynamic eth0

# dig 214.2.201.10.in-addr.arpa. ptr
;; Warning: Message parser reports malformed message packet.

; <<>> DiG 9.11.5-P4-5.1+deb10u8A~5.0.2.202210101801-Univention <<>> 214.2.201.10.in-addr.arpa. ptr
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20796
;; flags: qr rd ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; WARNING: Message has 70 extra bytes at end

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 881af249ef946da8 (echoed)
;; QUESTION SECTION:
;214.2.201.10.in-addr.arpa.     IN      PTR

;; Query time: 3 msec
;; SERVER: 10.0.2.3#53(10.0.2.3)
;; WHEN: Tue Jun 13 15:42:59 CEST 2023
;; MSG SIZE  rcvd: 136

请注意以下几点:

  1. dig不打印答案,但是增强型DNS OPT PSEUDISECTION
  2. 相反,出现了一些奇怪的警告:

警告:消息解析器报告格式错误的消息包。

警告:消息末尾有 70 个额外字节

Python DNS 替代方案

如果我使用它python3进行 DNS 查询,我会得到一个答案:

# python3 -c 'import dns.resolver
r = dns.resolver.Resolver()
q = r.query("214.2.201.10.in-addr.arpa.", "PTR")
print(q.rrset[0])'
dc0.a.customers.regiocloud.tech.

这是预料之中的,因为我在这里使用 OpenStack 通过 DHCP 提供的 DNS 服务器。

但即使我将名称服务器更改为使用任何其他服务器(例如 Quad9、Google8、随机 1.2.3.4 等),我仍然得到相同的答案:

# python3 -c 'import sys,dns.resolver
r = dns.resolver.Resolver()
r.nameservers = [sys.argv[1]]
q = r.query("214.2.201.10.in-addr.arpa.", "PTR")
print(q.rrset[0])' '9.9.9.9'
dc0.a.customers.regiocloud.tech.

OpenStack 似乎做了一些 DNS中间人截距。

Wireshark

dig对于另一台具有不同 IPv4 的虚拟机,我使用以下方法捕获了原始跟踪wireshark

Domain Name System (response)
    Transaction ID: 0x5853
    Flags: 0x8120 Standard query response, No error
        1... .... .... .... = Response: Message is a response
        .000 0... .... .... = Opcode: Standard query (0)
        .... .0.. .... .... = Authoritative: Server is not an authority for domain
        .... ..0. .... .... = Truncated: Message is not truncated
        .... ...1 .... .... = Recursion desired: Do query recursively
        .... .... 0... .... = Recursion available: Server can't do recursive queries
        .... .... .0.. .... = Z: reserved (0)
        .... .... ..1. .... = Answer authenticated: Answer/authority portion was authenticated by the server
        .... .... ...0 .... = Non-authenticated data: Unacceptable
        .... .... .... 0000 = Reply code: No error (0)
    Questions: 1
    Answer RRs: 1
    Authority RRs: 0
    Additional RRs: 0
    Queries
        136.0.201.10.in-addr.arpa: type PTR, class IN
            Name: 136.0.201.10.in-addr.arpa
            [Name Length: 25]
            [Label Count: 6]
            Type: PTR (domain name PoinTeR) (12)
            Class: IN (0x0001)
    Answers
        <Root>: type OPT
            Name: <Root>
            Type: OPT (41)
            UDP payload size: 4096
            Higher bits in extended RCODE: 0x00
            EDNS0 version: 0
            Z: 0x0000
                0... .... .... .... = DO bit: Cannot handle DNSSEC security RRs
                .000 0000 0000 0000 = Reserved: 0x0000
            Data length: 12
            Option: COOKIE
    [Request In: 1]
    [Time: 0.003197000 seconds]

请注意Answer RRs: 1,此处的 解释了dig对附加数据的抱怨:仅EDNS OPT记录被考虑,而不是第二个答案。修补捕获的数据包文件后,Answer RRs: 2我看到了 中的第二个答案记录wireshark,其中包含缺失的PTR记录dig未打印的

136.0.201.10.in-addr.arpa: type PTR, class IN, phahn-1st.a.customers.regiocloud.tech
    Name: 136.0.201.10.in-addr.arpa
    Type: PTR (domain name PoinTeR) (12)
    Class: IN (0x0001)
    Time to live: 3600 (1 hour)
    Data length: 39
    Domain Name: phahn-1st.a.customers.regiocloud.tech

问题

  1. 如何防止 OpenStack 拦截 DNS PTR 查询并自行应答,它应该转到配置的 DNS 服务器/etc/resolv.conf
  2. OpenStack 的答案似乎让人困惑dig,但 Pythons 却不是这样dns。需要重新配置什么才能使dig工作?

额外尝试

我已经读过了OpenStack:DNS 集成,但没有发现任何可操作的内容。(我不是 OpenStack 专家,并且该环境不由我管理)

如果我使用dig +tcp强制使用TCP而不是UDP,则查询不会被拦截,而是由真正的 DNS 服务器应答。

执行dig … any也会返回预期的答案,因此 OpenStack 似乎仅拦截特定的PTR

删除主机 IP 后,/etc/hosts通过 NSS (Linux 名称服务切换) 执行查询也会返回来自 OpenStack 的答案:

# getent hosts 10.201.2.214
10.201.2.214    dc0.a.customers.regiocloud.tech

答案1

OVN 有一个流程将发往 UDP/53 的流量重定向到其内部 DNS 解析器,但是它不支持 EDNS。

我们在 5 月份向规范支持部门报告了此问题,他们在上游对其进行了修复:https://github.com/ovn-org/ovn/commit/4b10571aa89b226c13a8c5551ceb7208d782b580

就我的情况来说,当我告诉 dig 禁用 edns 或使用 tcp (+noedns, +tcp) 时,它就可以工作了

相关内容