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:
dig
does not print the answer, but the EDNS OPT PSEUDISECTION
.
- 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
- 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
.
- 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