@nictool/dns-resource-record 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/README.md +323 -199
- package/dist/dns-rr.min.js +26 -0
- package/dist/dns-rr.min.js.map +7 -0
- package/index.js +12 -11
- package/lib/binary.js +108 -0
- package/lib/bind.js +94 -0
- package/lib/dns-query.js +67 -0
- package/lib/tinydns.js +128 -44
- package/lib/wire.js +519 -0
- package/package.json +23 -6
- package/rr/TEMPLATE.js +124 -0
- package/rr/a.js +8 -48
- package/rr/aaaa.js +13 -80
- package/rr/apl.js +123 -27
- package/rr/caa.js +27 -50
- package/rr/cert.js +58 -87
- package/rr/cname.js +7 -63
- package/rr/dhcid.js +20 -30
- package/rr/dname.js +9 -36
- package/rr/dnskey.js +38 -32
- package/rr/ds.js +43 -57
- package/rr/hinfo.js +21 -40
- package/rr/hip.js +88 -26
- package/rr/https.js +28 -40
- package/rr/ipseckey.js +97 -18
- package/rr/key.js +39 -29
- package/rr/kx.js +16 -27
- package/rr/loc.js +42 -12
- package/rr/mx.js +16 -51
- package/rr/naptr.js +58 -33
- package/rr/ns.js +8 -36
- package/rr/nsec.js +89 -18
- package/rr/nsec3.js +62 -26
- package/rr/nsec3param.js +56 -53
- package/rr/nxt.js +57 -18
- package/rr/openpgpkey.js +24 -30
- package/rr/ptr.js +7 -47
- package/rr/rp.js +17 -32
- package/rr/rrsig.js +80 -85
- package/rr/sig.js +70 -45
- package/rr/smimea.js +33 -33
- package/rr/soa.js +31 -49
- package/rr/spf.js +10 -17
- package/rr/srv.js +22 -62
- package/rr/sshfp.js +25 -53
- package/rr/svcb.js +27 -40
- package/rr/tlsa.js +34 -34
- package/rr/tsig.js +87 -24
- package/rr/txt.js +40 -59
- package/rr/uri.js +19 -29
- package/rr/wks.js +154 -22
- package/rr.js +290 -109
- package/lib/readme.js +0 -84
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,38 @@ Notable changes to this project are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
#### Unreleased
|
|
6
6
|
|
|
7
|
+
### [1.7.0] - 2026-04-20
|
|
8
|
+
|
|
9
|
+
#### Fixes
|
|
10
|
+
|
|
11
|
+
- rr/txt: chunk by UTF-8 bytes (vs ASCII)
|
|
12
|
+
- rr/rrsig: validate "type covered" correctly
|
|
13
|
+
|
|
14
|
+
#### Changes
|
|
15
|
+
|
|
16
|
+
- RR is strictly a factory now
|
|
17
|
+
- no longer returns a different object based on bindLine or tinyLine
|
|
18
|
+
- doc(CAA, DS): added RFC 9619
|
|
19
|
+
- openpgpkey: reject keys with non-ASCII
|
|
20
|
+
- tinydns: name any out-of-range chars in error msg
|
|
21
|
+
- fromBind: use a tokenizing parser (vs regexes)
|
|
22
|
+
|
|
23
|
+
#### Additions
|
|
24
|
+
|
|
25
|
+
- add rr/TEMPLATE.js with lots of docs
|
|
26
|
+
- declarative rdataFields to remove lots of boilerplate from rr/all
|
|
27
|
+
- browser compat enhancements
|
|
28
|
+
- rollup dns-rr.min.js + min.js.map
|
|
29
|
+
- add `static typeName` as constructor.name doesn't survive minification
|
|
30
|
+
- feat(lib/binary): add shared binary functions
|
|
31
|
+
- change: replace `Buffer` with Uint8Array, DataView, and math
|
|
32
|
+
- feat(lib/wire): add wire format helpers
|
|
33
|
+
- feat(fromWire): added wire format parsers
|
|
34
|
+
- used to round-trip DNS and validate parsing & formatting
|
|
35
|
+
- feat(fromBind): use a parser (vs regexes)
|
|
36
|
+
- test: add dnsLiveTests, test `toWire()` against live NSD & tinydns
|
|
37
|
+
- uncovered edge cases in round trips between formats
|
|
38
|
+
|
|
7
39
|
### [1.6.1] - 2026-04-20
|
|
8
40
|
|
|
9
41
|
- doc(README): add wire export format
|
|
@@ -385,3 +417,4 @@ Notable changes to this project are documented in this file.
|
|
|
385
417
|
[1.5.0]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.5.0
|
|
386
418
|
[1.6.0]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.6.0
|
|
387
419
|
[1.6.1]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.6.1
|
|
420
|
+
[1.7.0]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.7.0
|
package/README.md
CHANGED
|
@@ -1,272 +1,396 @@
|
|
|
1
|
-
[![Module Tests]
|
|
2
|
-
[![Coverage
|
|
1
|
+
[![Module Tests][ci-img]][ci-url]
|
|
2
|
+
[![Test Coverage][cov-img]][cov-url]
|
|
3
3
|
|
|
4
4
|
# dns-resource-record
|
|
5
5
|
|
|
6
|
-
DNS resource record parser, validator, importer, and exporter for node.js & browsers
|
|
6
|
+
DNS resource record parser, validator, importer, and exporter for node.js & browsers
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
**Quick Links:** [Getting Started](#getting-started) | [API Reference](#api-reference) | [Browser/CDN](#browser--cdn) | [Supported Records](#supported-records) | [Contributing](#development)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## Overview
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
- import RRs to and from the following formats:
|
|
12
|
+
This module validates, imports, and exports DNS resource records (RRs) with rigorous RFC compliance and robust test coverage.
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
| :------------------------------------------------------: | :----------------: | :----------------: |
|
|
17
|
-
| **JSON** | :white_check_mark: | :white_check_mark: |
|
|
18
|
-
| **[BIND](https://www.isc.org/bind/) / RFC 1035** | :white_check_mark: | :white_check_mark: |
|
|
19
|
-
| **[Tinydns](https://cr.yp.to/djbdns/tinydns-data.html)** | :white_check_mark: | :white_check_mark: |
|
|
20
|
-
| **MaraDNS** | | :white_check_mark: |
|
|
21
|
-
| **JS** | :white_check_mark: | :white_check_mark: |
|
|
22
|
-
| **PowerDNS** | | |
|
|
23
|
-
| **Wire** | | :white_check_mark: |
|
|
14
|
+
**What you can do:**
|
|
24
15
|
|
|
25
|
-
|
|
16
|
+
- **Validate** DNS records for RFC compliance and well-formedness
|
|
17
|
+
- **Parse/Import** records from BIND zone files, tinydns data files, or JS objects
|
|
18
|
+
- **Export** records to BIND, tinydns, MaraDNS, JSON, or wire format
|
|
19
|
+
- **Manipulate** validated records with type-safe setters
|
|
20
|
+
- **Convert** between formats seamlessly (e.g., tinydns → BIND -> wire)
|
|
26
21
|
|
|
27
|
-
This package
|
|
22
|
+
**Scope:** This package handles individual Resource Records. For zone file operations, see [dns-zone](https://github.com/NicTool/dns-zone).
|
|
28
23
|
|
|
29
|
-
|
|
24
|
+
**Quality:** RFC compliance is a first-class concern. If you encounter a valid RR that fails to parse or an invalid RR that passes validation, please [open an issue](https://github.com/NicTool/dns-resource-record/issues).
|
|
30
25
|
|
|
31
|
-
|
|
26
|
+
## Supported Records
|
|
27
|
+
|
|
28
|
+
This module supports all current DNS RRs in active use on the internet.
|
|
29
|
+
|
|
30
|
+
| Usage | **Resource Record Types** |
|
|
31
|
+
| :-----------: | :-----------------------------------------------------------: |
|
|
32
|
+
| _Common_ | A, AAAA, CNAME, HTTPS, MX, NS, PTR, SOA, SRV, TXT |
|
|
33
|
+
| _Less Common_ | APL, CERT, DHCID, DNAME, HIP, KX, LOC, NAPTR, SVCB, TSIG, URI |
|
|
34
|
+
| _Security_ | CAA, IPSECKEY, OPENPGPKEY, SMIMEA, SSHFP, TLSA |
|
|
35
|
+
| _DNSSEC_ | DNSKEY, DS, NSEC, NSEC3, NSEC3PARAM, RRSIG |
|
|
36
|
+
| _Obsolete_ | HINFO, KEY, NXT, RP, SIG, SPF, WKS |
|
|
37
|
+
|
|
38
|
+
## Getting Started
|
|
39
|
+
|
|
40
|
+
### Installation
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
npm install @nictool/dns-resource-record
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Validation
|
|
47
|
+
|
|
48
|
+
Validate an A record:
|
|
32
49
|
|
|
33
50
|
```js
|
|
34
51
|
import * as RR from '@nictool/dns-resource-record'
|
|
52
|
+
|
|
53
|
+
const validA = new RR.A({
|
|
54
|
+
owner: 'example.com.',
|
|
55
|
+
address: '192.0.2.1',
|
|
56
|
+
ttl: 3600,
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
console.log(validA.toBind())
|
|
60
|
+
// example.com 3600 IN A 192.0.2.1
|
|
35
61
|
```
|
|
36
62
|
|
|
37
|
-
|
|
63
|
+
Invalid records throw immediately:
|
|
38
64
|
|
|
39
65
|
```js
|
|
40
|
-
const exampleRRs = {
|
|
41
|
-
A: {
|
|
42
|
-
owner : 'test.example.com.',
|
|
43
|
-
type : 'A',
|
|
44
|
-
address: '192.0.2.127',
|
|
45
|
-
ttl : 3600,
|
|
46
|
-
},
|
|
47
|
-
AAAA: {
|
|
48
|
-
owner : 'test.example.com.',
|
|
49
|
-
type : 'AAAA',
|
|
50
|
-
address: '2605:7900:20:a::4',
|
|
51
|
-
ttl : 3600,
|
|
52
|
-
},
|
|
53
|
-
SOA: {
|
|
54
|
-
owner : 'example.com.',
|
|
55
|
-
type : 'SOA',
|
|
56
|
-
mname : 'matt.example.com.',
|
|
57
|
-
rname : 'ns1.example.com.',
|
|
58
|
-
serial : 1,
|
|
59
|
-
refresh: 7200,
|
|
60
|
-
retry : 3600,
|
|
61
|
-
expire : 1209600,
|
|
62
|
-
minimum: 3600,
|
|
63
|
-
ttl : 3600,
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
66
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
'ttl' => 3600,
|
|
71
|
-
'class' => 'IN',
|
|
72
|
-
'type' => 'SOA',
|
|
73
|
-
'mname' => 'matt.example.com.',
|
|
74
|
-
'rname' => 'ns1.example.com.',
|
|
75
|
-
'serial' => 1,
|
|
76
|
-
'refresh' => 7200,
|
|
77
|
-
'retry' => 3600,
|
|
78
|
-
'expire' => 1209600,
|
|
79
|
-
'minimum' => 3600
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
catch (e) {
|
|
83
|
-
console.error(e.message) // invalid RRs throw
|
|
67
|
+
new RR.A({ owner: 'example.com.', address: 'not-an-ip' })
|
|
68
|
+
} catch (err) {
|
|
69
|
+
console.error(err.message) // Error: A address must be IPv4
|
|
84
70
|
}
|
|
85
71
|
```
|
|
86
72
|
|
|
87
|
-
|
|
73
|
+
This library enforces RFC-compliance during construction, catching errors early.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## API Reference
|
|
78
|
+
|
|
79
|
+
### Understanding Record Structure
|
|
80
|
+
|
|
81
|
+
Every DNS record has these standard fields:
|
|
82
|
+
|
|
83
|
+
- **owner** — The domain name this record belongs to (always fully qualified, e.g., `example.com.`)
|
|
84
|
+
- **type** — The record type (A, AAAA, MX, TXT, etc.)
|
|
85
|
+
- **ttl** — Time to live in seconds
|
|
86
|
+
- **class** — Almost always `IN` (Internet); omitted in examples
|
|
87
|
+
|
|
88
|
+
Plus **rdata fields** specific to each record type (e.g., `address` for A records, `preference`/`exchange` for MX records).
|
|
89
|
+
|
|
90
|
+
### Core Workflows
|
|
91
|
+
|
|
92
|
+
#### 1. **Validate & Create** — Use the Constructor
|
|
93
|
+
|
|
94
|
+
When you have data in JavaScript object form:
|
|
88
95
|
|
|
89
96
|
```js
|
|
90
|
-
|
|
97
|
+
new RR.SOA({
|
|
98
|
+
owner: 'example.com.',
|
|
99
|
+
mname: 'ns1.example.com.',
|
|
100
|
+
rname: 'hostmaster.example.com.',
|
|
101
|
+
serial: 2024042201,
|
|
102
|
+
refresh: 7200,
|
|
103
|
+
retry: 3600,
|
|
104
|
+
expire: 1209600,
|
|
105
|
+
minimum: 3600,
|
|
106
|
+
ttl: 3600,
|
|
107
|
+
})
|
|
91
108
|
```
|
|
92
109
|
|
|
93
|
-
|
|
110
|
+
**When to use:** Building records programmatically, validating user input, working with API responses.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
#### 2. **Parse BIND Format** — Use `fromBind()`
|
|
115
|
+
|
|
116
|
+
When you have a line from a BIND zone file:
|
|
94
117
|
|
|
95
118
|
```js
|
|
96
|
-
|
|
97
|
-
|
|
119
|
+
const rr = RR.A.fromBind('www.example.com. 3600 IN A 192.0.2.1\n')
|
|
120
|
+
console.log(rr.get('address')) // '192.0.2.1'
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**When to use:** Processing BIND zone files, DNS configs, or standard zone file exports.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
#### 3. **Parse Tinydns Format** — Use `fromTinydns()`
|
|
128
|
+
|
|
129
|
+
When you have a line from a tinydns data file:
|
|
98
130
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
131
|
+
```js
|
|
132
|
+
const rr = RR.A.fromTinydns('+www.example.com:192.0.2.1:3600::\n')
|
|
133
|
+
console.log(rr.get('address')) // '192.0.2.1'
|
|
102
134
|
```
|
|
103
135
|
|
|
104
|
-
|
|
136
|
+
**When to use:** Working with djbdns/tinydns configurations, or when parsing tinydns data files.
|
|
137
|
+
|
|
138
|
+
---
|
|
105
139
|
|
|
106
|
-
|
|
140
|
+
#### 4. **Export to BIND** — Use `toBind()`
|
|
107
141
|
|
|
108
|
-
|
|
142
|
+
Convert any validated record to BIND zone file format:
|
|
109
143
|
|
|
110
144
|
```js
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
class: 'IN',
|
|
145
|
+
new RR.MX({
|
|
146
|
+
owner: 'example.com.',
|
|
147
|
+
preference: 10,
|
|
148
|
+
exchange: 'mail.example.com.',
|
|
116
149
|
ttl: 3600,
|
|
117
|
-
|
|
118
|
-
|
|
150
|
+
}).toBind()
|
|
151
|
+
// example.com 3600 IN MX 10 mail.example.com.
|
|
119
152
|
```
|
|
120
153
|
|
|
121
|
-
|
|
154
|
+
**When to use:** Generating zone files, displaying records for editing, exporting to BIND nameservers.
|
|
122
155
|
|
|
123
|
-
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
#### 5. **Export to Tinydns** — Use `toTinydns()`
|
|
159
|
+
|
|
160
|
+
Convert to tinydns data file format:
|
|
124
161
|
|
|
125
162
|
```js
|
|
126
|
-
|
|
127
|
-
|
|
163
|
+
new RR.A({
|
|
164
|
+
owner: 'example.com.',
|
|
165
|
+
address: '192.0.2.1',
|
|
166
|
+
ttl: 3600,
|
|
167
|
+
}).toTinydns()
|
|
168
|
+
// +example.com:192.0.2.1:3600::
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**When to use:** Generating tinydns data files, migrating to djbdns, or integrating with tinydns tooling.
|
|
172
|
+
|
|
173
|
+
---
|
|
128
174
|
|
|
129
|
-
|
|
175
|
+
#### 6. **Round-Trip Conversion**
|
|
130
176
|
|
|
131
|
-
|
|
132
|
-
|
|
177
|
+
Parse from one format, export to another:
|
|
178
|
+
|
|
179
|
+
```js
|
|
180
|
+
// tinydns → BIND
|
|
181
|
+
const fromTiny = RR.CAA.fromTinydns(
|
|
182
|
+
':ns1.example.com:257:\\000\\005issue"http\\072\\057\\057letsencrypt.org":3600::\n',
|
|
183
|
+
)
|
|
184
|
+
console.log(fromTiny.toBind())
|
|
185
|
+
// ns1.example.com 3600 IN CAA 0 issue "http://letsencrypt.org"
|
|
133
186
|
```
|
|
134
187
|
|
|
135
|
-
|
|
188
|
+
**When to use:** DNS migrations, format conversions, tool interoperability.
|
|
189
|
+
|
|
190
|
+
---
|
|
136
191
|
|
|
137
|
-
|
|
192
|
+
### Manipulating Records
|
|
193
|
+
|
|
194
|
+
Use **setter methods** to modify validated records. Setter names follow the pattern `set` + `FieldName` (camelCased):
|
|
138
195
|
|
|
139
196
|
```js
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
197
|
+
const a = new RR.A({
|
|
198
|
+
owner: 'example.com.',
|
|
199
|
+
address: '192.0.2.1',
|
|
200
|
+
ttl: 3600,
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
a.setAddress('192.0.2.2')
|
|
204
|
+
a.setTtl(7200)
|
|
205
|
+
|
|
206
|
+
console.log(a.toBind())
|
|
207
|
+
// example.com 7200 IN A 192.0.2.2
|
|
143
208
|
```
|
|
144
209
|
|
|
145
|
-
|
|
210
|
+
Setters include validation. Invalid values throw with helpful error messages.
|
|
146
211
|
|
|
147
|
-
|
|
212
|
+
For a list of available setters, check `getFields('rdata')` for your record type:
|
|
148
213
|
|
|
149
214
|
```js
|
|
150
|
-
|
|
151
|
-
//
|
|
215
|
+
new RR.SSHFP(null).getFields('rdata')
|
|
216
|
+
// ['algorithm', 'fptype', 'fingerprint']
|
|
217
|
+
// So use: setSshfp(), setFptype(), setFingerprint()
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
152
221
|
|
|
153
|
-
|
|
154
|
-
|
|
222
|
+
### Metadata Methods
|
|
223
|
+
|
|
224
|
+
Get information about record types:
|
|
225
|
+
|
|
226
|
+
#### `getFields([section])`
|
|
227
|
+
|
|
228
|
+
Get field names for a record type. Pass `'rdata'` to get only the custom fields:
|
|
229
|
+
|
|
230
|
+
```js
|
|
231
|
+
new RR.A(null).getFields() // ['owner', 'ttl', 'class', 'type', 'address']
|
|
232
|
+
new RR.A(null).getFields('rdata') // ['address']
|
|
233
|
+
new RR.MX(null).getFields('rdata') // ['preference', 'exchange']
|
|
155
234
|
```
|
|
156
235
|
|
|
157
|
-
|
|
236
|
+
#### `getRFCs()`
|
|
158
237
|
|
|
159
|
-
|
|
238
|
+
Get RFC references for a record type:
|
|
160
239
|
|
|
161
240
|
```js
|
|
162
|
-
|
|
241
|
+
new RR.A(null).getRFCs() // [1035]
|
|
242
|
+
new RR.MX(null).getRFCs() // [1035, 2181, 7505]
|
|
243
|
+
new RR.SRV(null).getRFCs() // [2782]
|
|
163
244
|
```
|
|
164
245
|
|
|
165
|
-
|
|
246
|
+
#### `getCanonical()`
|
|
166
247
|
|
|
167
|
-
|
|
248
|
+
Get a record with all fields populated with default/canonical values:
|
|
168
249
|
|
|
169
250
|
```js
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
251
|
+
new RR.AAAA(null).getCanonical()
|
|
252
|
+
// {
|
|
253
|
+
// owner: 'host.example.com.',
|
|
254
|
+
// address: '2001:0db8:0020:000a:0000:0000:0000:0004',
|
|
255
|
+
// class: 'IN',
|
|
256
|
+
// ttl: 3600,
|
|
257
|
+
// type: 'AAAA'
|
|
258
|
+
// }
|
|
178
259
|
```
|
|
179
260
|
|
|
180
|
-
|
|
261
|
+
#### `toJSON()` / `JSON.stringify()`
|
|
181
262
|
|
|
182
|
-
|
|
263
|
+
Serialize a record to a plain object:
|
|
183
264
|
|
|
184
|
-
|
|
265
|
+
```js
|
|
266
|
+
const a = new RR.A({ owner: 'example.com.', address: '192.0.2.1', ttl: 3600 })
|
|
267
|
+
JSON.stringify(a)
|
|
268
|
+
// {"owner":"example.com.","ttl":3600,"class":"IN","type":"A","address":"192.0.2.1"}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
### Advanced: Bypassing Validation
|
|
274
|
+
|
|
275
|
+
The `set()` method bypasses validation (use carefully):
|
|
185
276
|
|
|
186
277
|
```js
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}).toBind())
|
|
190
|
-
ns1.example.com 3600 IN CAA 0 issue "http://letsencrypt.org"
|
|
278
|
+
record.set('address', 'invalid-value')
|
|
279
|
+
// Works, but now the record is malformed — useful only for testing or low-level manipulation
|
|
191
280
|
```
|
|
192
281
|
|
|
193
|
-
|
|
282
|
+
**Note:** Validation is there to protect data integrity. Use at your own risk.
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Browser & CDN
|
|
287
|
+
|
|
288
|
+
Use this module directly in browsers via CDN:
|
|
289
|
+
|
|
290
|
+
```html
|
|
291
|
+
<!DOCTYPE html>
|
|
292
|
+
<html>
|
|
293
|
+
<head>
|
|
294
|
+
<title>DNS Record Validator</title>
|
|
295
|
+
</head>
|
|
296
|
+
<body>
|
|
297
|
+
<h1>DNS Record Validator</h1>
|
|
298
|
+
<pre id="output"></pre>
|
|
299
|
+
|
|
300
|
+
<script type="module">
|
|
301
|
+
// Import from unpkg (or jsdelivr, esm.sh)
|
|
302
|
+
import * as RR from 'https://unpkg.com/@nictool/dns-resource-record@latest/dist/dns-rr.min.js'
|
|
303
|
+
|
|
304
|
+
// Use just like Node.js
|
|
305
|
+
const record = new RR.A({
|
|
306
|
+
owner: 'example.com.',
|
|
307
|
+
address: '192.0.2.1',
|
|
308
|
+
ttl: 3600,
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
document.getElementById('output').textContent = record.toBind()
|
|
312
|
+
</script>
|
|
313
|
+
</body>
|
|
314
|
+
</html>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**Available CDNs:**
|
|
318
|
+
|
|
319
|
+
- **unpkg:** `https://unpkg.com/@nictool/dns-resource-record/dist/dns-rr.min.js`
|
|
320
|
+
- **jsdelivr:** `https://cdn.jsdelivr.net/npm/@nictool/dns-resource-record/dist/dns-rr.min.js`
|
|
321
|
+
- **esm.sh:** `https://esm.sh/@nictool/dns-resource-record`
|
|
322
|
+
|
|
323
|
+
**Live example:** See [nictool.github.io/builder/](https://nictool.github.io/builder/) for an interactive DNS record editor using this library.
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Important Concepts
|
|
328
|
+
|
|
329
|
+
### Domain Name Normalization
|
|
330
|
+
|
|
331
|
+
Domain owner names are:
|
|
332
|
+
|
|
333
|
+
- **Stored fully qualified** (absolute), e.g., `example.com.` not `example.com`
|
|
334
|
+
- **Normalized to lowercase** because:
|
|
335
|
+
- DNS is case-insensitive (RFC 4343, RFC 1035)
|
|
336
|
+
- This library enforces automatic duplicate suppression
|
|
337
|
+
- DNSSEC canonicalization requires it (RFC 4034)
|
|
338
|
+
- Wire format for most RRs requires lowercase
|
|
339
|
+
|
|
340
|
+
**Example:**
|
|
341
|
+
|
|
342
|
+
```js
|
|
343
|
+
new RR.A({ owner: 'EXAMPLE.COM', address: '192.0.2.1', ttl: 3600 })
|
|
344
|
+
// Automatically normalized to: 'example.com.'
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Relative vs Absolute Names
|
|
348
|
+
|
|
349
|
+
Master zone file expansions (relative domain names) are handled by [dns-zone](https://github.com/NicTool/dns-zone). This library works only with fully qualified names.
|
|
350
|
+
|
|
351
|
+
### Export Options
|
|
352
|
+
|
|
353
|
+
The `toBind()` and `toMaraDNS()` methods accept an options object to customize output:
|
|
354
|
+
|
|
355
|
+
```js
|
|
356
|
+
record.toBind({ suppressTtl: true, suppressClass: true, relativeName: true })
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
See [dns-zone](https://github.com/NicTool/dns-zone) for full options documentation.
|
|
360
|
+
|
|
361
|
+
## Development
|
|
362
|
+
|
|
363
|
+
No external dependencies. Runs on node.js and modern browsers.
|
|
364
|
+
|
|
365
|
+
**Key scripts:**
|
|
366
|
+
|
|
367
|
+
- `npm test` — Run all tests with node's built-in test runner
|
|
368
|
+
- `npm run watch` — Run tests in watch mode during development
|
|
369
|
+
- `npm run lint` — Check code with ESLint
|
|
370
|
+
- `npm run format` — Auto-format with Prettier and fix linting issues
|
|
371
|
+
- `npm run build` — Regenerate browser bundle and README
|
|
372
|
+
- `npm run test:coverage` — Generate test coverage report
|
|
373
|
+
|
|
374
|
+
**Architecture:**
|
|
375
|
+
|
|
376
|
+
- **rr.js** — Base class with shared DNS logic and validation
|
|
377
|
+
- **rr/\*.js** — Individual RR type implementations
|
|
378
|
+
- **test/\*.js** — Comprehensive test suite for each RR type
|
|
379
|
+
|
|
380
|
+
## References
|
|
381
|
+
|
|
382
|
+
- [DNS Record Types (Wikipedia)](https://en.wikipedia.org/wiki/List_of_DNS_record_types)
|
|
383
|
+
- [DNS Terminology (NicTool Dictionary)](https://nictool.github.io/Dictionary)
|
|
384
|
+
- [dns-zone](https://www.npmjs.com/package/@nictool/dns-zone) — Zone file operations
|
|
385
|
+
- [dns-nameserver](https://www.npmjs.com/package/@nictool/dns-nameserver) — Nameserver management
|
|
386
|
+
|
|
387
|
+
---
|
|
194
388
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
| **AAAA** | :white_check_mark: | :white_check_mark: |
|
|
204
|
-
| **CNAME** | :white_check_mark: | :white_check_mark: |
|
|
205
|
-
| **HTTPS** | :white_check_mark: | :white_check_mark: |
|
|
206
|
-
| **MX** | :white_check_mark: | :white_check_mark: |
|
|
207
|
-
| **NS** | :white_check_mark: | :white_check_mark: |
|
|
208
|
-
| **PTR** | :white_check_mark: | :white_check_mark: |
|
|
209
|
-
| **SRV** | :white_check_mark: | :white_check_mark: |
|
|
210
|
-
| **TXT** | :white_check_mark: | :white_check_mark: |
|
|
211
|
-
| _Less Common_ |
|
|
212
|
-
| **APL** | :white_check_mark: | :white_check_mark: |
|
|
213
|
-
| **CERT** | :white_check_mark: | :white_check_mark: |
|
|
214
|
-
| **DHCID** | :white_check_mark: | :white_check_mark: |
|
|
215
|
-
| **DNAME** | :white_check_mark: | :white_check_mark: |
|
|
216
|
-
| **HIP** | :white_check_mark: | :white_check_mark: |
|
|
217
|
-
| **KEY** | :white_check_mark: | :white_check_mark: |
|
|
218
|
-
| **KX** | :white_check_mark: | :white_check_mark: |
|
|
219
|
-
| **LOC** | :white_check_mark: | :white_check_mark: |
|
|
220
|
-
| **NAPTR** | :white_check_mark: | :white_check_mark: |
|
|
221
|
-
| **SOA** | :white_check_mark: | :white_check_mark: |
|
|
222
|
-
| **SVCB** | :white_check_mark: | :white_check_mark: |
|
|
223
|
-
| **TSIG** | :white_check_mark: | :white_check_mark: |
|
|
224
|
-
| **URI** | :white_check_mark: | :white_check_mark: |
|
|
225
|
-
| _Security_ |
|
|
226
|
-
| **CAA** | :white_check_mark: | :white_check_mark: |
|
|
227
|
-
| **IPSECKEY** | :white_check_mark: | :white_check_mark: |
|
|
228
|
-
| **OPENPGPKEY** | :white_check_mark: | :white_check_mark: |
|
|
229
|
-
| **SMIMEA** | :white_check_mark: | :white_check_mark: |
|
|
230
|
-
| **SSHFP** | :white_check_mark: | :white_check_mark: |
|
|
231
|
-
| **TLSA** | :white_check_mark: | :white_check_mark: |
|
|
232
|
-
| _DNSSEC_ |
|
|
233
|
-
| **DNSKEY** | :white_check_mark: | :white_check_mark: |
|
|
234
|
-
| **DS** | :white_check_mark: | :white_check_mark: |
|
|
235
|
-
| **NSEC** | :white_check_mark: | :white_check_mark: |
|
|
236
|
-
| **NSEC3** | :white_check_mark: | :white_check_mark: |
|
|
237
|
-
| **NSEC3PARAM** | :white_check_mark: | :white_check_mark: |
|
|
238
|
-
| **RRSIG** | :white_check_mark: | :white_check_mark: |
|
|
239
|
-
| _Deprecated_ |
|
|
240
|
-
| **NXT** | :white_check_mark: | :white_check_mark: |
|
|
241
|
-
| **SPF** | :white_check_mark: | :white_check_mark: |
|
|
242
|
-
| _Obsolete_ |
|
|
243
|
-
| **HINFO** | :white_check_mark: | :white_check_mark: |
|
|
244
|
-
| **RP** | :white_check_mark: | :white_check_mark: |
|
|
245
|
-
| **SIG** | :white_check_mark: | :white_check_mark: |
|
|
246
|
-
| **WKS** | :white_check_mark: | :white_check_mark: |
|
|
247
|
-
|
|
248
|
-
## TIPS
|
|
249
|
-
|
|
250
|
-
- Domain owner names are:
|
|
251
|
-
- stored fully qualified, aka absolute.
|
|
252
|
-
- normalized to lower case, because:
|
|
253
|
-
- DNS is case insensitive (see RFCs 4343, 1035, 1034)
|
|
254
|
-
- this library enforces duplicate suppression
|
|
255
|
-
- DNSSEC canonicalization (see RFC 4034)
|
|
256
|
-
- wire format for most RRs require it
|
|
257
|
-
- Master Zone File expansions exist in [dns-zone](https://github.com/NicTool/dns-zone)
|
|
258
|
-
- to{Bind|MaraDNS} output can be influenced (suppress TTL, class, relative domain names) with an options object. See it in `bin/dns-zone` in the [dns-zone](https://github.com/NicTool/dns-zone) package.
|
|
259
|
-
|
|
260
|
-
## SEE ALSO
|
|
261
|
-
|
|
262
|
-
- [Dictionary of DNS terms](https://nictool.github.io/web/Dictionary)
|
|
263
|
-
- [Wikipedia, List of DNS Record Types](https://en.wikipedia.org/wiki/List_of_DNS_record_types)
|
|
264
|
-
- @nictool/[dns-zone](https://www.npmjs.com/package/@nictool/dns-zone)
|
|
265
|
-
- @nictool/[dns-nameserver](https://www.npmjs.com/package/@nictool/dns-nameserver)
|
|
266
|
-
|
|
267
|
-
## DEVELOP
|
|
268
|
-
|
|
269
|
-
- There are no dependencies. That's no accident.
|
|
270
|
-
- ESM browsers and node.js
|
|
271
|
-
- Platform independence is a goal
|
|
272
|
-
- [x] CI tests are on linux, windows, and macOS
|
|
389
|
+
[ci-img]: https://github.com/NicTool/dns-resource-record/actions/workflows/ci.yml/badge.svg
|
|
390
|
+
[ci-url]: https://github.com/NicTool/dns-resource-record/actions/workflows/ci.yml
|
|
391
|
+
[cov-img]: https://coveralls.io/repos/github/NicTool/dns-resource-record/badge.svg
|
|
392
|
+
[cov-url]: https://coveralls.io/github/NicTool/dns-resource-record
|
|
393
|
+
[bind-url]: https://www.isc.org/bind/
|
|
394
|
+
[knot-url]: https://www.knot-dns.cz
|
|
395
|
+
[nsd-url]: https://www.nlnetlabs.nl/projects/nsd/about/
|
|
396
|
+
[pdns-url]: https://www.powerdns.com/powerdns-authoritative-server
|