Skip to content

Commit

Permalink
New release update
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-jedek committed Jul 8, 2024
1 parent 72c9d51 commit b11f985
Show file tree
Hide file tree
Showing 65 changed files with 779 additions and 268 deletions.
18 changes: 18 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
08/Jul/2024
- release version 1.4
- added the `cut` modifier for cutting arbitrary number of bytes from the end of the packet
- deprecated the `cutabuf` and `cutcnamebuf` features
- added tests (total test count: 678)

05/Jul/2024
- added the `size` feature that responds with the maximum number of A records that can fit in the specified packet size
- added support for DNS compression, configurable via config file
- added the `nc` modifier to not use compression in a response
- added the `fc` modifier to force compression in a response
- added tests (total test count: 669)
- various code optimizations

04/Jul/2024
- optimization in the startup routine to remove all debug messages if debug mode is disabled
- added support for parsing the EDNS0 section, configurable via config file

03/Jul/2024
- added support for the Attrleaf naming pattern (underscored domain names) for the SRV and SVCB alias/chain/loop features
- enhanced the `nfz` modifier, added 4 more variants, now it can produce 49 different domain name variants
Expand Down
70 changes: 66 additions & 4 deletions docs/catalogue/general-features.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# PolarDNS catalogue - General features
1. [General features](general-features.md)
- [Always resolve to IP (always)](#always-resolve-to-ip-always)
- [Client IP address (self / whatismyip)](#client-ip-address-self--whatismyip)
- [Max A records within size limit (size)](#max-a-records-within-size-limit-size)
- [What is my IP address (self / whatismyip)](#what-is-my-ip-address-self--whatismyip)
- [Chunked CNAME aliases (chunkedcnames)](#chunked-cname-aliases-chunkedcnames)
- [Cut A record from the end (cutabuf)](#cut-a-record-from-the-end-cutabuf)
- [Cut CNAME record from the end (cutcnamebuf)](#cut-cname-record-from-the-end-cutcnamebuf)
Expand Down Expand Up @@ -51,7 +52,68 @@ always.yourdomain.com. 60 IN A 2.3.4.5
;; MSG SIZE rcvd: 76
```
### Client IP address (self / whatismyip)
### Max A records within size limit (size)
Respond with as many A records as we can possibly fit within the specified packet size limit. By default 512 bytes.

<table>
<tr><td>format:</td><td>size.&lt;BYTES>.yourdomain.com</td></tr>
<tr><td>example:</td><td><code>dig size.yourdomain.com @127.0.0.1</code></td></tr>
<tr><td>example:</td><td><code>dig size.100.yourdomain.com @127.0.0.1</code></td></tr>
<tr><td>example:</td><td><code>dig size.1000.yourdomain.com @127.0.0.1</code></td></tr>
<tr><td>example:</td><td><code>dig size.512.yourdomain.com @127.0.0.1</code></td></tr>
</table>

Sample:
```
# dig size.512.yourdomain.com @127.0.0.1
; <<>> DiG 9.18.10-2-Debian <<>> size.512.yourdomain.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42906
;; flags: qr aa; QUERY: 1, ANSWER: 29, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;size.512.yourdomain.com. IN A
;; ANSWER SECTION:
size.512.yourdomain.com. 60 IN A 127.0.0.197
size.512.yourdomain.com. 60 IN A 127.0.0.179
size.512.yourdomain.com. 60 IN A 127.0.0.174
size.512.yourdomain.com. 60 IN A 127.0.0.66
size.512.yourdomain.com. 60 IN A 127.0.0.146
size.512.yourdomain.com. 60 IN A 127.0.0.70
size.512.yourdomain.com. 60 IN A 127.0.0.245
size.512.yourdomain.com. 60 IN A 127.0.0.195
size.512.yourdomain.com. 60 IN A 127.0.0.82
size.512.yourdomain.com. 60 IN A 127.0.0.211
size.512.yourdomain.com. 60 IN A 127.0.0.195
size.512.yourdomain.com. 60 IN A 127.0.0.150
size.512.yourdomain.com. 60 IN A 127.0.0.171
size.512.yourdomain.com. 60 IN A 127.0.0.129
size.512.yourdomain.com. 60 IN A 127.0.0.214
size.512.yourdomain.com. 60 IN A 127.0.0.31
size.512.yourdomain.com. 60 IN A 127.0.0.3
size.512.yourdomain.com. 60 IN A 127.0.0.251
size.512.yourdomain.com. 60 IN A 127.0.0.64
size.512.yourdomain.com. 60 IN A 127.0.0.93
size.512.yourdomain.com. 60 IN A 127.0.0.96
size.512.yourdomain.com. 60 IN A 127.0.0.125
size.512.yourdomain.com. 60 IN A 127.0.0.51
size.512.yourdomain.com. 60 IN A 127.0.0.14
size.512.yourdomain.com. 60 IN A 127.0.0.81
size.512.yourdomain.com. 60 IN A 127.0.0.204
size.512.yourdomain.com. 60 IN A 127.0.0.1
size.512.yourdomain.com. 60 IN A 127.0.0.89
size.512.yourdomain.com. 60 IN A 127.0.0.175
;; Query time: 3 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Sun Jul 07 22:59:53 +04 2024
;; MSG SIZE rcvd: 505
```
### What is my IP address (self / whatismyip)
Respond with A and TXT records containing the IP address of the connecting client. The TXT record also contains the port information.

<table>
Expand Down Expand Up @@ -130,7 +192,7 @@ chunkedcnames.12.slp150.yourdomain.com. 60 IN CNAME always63975.yourdomain.com.
```
### Cut A record from the end (cutabuf)
Respond with legit A record, but cut arbitrary number of bytes from the end of the buffer.
:exclamation:**DEPRECATED**:exclamation: Use the generic [cut](response-modifiers.md#cut-n-bytes-from-the-end-of-the-packet-cut) response modifier to cut any response.Respond with legit A record, but cut arbitrary number of bytes from the end of the buffer.

<table>
<tr><td>format:</td><td>cutabuf.&lt;BYTES-TO-CUT>.yourdomain.com</td></tr>
Expand Down Expand Up @@ -159,7 +221,7 @@ Sample:
```
### Cut CNAME record from the end (cutcnamebuf)
Respond with legit CNAME record, but cut arbitrary number of bytes from the end of the buffer.
:exclamation:**DEPRECATED**:exclamation: Use the generic [cut](response-modifiers.md#cut-n-bytes-from-the-end-of-the-packet-cut) response modifier to cut any response.Respond with legit CNAME record, but cut arbitrary number of bytes from the end of the buffer.

<table>
<tr><td>format:</td><td>cutcnamebuf.&lt;BYTES-TO-CUT>.yourdomain.com</td></tr>
Expand Down
124 changes: 124 additions & 0 deletions docs/catalogue/response-modifiers.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
- [Set answer RRs in the header (anrr)](#set-answer-rrs-in-the-header-anrr)
- [Set authority RRs in the header (aurr)](#set-authority-rrs-in-the-header-aurr)
- [Set additional RRs in the header (adrr)](#set-additional-rrs-in-the-header-adrr)
- [Cut N bytes from the end of the packet (cut)](#cut-n-bytes-from-the-end-of-the-packet-cut)
- [Force compression (fc)](#force-compression-fc)
- [No compression (nc)](#no-compression-nc)
- [Name fuzzing generator (nfz)](#name-fuzzing-generator-nfz)
1. [CNAME fuzzing](cname-fuzzing.md)
1. [Bad compression](bad-compression.md)
Expand Down Expand Up @@ -347,6 +350,124 @@ always.adrr50.yourdomain.com. 60 IN A 2.3.4.5
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Thu Nov 02 16:37:51 +04 2023
;; MSG SIZE rcvd: 90
```
### Cut N bytes from the end of the packet (cut)
Cut arbitrary number of bytes from the end of the packet.

<table>
<tr><td>format:</td><td>anything.cut&lt;NUMBER>.yourdomain.com</td></tr>
<tr><td>example:</td><td><code>dig always.cut00.yourdomain.com @127.0.0.1</code></td></tr>
<tr><td>example:</td><td><code>dig always.cut10.yourdomain.com @127.0.0.1</code></td></tr>
<tr><td>example:</td><td><code>dig size.128.cut00.fc.yourdomain.com @127.0.0.1</code></td></tr>
<tr><td>example:</td><td><code>dig size.128.cut16.fc.yourdomain.com @127.0.0.1</code></td></tr>
</table>

Sample:
```
# dig size.128.cut16.fc.yourdomain.com @127.0.0.1
;; Warning: Message parser reports malformed message packet.
; <<>> DiG 9.18.10-2-Debian <<>> size.128.cut16.fc.yourdomain.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19940
;; flags: qr aa; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;size.128.cut16.fc.yourdomain.com. IN A
;; ANSWER SECTION:
size.128.cut16.fc.yourdomain.com. 60 IN A 127.0.0.236
size.128.cut16.fc.yourdomain.com. 60 IN A 127.0.0.233
size.128.cut16.fc.yourdomain.com. 60 IN A 127.0.0.123
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Mon Jul 08 15:41:00 +04 2024
;; MSG SIZE rcvd: 98
```
### Force compression (fc)
Use DNS compression in the response, overriding any DNS compression settings specified in the configuration file.

<table>
<tr><td>format:</td><td>anything.fc.yourdomain.com</td></tr>
<tr><td>example:</td><td><code>dig always.fc.yourdomain.com @127.0.0.1</code></td></tr>
<tr><td>example:</td><td><code>dig size.300.fc.yourdomain.com @127.0.0.1</code></td></tr>
</table>

Sample:
```
# dig size.300.fc.yourdomain.com @127.0.0.1
; <<>> DiG 9.18.10-2-Debian <<>> size.300.fc.yourdomain.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17029
;; flags: qr aa; QUERY: 1, ANSWER: 16, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;size.300.fc.yourdomain.com. IN A
;; ANSWER SECTION:
size.300.fc.yourdomain.com. 60 IN A 127.0.0.112
size.300.fc.yourdomain.com. 60 IN A 127.0.0.206
size.300.fc.yourdomain.com. 60 IN A 127.0.0.64
size.300.fc.yourdomain.com. 60 IN A 127.0.0.238
size.300.fc.yourdomain.com. 60 IN A 127.0.0.100
size.300.fc.yourdomain.com. 60 IN A 127.0.0.121
size.300.fc.yourdomain.com. 60 IN A 127.0.0.72
size.300.fc.yourdomain.com. 60 IN A 127.0.0.164
size.300.fc.yourdomain.com. 60 IN A 127.0.0.79
size.300.fc.yourdomain.com. 60 IN A 127.0.0.85
size.300.fc.yourdomain.com. 60 IN A 127.0.0.243
size.300.fc.yourdomain.com. 60 IN A 127.0.0.97
size.300.fc.yourdomain.com. 60 IN A 127.0.0.16
size.300.fc.yourdomain.com. 60 IN A 127.0.0.119
size.300.fc.yourdomain.com. 60 IN A 127.0.0.215
size.300.fc.yourdomain.com. 60 IN A 127.0.0.178
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Sun Jul 07 22:59:53 +04 2024
;; MSG SIZE rcvd: 300
```
### No compression (nc)
Do not use DNS compression in the response, overriding any DNS compression settings specified in the configuration file.

<table>
<tr><td>format:</td><td>anything.nc.yourdomain.com</td></tr>
<tr><td>example:</td><td><code>dig always.nc.yourdomain.com @127.0.0.1</code></td></tr>
<tr><td>example:</td><td><code>dig size.300.nc.yourdomain.com @127.0.0.1</code></td></tr>
</table>

Sample:
```
# dig size.300.nc.yourdomain.com @127.0.0.1
; <<>> DiG 9.18.10-2-Debian <<>> size.300.nc.yourdomain.com @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20422
;; flags: qr aa; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;size.300.nc.yourdomain.com. IN A
;; ANSWER SECTION:
size.300.nc.yourdomain.com. 60 IN A 127.0.0.1
size.300.nc.yourdomain.com. 60 IN A 127.0.0.130
size.300.nc.yourdomain.com. 60 IN A 127.0.0.148
size.300.nc.yourdomain.com. 60 IN A 127.0.0.83
size.300.nc.yourdomain.com. 60 IN A 127.0.0.75
size.300.nc.yourdomain.com. 60 IN A 127.0.0.224
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Sun Jul 07 23:05:03 +04 2024
;; MSG SIZE rcvd: 296
```
### Name fuzzing generator (nfz)
Generate various illegal and malformed domain names based on the selected variant and size. This generator was primarily created for alias features (such as alias, cnalias, dnalias, etc.) to provide a unified mechanism for generating malformed domain names.
Expand All @@ -366,6 +487,7 @@ Generate various illegal and malformed domain names based on the selected varian

Samples:
```
-------------------------------------------------------------------------------------------
# dig MX alias.10.nfz0.10.yourdomain.com @127.0.0.1
; <<>> DiG 9.18.10-2-Debian <<>> MX alias.10.nfz0.10.yourdomain.com @127.0.0.1
Expand Down Expand Up @@ -1814,7 +1936,9 @@ alias.10.nfz49.10.yourdomain.com. 60 IN MX 0 127.0.0.1:80.
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Thu Jul 04 00:22:42 +04 2024
;; MSG SIZE rcvd: 650
```

##
Go back to [menu](#polardns-catalogue---response-modifiers).

12 changes: 6 additions & 6 deletions modules/afuzz2.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ category = "General features"
code = '''
if req.first_subdomain.startswith("afuzz2"):
# Send many A records with a slightly distorted name. In the end, provide the correct one also
# af<01>zz2.dnslabtest1.com A 6.6.6.1
# af<02>zz2.dnslabtest1.com A 6.6.6.2
# af<03>zz2.dnslabtest1.com A 6.6.6.3
# af<01>zz2.yourdomain.com A 6.6.6.1
# af<02>zz2.yourdomain.com A 6.6.6.2
# af<03>zz2.yourdomain.com A 6.6.6.3
# ...
# af<fe>zz2.dnslabtest1.com A 6.6.6.254
# af<ff>zz2.dnslabtest1.com A 6.6.6.255
# afuzz2.dnslabtest1.com A 1.2.3.4
# af<fe>zz2.yourdomain.com A 6.6.6.254
# af<ff>zz2.yourdomain.com A 6.6.6.255
# afuzz2.yourdomain.com A 1.2.3.4
answers = 1
if req.subdomains[1].isnumeric():
answers = int(req.subdomains[1])
Expand Down
18 changes: 12 additions & 6 deletions modules/alias.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ code = '''
for i in range(answers):
dom = name_fuzz(resp.nfz) if hasattr(resp, "nfz") else random_chain(req.full_domain)
bindom = convDom2Bin(dom)
buffer += convDom2Bin(req.full_domain) + getTypeBin("DNAME") + getClassBin("IN")
buffer += b'\xc0\x0c' if resp.compress else convDom2Bin(req.full_domain)
buffer += getTypeBin("DNAME") + getClassBin("IN")
buffer += struct.pack(">L", resp.TTL) ## TTL
buffer += struct.pack(">H", len(bindom)) ## Data length
buffer += bindom ## DNAME value
Expand All @@ -34,7 +35,8 @@ code = '''
dom = name_fuzz(resp.nfz) if hasattr(resp, "nfz") else random_chain(req.full_domain)
bindom = convDom2Bin(dom)
data_len = 2+len(bindom) # SvcPriority (2 bytes) + the target name
buffer += convDom2Bin(req.full_domain) + getTypeBin("HTTPS") + getClassBin("IN")
buffer += b'\xc0\x0c' if resp.compress else convDom2Bin(req.full_domain)
buffer += getTypeBin("HTTPS") + getClassBin("IN")
buffer += struct.pack(">L", resp.TTL) ## TTL
buffer += struct.pack(">H", data_len) ## Data length
buffer += struct.pack(">H", 0) ## SvcPriority (0 means alias mode - RFC 9460)
Expand All @@ -47,7 +49,8 @@ code = '''
bindom = convDom2Bin(dom)
data_len = 2+len(bindom) # SvcPriority (2 bytes) + the target name
data_len = 2+len(bindom) # SvcPriority (2 bytes) + the target name
buffer += convDom2Bin(req.full_domain) + getTypeBin("SVCB") + getClassBin("IN")
buffer += b'\xc0\x0c' if resp.compress else convDom2Bin(req.full_domain)
buffer += getTypeBin("SVCB") + getClassBin("IN")
buffer += struct.pack(">L", resp.TTL) ## TTL
buffer += struct.pack(">H", data_len) ## Data length
buffer += struct.pack(">H", 0) ## SvcPriority (0 means alias mode - RFC 9460)
Expand All @@ -61,7 +64,8 @@ code = '''
data_len = 2+len(bindom) # SvcPriority (2 bytes) + the target name
port = random.getrandbits(16)
data_len = 2+2+2+len(bindom) # Priority (2 bytes) + Weight (2 bytes) + Port (2 bytes) + Target domain
buffer += convDom2Bin(req.full_domain) + getTypeBin("SRV") + getClassBin("IN")
buffer += b'\xc0\x0c' if resp.compress else convDom2Bin(req.full_domain)
buffer += getTypeBin("SRV") + getClassBin("IN")
buffer += struct.pack(">L", resp.TTL) ## TTL
buffer += struct.pack(">H", data_len) ## Data length
buffer += struct.pack(">H", 0) ## Priority
Expand All @@ -76,7 +80,8 @@ code = '''
bindom = convDom2Bin(dom)
data_len = 2+len(bindom) # SvcPriority (2 bytes) + the target name
data_len = 2+len(bindom) # Priority (2 bytes) + Target domain
buffer += convDom2Bin(req.full_domain) + getTypeBin("MX") + getClassBin("IN")
buffer += b'\xc0\x0c' if resp.compress else convDom2Bin(req.full_domain)
buffer += getTypeBin("MX") + getClassBin("IN")
buffer += struct.pack(">L", resp.TTL) ## TTL
buffer += struct.pack(">H", data_len) ## Data length
buffer += struct.pack(">H", 0) ## Priority
Expand All @@ -88,7 +93,8 @@ code = '''
dom = name_fuzz(resp.nfz) if hasattr(resp, "nfz") else random_chain(req.full_domain)
bindom = convDom2Bin(dom)
data_len = 2+len(bindom) # SvcPriority (2 bytes) + the target name
buffer += convDom2Bin(req.full_domain) + getTypeBin("CNAME") + getClassBin("IN")
buffer += b'\xc0\x0c' if resp.compress else convDom2Bin(req.full_domain)
buffer += getTypeBin("CNAME") + getClassBin("IN")
buffer += struct.pack(">L", resp.TTL) ## TTL
buffer += struct.pack(">H", len(bindom)) ## Data length
buffer += bindom ## CNAME value
Expand Down
6 changes: 4 additions & 2 deletions modules/badcompresspoc1nn.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ if req.first_subdomain.startswith("badcompresspoc1nn"):
### ANSWER SECTION ########
databin = b"\x0babcdeabcdef"
# TXT ~~~ CNAME points here
buffer += convDom2Bin(req.full_domain) + getTypeBin("TXT") + getClassBin("IN")
buffer += b'\xc0\x0c' if resp.compress else convDom2Bin(req.full_domain)
buffer += getTypeBin("TXT") + getClassBin("IN")
buffer += struct.pack(">L", resp.TTL) ## TTL
buffer += struct.pack(">H", len(databin)) ## Data length
buffer += databin
# CNAME
offset_to_the_txt = (len(req.full_domain)*2) + 18 + 12 ## backward pointer to the previous TXT record
databin = b"\xc0" + struct.pack(">B", offset_to_the_txt)
buffer += convDom2Bin(req.full_domain) + getTypeBin("CNAME") + getClassBin("IN")
buffer += b'\xc0\x0c' if resp.compress else convDom2Bin(req.full_domain)
buffer += getTypeBin("CNAME") + getClassBin("IN")
buffer += struct.pack(">L", resp.TTL) ## TTL
buffer += struct.pack(">H", len(databin)) ## Data length
buffer += databin
Expand Down
6 changes: 4 additions & 2 deletions modules/badcompresspoc1wn.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ if req.first_subdomain.startswith("badcompresspoc1wn"):
### ANSWER SECTION ########
databin = b"\x0babcdeabcde\x00"
# TXT ~~~ CNAME points here
buffer += convDom2Bin(req.full_domain) + getTypeBin("TXT") + getClassBin("IN")
buffer += b'\xc0\x0c' if resp.compress else convDom2Bin(req.full_domain)
buffer += getTypeBin("TXT") + getClassBin("IN")
buffer += struct.pack(">L", resp.TTL) ## TTL
buffer += struct.pack(">H", len(databin)) ## Data length
buffer += databin
# CNAME
offset_to_the_txt = (len(req.full_domain)*2) + 18 + 12 ## backward pointer to the previous TXT record
databin = b"\xc0" + struct.pack(">B", offset_to_the_txt)
buffer += convDom2Bin(req.full_domain) + getTypeBin("CNAME") + getClassBin("IN")
buffer += b'\xc0\x0c' if resp.compress else convDom2Bin(req.full_domain)
buffer += getTypeBin("CNAME") + getClassBin("IN")
buffer += struct.pack(">L", resp.TTL) ## TTL
buffer += struct.pack(">H", len(databin)) ## Data length
buffer += databin
Expand Down
Loading

0 comments on commit b11f985

Please sign in to comment.