Skip to content

Commit 05ec4b3

Browse files
committed
New features and updates
1 parent 002fcae commit 05ec4b3

20 files changed

+280
-77
lines changed

changelog

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
24/Sep/2024
2+
- release version 1.5.0
3+
- adopting the semantic versioning (SemVer)
4+
- added the `nptenumalias` and `nptenumloop` features returning NAPTR records in response to ENUM (E.164) phone number queries
5+
- updated the catalogue documentation
6+
- added tests (total test count: 750)
7+
8+
19/Sep/2024
9+
- send only one alias by default, ensuring uniform behavior across all `alias*` feature (CNAME/DNAME/HTTPS/SVCB/SRV/MX/NS/TXT)
10+
11+
06/Aug/2024
12+
- small fix in matching of underscored domain names for the SRV and SVCB alias/chain/loop features
13+
114
15/Jul/2024
215
- added the `add` modifier for appending arbitrary bytes to the end of the packet
316
- added the `rl` modifier for recalculating the length in TCP in case `cut` or `add` modifiers were used during a request

docs/catalogue/aliases-loops-and-chains.md

Lines changed: 103 additions & 31 deletions
Large diffs are not rendered by default.

modules/alias.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ code = '''
1010
elif req.first_subdomain.startswith("alias"):
1111
# Send multiple random aliases in any of CNAME/DNAME/HTTPS/SVCB/SRV/MX/NS/SPF(TXT) record types
1212
# BEWARE: This could result in multiplication
13-
answers = int(req.subdomains[1]) if req.subdomains[1].isnumeric() else 3
13+
answers = int(req.subdomains[1]) if req.subdomains[1].isnumeric() else 1
1414
### DNS header ########
1515
buffer = prep_dns_header(b'\x84\x00', req.QURR, answers, 0, 0)
1616
### QUESTION SECTION ########

modules/cnalias.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ code = '''
1010
elif req.first_subdomain.startswith("cnalias"):
1111
# Send multiple random CNAME aliases
1212
# BEWARE: This could result in multiplication
13-
answers = int(req.subdomains[1]) if req.subdomains[1].isnumeric() else 3
13+
answers = int(req.subdomains[1]) if req.subdomains[1].isnumeric() else 1
1414
### DNS header ########
1515
buffer = prep_dns_header(b'\x84\x00', req.QURR, answers, 0, 0)
1616
### QUESTION SECTION ########

modules/dnalias.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ code = '''
1010
elif req.first_subdomain.startswith("dnalias"):
1111
# Send multiple random DNAME aliases
1212
# BEWARE: This could result in multiplication
13-
answers = int(req.subdomains[1]) if req.subdomains[1].isnumeric() else 3
13+
answers = int(req.subdomains[1]) if req.subdomains[1].isnumeric() else 1
1414
### DNS header ########
1515
buffer = prep_dns_header(b'\x84\x00', req.QURR, answers, 0, 0)
1616
### QUESTION SECTION ########

modules/htalias.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ code = '''
1010
elif req.first_subdomain.startswith("htalias"):
1111
# Send multiple random HTTPS aliases (RFC 9460).
1212
# BEWARE: This could result in multiplication
13-
answers = int(req.subdomains[1]) if req.subdomains[1].isnumeric() else 3
13+
answers = int(req.subdomains[1]) if req.subdomains[1].isnumeric() else 1
1414
### DNS header ########
1515
buffer = prep_dns_header(b'\x84\x00', req.QURR, answers, 0, 0)
1616
### QUESTION SECTION ########

modules/mxalias.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ code = '''
1010
elif req.first_subdomain.startswith("mxalias"):
1111
# Send multiple random MX aliases
1212
# BEWARE: This could result in multiplication
13-
answers = int(req.subdomains[1]) if req.subdomains[1].isnumeric() else 3
13+
answers = int(req.subdomains[1]) if req.subdomains[1].isnumeric() else 1
1414
### DNS header ########
1515
buffer = prep_dns_header(b'\x84\x00', req.QURR, answers, 0, 0)
1616
### QUESTION SECTION ########

modules/nptenumalias.toml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
[module]
2+
name = "nptenumalias"
3+
type = "feature"
4+
info = "NAPTR ENUM random N aliases"
5+
desc = "Respond with N number of NAPTR ENUM records containing random E.164 phone numbers (aliases) in SIP service URI. BEWARE: This could result in multiplication."
6+
author = "ivan.jedek@oryxlabs.com"
7+
category = "Aliases, loops and chains"
8+
9+
code = '''
10+
elif req.first_subdomain == "1" and req.full_domain.endswith(".e164.arpa"):
11+
# Requesting to translate an E.164 telephone number ending with the digit 1 (e.g., a NAPTR
12+
# record for 1.<anything>.e164.arpa in reverse). The response will be a SIP service URI
13+
# pointing to another random E.164 telephone number also ending with the digit 1 (leading
14+
# here again, producing another alias). While NAPTR ENUM records do not contain aliases
15+
# like CNAME records, this could achieve similar results by prompting the client to
16+
# perform consecutive queries to resolve it.
17+
# BEWARE: This could result in multiplication
18+
19+
answers = int(req.subdomains[1]) if req.subdomains[1].isnumeric() else 1
20+
21+
# figure out the ending part of the domain which is not a number any more
22+
# in order to preserve the parameters if any
23+
for i, part in enumerate(req.subdomains):
24+
if not part.isnumeric():
25+
dom_end = '.' + '.'.join(req.subdomains[i:])
26+
break
27+
else:
28+
dom_end = req.full_domain
29+
30+
### DNS header ########
31+
buffer = prep_dns_header(b'\x84\x00', req.QURR, answers, 0, 0)
32+
### QUESTION SECTION ########
33+
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin
34+
### ANSWER SECTION ########
35+
doms = []
36+
for i in range(answers):
37+
random_number = random.getrandbits(30) % 1000000000
38+
new_dom = '1.' + str(answers) + '.' + '.'.join(str(random_number)) + dom_end
39+
order = 0
40+
pref = 0
41+
flags = b'U' # Flags = "U" (URI)
42+
service = b'E2U+sip' # Service = SIP
43+
regex = bytes("!^.*$!" + new_dom + "!", "utf-8")
44+
replacement = b'\x00'
45+
46+
data_len = 2+2+1+len(flags)+1+len(service)+1+len(regex)+len(replacement)
47+
buffer += b'\xc0\x0c' if resp.compress else convDom2Bin(req.full_domain) ## Name
48+
buffer += getTypeBin("NAPTR") + getClassBin("IN")
49+
buffer += struct.pack(">L", resp.TTL) ## TTL
50+
buffer += struct.pack(">H", data_len) ## Data length (2B)
51+
buffer += struct.pack(">H", order) ## Order (2B)
52+
buffer += struct.pack(">H", pref) ## Preference (2B)
53+
buffer += struct.pack(">B", len(flags)) ## Flags Length (1B)
54+
buffer += flags ## Flags
55+
buffer += struct.pack(">B", len(service)) ## Service Length (1B)
56+
buffer += service ## Service
57+
buffer += struct.pack(">B", len(regex)) ## Regex Length (1B)
58+
buffer += regex ## Regex
59+
buffer += replacement ## Replacement
60+
doms.append(new_dom)
61+
# log and send
62+
log("%d NAPTR ENUM aliases: %s" % (answers, ', '.join(map(str, doms[:3])) + (', ...' if answers > 3 else '')))
63+
send_buf(self, buffer)
64+
#####################################################################
65+
'''

modules/nptenumloop.toml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
[module]
2+
name = "nptenumloop"
3+
type = "feature"
4+
info = "NAPTR ENUM alias loop"
5+
desc = "Respond with N number of NAPTR ENUM records containing random E.164 phone numbers (aliases) in SIP service URI. BEWARE: This could result in multiplication."
6+
author = "ivan.jedek@oryxlabs.com"
7+
category = "Aliases, loops and chains"
8+
9+
code = '''
10+
elif req.first_subdomain == "2" and req.full_domain.endswith(".e164.arpa"):
11+
# Requesting to translate an E.164 telephone number ending with the digit 2 (e.g., a NAPTR
12+
# record for 2.<anything>.e164.arpa in reverse). The response will be a SIP service URI
13+
# pointing to the same exact E.164 telephone number, effectively creating a direct loop.
14+
# While NAPTR ENUM records do not contain aliases like CNAME records, this could achieve
15+
# similar results by prompting the client to perform consecutive queries to resolve it.
16+
# BEWARE: This could potentially lead to a domain lock-up (DoS)
17+
18+
### DNS header ########
19+
buffer = prep_dns_header(b'\x84\x00', req.QURR, 1, 0, 0)
20+
### QUESTION SECTION ########
21+
if resp.noq: buffer += convDom2Bin(req.full_domain) + req.type_bin + req.class_bin
22+
### ANSWER SECTION ########
23+
order = 0
24+
pref = 0
25+
flags = b'U' # Flags = "U" (URI)
26+
service = b'E2U+sip' # Service = SIP
27+
regex = bytes("!^.*$!" + req.full_domain + "!", "utf-8")
28+
replacement = b'\x00'
29+
30+
data_len = 2+2+1+len(flags)+1+len(service)+1+len(regex)+len(replacement)
31+
buffer += b'\xc0\x0c' if resp.compress else convDom2Bin(req.full_domain) ## Name
32+
buffer += getTypeBin("NAPTR") + getClassBin("IN")
33+
buffer += struct.pack(">L", resp.TTL) ## TTL
34+
buffer += struct.pack(">H", data_len) ## Data length (2B)
35+
buffer += struct.pack(">H", order) ## Order (2B)
36+
buffer += struct.pack(">H", pref) ## Preference (2B)
37+
buffer += struct.pack(">B", len(flags)) ## Flags Length (1B)
38+
buffer += flags ## Flags
39+
buffer += struct.pack(">B", len(service)) ## Service Length (1B)
40+
buffer += service ## Service
41+
buffer += struct.pack(">B", len(regex)) ## Regex Length (1B)
42+
buffer += regex ## Regex
43+
buffer += replacement ## Replacement
44+
# log and send
45+
log("NAPTR ENUM loop %s" % (req.full_domain))
46+
send_buf(self, buffer)
47+
#####################################################################
48+
'''

modules/nsalias.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ code = '''
1010
elif req.first_subdomain.startswith("nsalias"):
1111
# Send multiple random NS aliases
1212
# BEWARE: This could result in multiplication
13-
answers = int(req.subdomains[1]) if req.subdomains[1].isnumeric() else 3
13+
answers = int(req.subdomains[1]) if req.subdomains[1].isnumeric() else 1
1414
### DNS header ########
1515
buffer = prep_dns_header(b'\x84\x00', req.QURR, answers, 0, 0)
1616
### QUESTION SECTION ########

0 commit comments

Comments
 (0)