Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Corner case where offset is equal to len(msg), response is truncated without TC bit set and no error is raised #1492

Open
SriHarsha001 opened this issue Oct 30, 2023 · 1 comment

Comments

@SriHarsha001
Copy link

SriHarsha001 commented Oct 30, 2023

If there is a misbehaving upstream server which does not set TC bit and sends back a response length greater than pc.c.UDPSize or 512 default size, then there is a corner case where offset is equal to len(msg) as calculated in unpackHeader defined here github.com/miekg/msg_helpers.go. In this case, there is no Overflow/ErrBuff error returned, so the response will be truncated without TC bit set.

For example -

  • When domain name has 15 characters, offset after unpackQuestion will be 32.
  • Each loop adds 30 to offset and when number of A records in response is more than 15, then offset calculated in unpackRRslice will keep increasing in this sequence 62,92,122,152,182.....482,512
  • In 16th loop, offset (32 question bytes + 30 * 16) == 512 which will be == len(msg) for default UDPsize, so in this case, there is no Overflow error returned.
  • And the response will be truncated (ie response does not contain all the A records) and TC flag is false. This is a failure scenario.

Similarly,

  • When domain name has 19 characters, offset after unpackQuestion will be 36.
  • Each loop adds 34 to offset and when number of A records in response is more than 14, then offset calculated in unpackRRslice will keep increasing in this sequence 70,104,138,.....512
  • In 14th loop, offset (36 question bytes + 34 * 14) == 512 which will be == len(msg) for default UDPsize, so in this case, there is no Overflow error returned.
  • And the response will be truncated (ie response does not contain all the A records) and TC flag is false. This is a failure scenario.
As we can see, response is truncated and TC bit is false.
~----------------------------------------------------------------------------
kubectl exec dnsutils -- dig corednse2e.com +ignore +noedns +search +noshowsearch +time=10 +tries=6 @10.96.0.10
; <<>> DiG 9.9.5-9+deb8u19-Debian <<>> corednse2e.com +ignore +noedns +search +noshowsearch +time=10 +tries=6 @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35567
;; flags: qr rd ra; QUERY: 1, ANSWER: 30, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;corednse2e.com. IN A

;; ANSWER SECTION:
corednse2e.com. 30 IN A 10.96.0.55
corednse2e.com. 30 IN A 10.96.0.51
corednse2e.com. 30 IN A 10.96.0.246
corednse2e.com. 30 IN A 10.96.0.93
corednse2e.com. 30 IN A 10.96.0.54
corednse2e.com. 30 IN A 10.96.0.97
corednse2e.com. 30 IN A 76.223.105.230
corednse2e.com. 30 IN A 10.96.0.98
corednse2e.com. 30 IN A 10.96.0.242
corednse2e.com. 30 IN A 10.96.0.50
corednse2e.com. 30 IN A 10.96.0.91
corednse2e.com. 30 IN A 10.96.0.96
corednse2e.com. 30 IN A 10.96.0.250
corednse2e.com. 30 IN A 10.96.0.252
corednse2e.com. 30 IN A 10.96.0.99
corednse2e.com. 30 IN A 10.96.0.248
corednse2e.com. 30 IN A 13.248.243.5
corednse2e.com. 30 IN A 10.96.0.254
corednse2e.com. 30 IN A 10.96.0.92
corednse2e.com. 30 IN A 10.96.0.249
corednse2e.com. 30 IN A 10.96.0.52
corednse2e.com. 30 IN A 10.96.0.251
corednse2e.com. 30 IN A 10.96.0.244
corednse2e.com. 30 IN A 10.96.0.53
corednse2e.com. 30 IN A 10.96.0.243
corednse2e.com. 30 IN A 10.96.0.247
corednse2e.com. 30 IN A 10.96.0.253
corednse2e.com. 30 IN A 10.96.0.255
corednse2e.com. 30 IN A 10.96.0.95
corednse2e.com. 30 IN A 10.96.0.94

;; Query time: 37 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Thu Oct 26 05:31:44 UTC 2023
;; MSG SIZE rcvd: 512

Whereas full response should have 64 records.
~----------------------------------------------------------------------------
kubectl exec dnsutils -- dig corednse2e.com +ignore +noedns +search +noshowsearch +time=10 +tries=6 @168.63.129.16
; <<>> DiG 9.9.5-9+deb8u19-Debian <<>> corednse2e.com +ignore +noedns +search +noshowsearch +time=10 +tries=6 @168.63.129.16
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59586
;; flags: qr rd ra; QUERY: 1, ANSWER: 64, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;corednse2e.com. IN A

;; ANSWER SECTION:
corednse2e.com. 600 IN A 76.223.105.230
corednse2e.com. 600 IN A 13.248.243.5
corednse2e.com. 600 IN A 10.96.0.91
corednse2e.com. 600 IN A 10.96.0.92
corednse2e.com. 600 IN A 10.96.0.93
corednse2e.com. 600 IN A 10.96.0.94
corednse2e.com. 600 IN A 10.96.0.95
corednse2e.com. 600 IN A 10.96.0.96
corednse2e.com. 600 IN A 10.96.0.97
corednse2e.com. 600 IN A 10.96.0.98
corednse2e.com. 600 IN A 10.96.0.242
corednse2e.com. 600 IN A 10.96.0.243
corednse2e.com. 600 IN A 10.96.0.99
corednse2e.com. 600 IN A 10.96.0.244
corednse2e.com. 600 IN A 10.96.0.246
corednse2e.com. 600 IN A 10.96.0.247
corednse2e.com. 600 IN A 10.96.0.248
corednse2e.com. 600 IN A 10.96.0.249
corednse2e.com. 600 IN A 10.96.0.250
corednse2e.com. 600 IN A 10.96.0.251
corednse2e.com. 600 IN A 10.96.0.252
corednse2e.com. 600 IN A 10.96.0.253
corednse2e.com. 600 IN A 10.96.0.254
corednse2e.com. 600 IN A 10.96.0.255
corednse2e.com. 600 IN A 10.96.0.50
corednse2e.com. 600 IN A 10.96.0.51
corednse2e.com. 600 IN A 10.96.0.52
corednse2e.com. 600 IN A 10.96.0.53
corednse2e.com. 600 IN A 10.96.0.54
corednse2e.com. 600 IN A 10.96.0.55
corednse2e.com. 600 IN A 10.96.0.57
corednse2e.com. 600 IN A 10.96.0.58
corednse2e.com. 600 IN A 10.96.0.59
corednse2e.com. 600 IN A 10.96.0.60
corednse2e.com. 600 IN A 10.96.0.61
corednse2e.com. 600 IN A 10.96.0.62
corednse2e.com. 600 IN A 10.96.0.63
corednse2e.com. 600 IN A 10.96.0.64
corednse2e.com. 600 IN A 10.96.0.65
corednse2e.com. 600 IN A 10.96.0.66
corednse2e.com. 600 IN A 10.96.0.67
corednse2e.com. 600 IN A 10.96.0.68
corednse2e.com. 600 IN A 10.96.0.69
corednse2e.com. 600 IN A 10.96.0.70
corednse2e.com. 600 IN A 10.96.0.71
corednse2e.com. 600 IN A 10.96.0.72
corednse2e.com. 600 IN A 10.96.0.73
corednse2e.com. 600 IN A 10.96.0.74
corednse2e.com. 600 IN A 10.96.0.75
corednse2e.com. 600 IN A 10.96.0.76
corednse2e.com. 600 IN A 10.96.0.77
corednse2e.com. 600 IN A 10.96.0.78
corednse2e.com. 600 IN A 10.96.0.79
corednse2e.com. 600 IN A 10.96.0.80
corednse2e.com. 600 IN A 10.96.0.81
corednse2e.com. 600 IN A 10.96.0.82
corednse2e.com. 600 IN A 10.96.0.83
corednse2e.com. 600 IN A 10.96.0.84
corednse2e.com. 600 IN A 10.96.0.85
corednse2e.com. 600 IN A 10.96.0.86
corednse2e.com. 600 IN A 10.96.0.87
corednse2e.com. 600 IN A 10.96.0.88
corednse2e.com. 600 IN A 10.96.0.89
corednse2e.com. 600 IN A 10.96.0.90

;; Query time: 38 msec
;; SERVER: 168.63.129.16#53(168.63.129.16)
;; WHEN: Thu Oct 26 05:32:22 UTC 2023
;; MSG SIZE rcvd: 1056

With the proposed fix, below is the expected response.
~----------------------------------------------------------------------------
kubectl exec dnsutils -- dig corednse2e.com +ignore +noedns +search +noshowsearch +time=10 +tries=6 @10.96.0.10
; <<>> DiG 9.9.5-9+deb8u19-Debian <<>> corednse2e.com +ignore +noedns +search +noshowsearch +time=10 +tries=6 @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49592
;; flags: qr tc rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;corednse2e.com. IN A

;; Query time: 82 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Thu Oct 26 05:35:25 UTC 2023
;; MSG SIZE rcvd: 32
@descensus
Copy link

descensus commented Nov 30, 2023

Hmm dont think this is a corner case.
I have many domains that have lots of subdomains so all are 15+ chars long.
Out of 700+ records per zone, my AXFR gets about 462 records.

This works flawless using dig axfr against the same DNS.
The DNS is nsd.

Edit: found what was wrong, my range loop receiving from the axfr channel didnt account for that it will restart the range loop after record 470 and then contine on record 471 to the end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants