I got a tip about a trick to check for poisoned DNS responses by the GFW. The GFW injector always responds with a single A record, even when the query is for a different record type, like TXT or AAAA.
Because of the bidirectional nature of the GFW’s DNS injection, you can test this even from outside the firewall. Just send a DNS query for a blocked name to some IP address inside of China, and you will get an injected response.
Example non-poisoned domain (example.com). Note status: REFUSED
and ANSWER: 0
.
$ dig -t TXT @dns2.edu.cn example.com
; <<>> DiG 9.11.5-P4-5.1-Debian <<>> -t TXT @dns2.edu.cn example.com
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 22796
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.com. IN TXT
;; Query time: 241 msec
;; SERVER: 2001:da8:1:100::13#53(2001:da8:1:100::13)
;; WHEN: Wed May 06 19:59:30 MDT 2020
;; MSG SIZE rcvd: 40
Example poisoned domain (torproject.org). Note status: NOERROR
, ANSWER: 1
, and A 4.36.66.178
even though we asked for TXT
.
$ dig -t TXT @dns2.edu.cn torproject.org
; <<>> DiG 9.11.5-P4-5.1-Debian <<>> -t TXT @dns2.edu.cn torproject.org
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37395
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;torproject.org. IN TXT
;; ANSWER SECTION:
torproject.org. 253 IN A 4.36.66.178
;; Query time: 231 msec
;; SERVER: 2001:da8:1:100::13#53(2001:da8:1:100::13)
;; WHEN: Wed May 06 20:02:21 MDT 2020
;; MSG SIZE rcvd: 48