0

I have several virtual machines with Debian/GNU Linux running on OpenStack. When resolving their internal IPv4 addresses I get some strange results:

# 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

Notice several things:

  1. dig does not print the answer, but the EDNS OPT PSEUDISECTION.
  2. Instead there are some strange warnings:

Warning: Message parser reports malformed message packet.

and

WARNING: Message has 70 extra bytes at end

Alternative Python DNS

If I use python3 to do the DNS query, I get an answer:

# 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.

This is expected as I'm using the DNS server supplied by OpenStack via DHCP here.

But even when I change the name-server to use any other server (like Quad9, Google8, random 1.2.3.4, …), I still get the same answer:

# 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.

So OpenStack seems to do some DNS man-in-the-middle intercept.

Wireshark

For another VM with a different IPv4 I captured the original trace done with dig using 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]

Notice here the Answer RRs: 1, which explains dig complaining about the additional data: Only the EDNS OPT records is accounted for, not the 2nd answer. After patching the captured packet file to have Answer RRs: 2 I see the 2nd answer record in wireshark, which then contains the missing PTR record dig did not print:

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

Questions

  1. How can I prevent OpenStack from intercepting the DNS PTR query and answering it itself, it should go to the DNS server configured in /etc/resolv.conf.
  2. The answer from OpenStack seems to confuse dig but not Pythons dns. What needs to be re-configured to also make dig work?

Additional tries

I already read OpenStack: DNS integration, but found nothing actionable. (I'm not an OpenStack expert and the environment is not managed by me)

If I use dig +tcp to force using TCP instead of UDP, the query does not get intercepted and is answered by the real DNS server.

Doing a dig … any also returns the expected answer, so OpenStack seems to intercept only the specific for PTR only.

After removing the hosts IP from /etc/hosts doing a query via NSS (Linux Name Service Switch) also returns the answer from OpenStack:

# getent hosts 10.201.2.214
10.201.2.214    dc0.a.customers.regiocloud.tech
pmhahn
  • 106
  • 7

1 Answers1

0

OVN has a flow which redirects traffic destinated to UDP/53 to it's internal DNS resolver, however it does not support EDNS.

We reported this issue to canonical support in May and they fixed it upstream: https://github.com/ovn-org/ovn/commit/4b10571aa89b226c13a8c5551ceb7208d782b580

In my case it works when i tell dig to disable edns or use tcp (+noedns, +tcp)