Loop - Alias Loops

Loop - Alias Loops

This module implements alias loops in DNS using variety of different record (resource) types. It supports the following record types:

  • CNAME (Canonical Name)
  • DNAME (Delegation Name)
  • HTTPS (HyperText Transfer Protocol Secure)
  • SVCB (Service Binding)
  • SPF (Sender Policy Framework)
  • SRV (Service Locator)
  • MX (Mail Exchange)
  • NS (Name Server)

The loops can be a direct loop, where the alias points back to the same domain name as in the original query, or they can include multiple elements, cycling through a specified number of domains.

The idea is that if the client/resolver decides to resolve the response further, it will enter an infinite loop. In practice, however, most modern resolvers detect such loops and terminate the resolution.

BEWAREThis can potentially lead to a domain lock-up (DoS).

Category: Alias loops

Tags: Domain Lock-Up, Denial of Service

RFCs: RFC1034, RFC1035, RFC2672, RFC2782, RFC2915, RFC3761, RFC4408, RFC6672, RFC7208, RFC9460

Format

loop.<NUMBER>.yourdomain.com

Where:

  • The <NUMBER> parameter specifies the number of elements the loop should contain.

Examples

By default, the module generates a direct CNAME alias loop:

# dig loop.yourdomain.com @127.0.0.1

; <<>> DiG 9.18.10-2-Debian <<>> loop.yourdomain.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41495
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;loop.yourdomain.com.		IN	A

;; ANSWER SECTION:
loop.yourdomain.com.	60	IN	CNAME	loop.yourdomain.com.

;; Query time: 3 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Thu Nov 07 10:53:17 +04 2024
;; MSG SIZE  rcvd: 70

Download PCAP File

We can see that the CNAME alias points to the same domain name, effectively forming a direct loop.


Like other features, you can append anything to the feature name to avoid receiving cached responses from the target DNS resolver. This forces the target resolver to actively communicate with our PolarDNS server instead of responding with cached answers. Using a random number is the most effective strategy:

# dig loop${RANDOM}.yourdomain.com @10.211.55.2

; <<>> DiG 9.18.10-2-Debian <<>> loop1079.yourdomain.com @10.211.55.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36755
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;loop1079.yourdomain.com.	IN	A

;; ANSWER SECTION:
loop1079.yourdomain.com. 60	IN	CNAME	loop1079.yourdomain.com.

;; Query time: 7 msec
;; SERVER: 10.211.55.2#53(10.211.55.2) (UDP)
;; WHEN: Thu Nov 07 10:53:18 +04 2024
;; MSG SIZE  rcvd: 78

Download PCAP File


In this example, we request a MX alias loop consisting of 5 elements:

# dig MX loop.5.yourdomain.com @127.0.0.1

; <<>> DiG 9.18.10-2-Debian <<>> MX loop.5.yourdomain.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44830
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;loop.5.yourdomain.com.		IN	MX

;; ANSWER SECTION:
loop.5.yourdomain.com.	60	IN	MX	0 loop.5.1.yourdomain.com.

;; Query time: 24 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Thu Nov 07 11:31:45 +04 2024
;; MSG SIZE  rcvd: 78

Download PCAP File

The resulting domain name loop.5.1.yourdomain.com represents the 1st element of the loop.


By resolving the 1st element, we are pointed to the 2nd element of the loop:

# dig MX loop.5.1.yourdomain.com @127.0.0.1

; <<>> DiG 9.18.10-2-Debian <<>> MX loop.5.1.yourdomain.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31031
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;loop.5.1.yourdomain.com.	IN	MX

;; ANSWER SECTION:
loop.5.1.yourdomain.com. 60	IN	MX	0 loop.5.2.yourdomain.com.

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Thu Nov 07 11:31:46 +04 2024
;; MSG SIZE  rcvd: 80

Download PCAP File

This continues up to the 5th and final element — loop.5.5.yourdomain.com.


By resolving the final element of the loop, we are directed back to the 1st element again:

# dig MX loop.5.5.yourdomain.com @127.0.0.1

; <<>> DiG 9.18.10-2-Debian <<>> MX loop.5.5.yourdomain.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63220
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;loop.5.5.yourdomain.com.	IN	MX

;; ANSWER SECTION:
loop.5.5.yourdomain.com. 60	IN	MX	0 loop.5.1.yourdomain.com.

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Thu Nov 07 11:31:47 +04 2024
;; MSG SIZE  rcvd: 80

Download PCAP File

We can see that we are indeed pointed back to the 1st element again, forming a loop.


In this example, we request an SPF alias loop consisting of 10 elements. Since SPF records are published within TXT records in DNS, we request a TXT record in this case:

# dig TXT loop.10.yourdomain.com @127.0.0.1

; <<>> DiG 9.18.10-2-Debian <<>> TXT loop.10.yourdomain.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13350
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;loop.10.yourdomain.com.		IN	TXT

;; ANSWER SECTION:
loop.10.yourdomain.com.	60	IN	TXT	"v=spf1 include:loop.10.1.yourdomain.com ~all"

;; Query time: 8 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Thu Nov 07 11:35:51 +04 2024
;; MSG SIZE  rcvd: 97

Download PCAP File

The resulting domain name loop.10.1.yourdomain.com represents the 1st element of the loop.


By resolving the 1st element, we are pointed to the 2nd element of the loop:

# dig TXT loop.10.1.yourdomain.com @127.0.0.1

; <<>> DiG 9.18.10-2-Debian <<>> TXT loop.10.1.yourdomain.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42805
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;loop.10.1.yourdomain.com.	IN	TXT

;; ANSWER SECTION:
loop.10.1.yourdomain.com. 60	IN	TXT	"v=spf1 include:loop.10.2.yourdomain.com ~all"

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Thu Nov 07 11:35:52 +04 2024
;; MSG SIZE  rcvd: 99

Download PCAP File

This continues up to the 10th and final element — loop.10.10.yourdomain.com.


By resolving the final element of the loop, we are directed back to the 1st element again:

# dig TXT loop.10.10.yourdomain.com @127.0.0.1

; <<>> DiG 9.18.10-2-Debian <<>> TXT loop.10.10.yourdomain.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43528
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;loop.10.10.yourdomain.com.	IN	TXT

;; ANSWER SECTION:
loop.10.10.yourdomain.com. 60	IN	TXT	"v=spf1 include:loop.10.1.yourdomain.com ~all"

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Thu Nov 07 11:35:54 +04 2024
;; MSG SIZE  rcvd: 100

Download PCAP File

We can see that we are indeed pointed back to the 1st element again, forming a loop.


From the same category

See also


Go back to catalogue.