song940 / node-dns Goto Github PK
View Code? Open in Web Editor NEW:globe_with_meridians: DNS Server and Client Implementation in Pure JavaScript with no dependencies.
Home Page: https://npmjs.org/dns2
License: MIT License
:globe_with_meridians: DNS Server and Client Implementation in Pure JavaScript with no dependencies.
Home Page: https://npmjs.org/dns2
License: MIT License
I liked your propose but I don't know how to use it resolves the queries to all query types?
Can you explain this line to me?
Line 35 in 4b03451
Steps to reproduce:
Actual result:
Prints []
and then hangs.
Expected result:
An actual result.
If I run tcpdump while running example/index.js, I see a SERVFAIL response from google's DNS server:
$ sudo tcpdump -X host 8.8.8.8
tcpdump: data link type PKTAP
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on pktap, link-type PKTAP (Apple DLT_PKTAP), capture size 262144 bytes
18:38:18.452157 IP 172.20.10.7.51217 > dns.google.domain: 7873 Type0? google.com. (28)
0x0000: c698 80e9 e264 80e6 5014 bf1c 0800 4500 .....d..P.....E.
0x0010: 0038 5435 0000 4011 6055 ac14 0a07 0808 .8T5..@.`U......
0x0020: 0808 c811 0035 0024 3fbb 1ec1 0000 0001 .....5.$?.......
0x0030: 0000 0000 0000 0667 6f6f 676c 6503 636f .......google.co
0x0040: 6d00 0000 0001 m.....
18:38:18.525937 IP dns.google.domain > 172.20.10.7.51217: 7873 ServFail 0/0/0 (28)
0x0000: 80e6 5014 bf1c c698 80e9 e264 0800 4580 ..P........d..E.
0x0010: 0038 efdc 0000 7811 8c2d 0808 0808 ac14 .8....x..-......
0x0020: 0a07 0035 c811 0024 bf38 1ec1 8082 0001 ...5...$.8......
0x0030: 0000 0000 0000 0667 6f6f 676c 6503 636f .......google.co
0x0040: 6d00 0000 0001 m.....
^C
2 packets captured
7 packets received by filter
0 packets dropped by kernel
The other script in example/ work as expected.
On my system it's taking ~5 seconds to resolve a simple lookup.
The delay seems to be outside my query handler and in the dns2 server itslef.
Is dns2 known to be slow?
Hi,
I am trying to handle SRV type queries, such as
dig @127.0.0.1 -p 53 instance._service_type -t srv
I noticed that packet.js includes an [SRV description], but does not recognize Packet.TYPE.SRV. Thus, I added
SRV : 0x21,
to the Packet.TYPE definition, and now the server correctly decodes the query. However, something is wrong in the answer:
Samsung:Downloads micheleamoretti$ dig @127.0.0.1 -p 53 6gkzwgjz._iot._udp -t srv
;; Warning: Message parser reports malformed message packet.
; <<>> DiG 9.10.6 <<>> @127.0.0.1 -p 53 6gkzwgjz._iot._udp -t srv
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20964
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: Message has 6 extra bytes at end
;; QUESTION SECTION:
;6gkzwgjz._iot._udp. IN SRV
;; Query time: 9 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Jun 25 14:55:53 CEST 2020
;; MSG SIZE rcvd: 72
What is the cause of that WARNING?
My server code creates the response in this way:
response.header.qr = 1;
response.header.ra = 1;
response.additionals = [];
if (domains[query])
{
response.answers.push({
name: query,
type: Packet.TYPE.SRV,
class: Packet.CLASS.IN,
ttl: 100,
target: domains[query],
port: 8080
});
}
It is not possible to set an AAAA record to an IPv6 Address with ::, like fe80::1
The solution is to expand the IPv6 Address to i.e. fe80:0:0:0:0:0:0:1
It would be nice if the library would also handle abbreviated IPv6 Addresses.
According to the source code and documentation in order to return a valid AAAA response I have to do the following code:
const response = Packet.createResponseFromRequest(request);
response.answers.push({
name: 'google.com',
type: Packet.TYPE.AAAA,
class: Packet.CLASS.IN,
ttl: 10,
address: '2a00:1450:4003:803::200e',
});
but currently, dig returns an error like this
WARNING: Message has 12 extra bytes at end
Hi @song940 and all others, any chance of a possible rate limiter implementation or something that might work that has already been implemented?
When under high load, the server pauses for a couple of seconds now and again.
I've tried to work out what could have caused this.
But at my wits end to find this.
Has someone else seen something similar?
One of the advantages of dns-over-https for me is to be able to make dns queries in browsers. However without having CORS headers it is severely limited. Maybe it would gbe good to add configuration that allows to specify CORS settings and maybe even have a *
as default?
on udp ipv4 didn't test other protocols
Does this package support GeoDNS? ( Response based on client country, usefull for custom CDN's )
I would like to make DNS lookups with an EDNS Client Subnet extension as specified in https://tools.ietf.org/html/rfc7871. This extension is used to request an IP address as if the request was made from client in a specific subnet.
E.g. I want to be able to perform lookups that Bind's dig can do (since version 9.10):
$ dig @ns1.google.com google.com +subnet=208.67.222.0/24
; <<>> DiG 9.10.6 <<>> @ns1.google.com google.com +subnet=208.67.222.0/24
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26637
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
; CLIENT-SUBNET: 208.67.222.0/24/24
;; QUESTION SECTION:
;google.com. IN A
;; ANSWER SECTION:
google.com. 300 IN A 172.217.17.110
;; Query time: 26 msec
;; SERVER: 216.239.32.10#53(216.239.32.10)
;; WHEN: Thu Oct 08 17:04:18 CEST 2020
;; MSG SIZE rcvd: 66
Hi again,
I'm running dns2 inside a Debian VM - VirtualBox.
When i force dns2 to use the same IP addr resolver that nslookup use, dns2 return an empty result. tcpdump show an access denied.
NSLOOKUP:
root@debian:/home/franck# /usr/sbin/tcpdump -Ax -n udp port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp0s3, link-type EN10MB (Ethernet), capture size 262144 bytes
14:05:31.332388 IP 10.0.2.15.47214 > 192.168.1.254.53: 18577+ A? google.com. (28)
0x0000: 4500 0038 95a1 0000 4011 165f 0a00 020f
0x0010: c0a8 01fe b86e 0035 0024 ceea 4891 0100
0x0020: 0001 0000 0000 0000 0667 6f6f 676c 6503
0x0030: 636f 6d00 0001 0001
14:05:31.337546 IP 192.168.1.254.53 > 10.0.2.15.47214: 18577 1/0/0 A 142.250.179.78 (44)
0x0000: 4500 0048 c8d6 0000 4011 e319 c0a8 01fe
0x0010: 0a00 020f 0035 b86e 0034 983e 4891 8180
0x0020: 0001 0001 0000 0000 0667 6f6f 676c 6503
0x0030: 636f 6d00 0001 0001 c00c 0001 0001 0000
0x0040: 00c7 0004 8efa b34e
14:05:31.338036 IP 10.0.2.15.50613 > 192.168.1.254.53: 49218+ AAAA? google.com. (28)
0x0000: 4500 0038 95a2 0000 4011 165e 0a00 020f
0x0010: c0a8 01fe c5b5 0035 0024 ceea c042 0100
0x0020: 0001 0000 0000 0000 0667 6f6f 676c 6503
0x0030: 636f 6d00 001c 0001
14:05:31.340476 IP 192.168.1.254.53 > 10.0.2.15.50613: 49218 1/0/0 AAAA 2a00:1450:4007:80a::200e (56)
0x0000: 4500 0054 c8d7 0000 4011 e30c c0a8 01fe
0x0010: 0a00 020f 0035 c5b5 0040 aeb8 c042 8180
0x0020: 0001 0001 0000 0000 0667 6f6f 676c 6503
0x0030: 636f 6d00 001c 0001 c00c 001c 0001 0000
0x0040: 00d4 0010 2a00 1450 4007 080a 0000 0000
0x0050: 0000 200e
DNS2
14:05:43.510957 IP 10.0.2.15.60211 > 192.168.1.254.53: 183 A? google.com. (28)
0x0000: 4500 0038 97be 4000 4011 d441 0a00 020f
0x0010: c0a8 01fe eb33 0035 0024 ceea 00b7 0000
0x0020: 0001 0000 0000 0000 0667 6f6f 676c 6503
0x0030: 636f 6d00 0001 0001
14:05:43.518647 IP 192.168.1.254.53 > 10.0.2.15.60211: 183 Refused 0/0/0 (28)
0x0000: 4500 0038 c8d8 0000 4011 e327 c0a8 01fe
0x0010: 0a00 020f 0035 eb33 0024 b192 00b7 8085
0x0020: 0001 0000 0000 0000 0667 6f6f 676c 6503
0x0030: 636f 6d00 0001 0001
Any idea ?
You will find in attachement pcap files with both traces.
Hi,
I managed to run the server described in the README page, but I am in trouble with the client.
I have macOS 10.15.5, node 12.18.1.
mymac$ node client.js
/.../path/.../client.js:12
dns.send(packet, function(err, res){
^
TypeError: dns.send is not a function
at Object. (/.../path/.../client.js:12:5)
at Module._compile (internal/modules/cjs/loader.js:1138:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
at Module.load (internal/modules/cjs/loader.js:986:32)
at Function.Module._load (internal/modules/cjs/loader.js:879:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47
const dns = require('dns2');
const proxy = require('dns2-proxy');
const cache = require('dns2-proxy-redis');
const dnsmasq = require('dns2-dnsmasq');
const app = proxy();
app.use(cache());
app.use(dnsmasq({
conf: '/etc/dnsmasq.conf'
}));
dns.createServer(app).listen(53);
What is the max RPS that the server can handle?
(Requests Per Second)
Hi.
I was trying to run the code in your example:
const dns = require('dns2');
const { Packet } = dns;
const server = dns.createServer(function(request, send) {
const response = Packet.createResponseFromRequest(request);
const answer = new Packet.createResourceFromQuestion(request.questions[0], {
target: 'hermes2.jabber.org',
port: 8080,
weight: 30,
priority: 30
});
response.answers.push(answer);
send(response);
}).listen(5333);
And it's throwing when the response is being sent after you push the answer into response.answers
.
TypeError: Cannot read property 'split' of undefined
at Function.Packet.Resource.A.encode (C:\Users\austi\Projects\names\node_modules\dns2\packet.js:429:30)
at Function.Packet.Resource.encode (C:\Users\austi\Projects\names\node_modules\dns2\packet.js:332:39)
at C:\Users\austi\Projects\names\node_modules\dns2\packet.js:152:22
at Array.map (<anonymous>)
at Packet.<anonymous> (C:\Users\austi\Projects\names\node_modules\dns2\packet.js:151:29)
at Array.forEach (<anonymous>)
at Packet.toBuffer (C:\Users\austi\Projects\names\node_modules\dns2\packet.js:148:6)
at Server.response (C:\Users\austi\Projects\names\node_modules\dns2\server\udp.js:27:25)
at Server.<anonymous> (C:\Users\austi\Projects\names\index.js:13:5)
at Server.emit (events.js:200:13)
How can I get SOA records of a domain. Sometimes its not showing.
Hi !
Times to times, using TCP client, i have this error :
eviltik@debian:/code/eviltik/node-dns$ node --trace-warnings example/client/tcp.js
(node:5179) UnhandledPromiseRejectionWarning: RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: Attempt to access memory outside buffer bounds
at boundsError (internal/buffer.js:81:11)
at Buffer.readUInt8 (internal/buffer.js:249:5)
at Function.BufferReader.read (/code/eviltik/node-dns/lib/reader.js:39:23)
at BufferReader.read (/code/eviltik/node-dns/lib/reader.js:49:26)
at Function.Packet.Header.parse (/code/eviltik/node-dns/packet.js:200:27)
at Function.Packet.parse (/code/eviltik/node-dns/packet.js:116:33)
at /code/eviltik/node-dns/client/tcp.js:18:19
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async /code/eviltik/node-dns/example/client/tcp.js:6:20
at emitUnhandledRejectionWarning (internal/process/promises.js:168:15)
at processPromiseRejections (internal/process/promises.js:247:11)
at processTicksAndRejections (internal/process/task_queues.js:94:32)
(node:5179) RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: Attempt to access memory outside buffer bounds
at boundsError (internal/buffer.js:81:11)
at Buffer.readUInt8 (internal/buffer.js:249:5)
at Function.BufferReader.read (/code/eviltik/node-dns/lib/reader.js:39:23)
at BufferReader.read (/code/eviltik/node-dns/lib/reader.js:49:26)
at Function.Packet.Header.parse (/code/eviltik/node-dns/packet.js:200:27)
at Function.Packet.parse (/code/eviltik/node-dns/packet.js:116:33)
at /code/eviltik/node-dns/client/tcp.js:18:19
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async /code/eviltik/node-dns/example/client/tcp.js:6:20
(node:5179) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
at emitDeprecationWarning (internal/process/promises.js:180:11)
at processPromiseRejections (internal/process/promises.js:249:13)
at processTicksAndRejections (internal/process/task_queues.js:94:32)
I had a chance to sniff it using tcpdump. In the zip file, you will find a successfull result (OK) and an errored result (KO)
It's too low level for me, i can't help/understand here. We can see that in the KO trace, 2 packets are missing at the end: FIN,ACK from the server, followed by an ACK from the client. Note that on my side (inside a Virtualbox VM) it append randomly, let's say one error each 10 resolve). Hard to reproduce.
Any idea if it would be possible to implement DNSSEC?
A.K.A DNSKEY and RRSIG
Hi,
is there a way to send authoritative instead of non-authoritative responses?
I use this code from the example
udp: true,
tcp: true,
handle: (request, send, rinfo) => {
const response = Packet.createResponseFromRequest(request);
const [ question ] = request.questions;
const { name } = question;
response.answers.push({
name,
type: Packet.TYPE.A,
class: Packet.CLASS.IN,
ttl: 300,
address: '8.8.8.8'
});
send(response);
}
});```
The Problem is, tcp is listening on IPv6 :: instead of 127.0.0.1 and i have no option to give a ipv4 adress - only ports
On an authoritative server, was trying to get NS to work
the output, when digging, appears under the answer section, I see using serverspace.io they respond in an authority section of the response, is this why I'm getting servfail via google?
C:\bind>dig NS sheppie.fujiavax.ga
; <<>> DiG 9.11.36 <<>> NS sheppie.fujiavax.ga
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33409
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;sheppie.fujiavax.ga. IN NS
;; ANSWER SECTION:
sheppie.fujiavax.ga. 3600 IN NS ns1.epizy.com.
;; Query time: 669 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Mon Jan 24 19:48:04 South Africa Standard Time 2022
;; MSG SIZE rcvd: 75
C:\bind>dig @ns01.serverspace.io NS sheppie.fuji.ga
; <<>> DiG 9.11.36 <<>> @ns01.serverspace.io NS sheppie.fuji.ga
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 39571
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;sheppie.fuji.ga. IN NS
;; Query time: 231 msec
;; SERVER: 45.14.48.20#53(45.14.48.20)
;; WHEN: Mon Jan 24 19:49:04 South Africa Standard Time 2022
;; MSG SIZE rcvd: 44
C:\bind>dig sheppie.fujiavax.ga
; <<>> DiG 9.11.36 <<>> sheppie.fujiavax.ga
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 4712
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;sheppie.fujiavax.ga. IN A
;; Query time: 946 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Mon Jan 24 19:51:09 South Africa Standard Time 2022
;; MSG SIZE rcvd: 48
I want to log each requests in db. But I want to log requester's IP. rinfo.address
returns 192.168.0.1 (It's local ip of my ipTIME router)
Hi,
when I send a request to the server using dig, as shown in the README, I get a response that seems ok, but the server prints the following messages:
node-dns > unknown parser type: undefined(41)
..
node-dns > unknown encoder undefined(41)
At the client, the response starts with:
;; Warning: Message parser reports malformed message packet.
I think the issue is in the client's request sent by dig. Is there a way to fix it?
Thanks
This is not an issue but an example for anyone who wants to use dns2 both with UDP and TCP. You can find the example application here.
npm install dns2
node app.js
โ it should start both serversdig A example.com @127.0.0.1 -p5053
dig A example.com +tcp @127.0.0.1 -p5053
Hi, so without specifying too much detail yet, I can use a standard tool to test my DNS server which in turn causes a buffer overrun which by default will cause the listener to throw an exception and stop responding.
Should I report the details somewhere specific? I haven't investigated a fix yet as this is just a prototype I'm working on.
Perhaps there is a standard way (in this library) to just catch this and continue?
Example exception (server created with dns2.createUDPServer):
internal/buffer.js:81
throw new ERR_BUFFER_OUT_OF_BOUNDS();
^
RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: Attempt to access memory outside buffer bounds
at boundsError (internal/buffer.js:81:11)
at Uint8Array.readUInt8 (internal/buffer.js:249:5)
at Function.BufferReader.read (dns-service\node_modules\dns2\lib\reader.js:39:23)
at BufferReader.read (dns-service\node_modules\dns2\lib\reader.js:49:26)
at Function.Packet.Header.parse (dns-service\node_modules\dns2\packet.js:200:27)
at Function.Packet.parse (dns-service\node_modules\dns2\packet.js:116:33)
at Server.handle (dns-service\node_modules\dns2\server\udp.js:22:28)
at Server.emit (events.js:315:20)
at UDP.onMessage [as onmessage] (dgram.js:919:8) {
code: 'ERR_BUFFER_OUT_OF_BOUNDS'
There is a rather annoying error in the types. and is that although they are declared these are not exported so every time they try to use in a modular system or to declare that a value has a specific typescript type throws an error that "X type is used but not accessible"
The exported variable 'DomainNameServer' has or uses the name 'DnsServer' of the module 'C:/Servers/npanel/node_modules/@types/dns2/index' external, but cannot be named.ts(4023)
SOLUTION: use a export
before declare
export declare class DnsServer extends EventEmitter {
addresses(): {
udp?: net.AddressInfo;
tcp?: net.AddressInfo;
doh?: net.AddressInfo;
};
listen(ports: { udp?: number; tcp?: number; doh?: number }): Promise<void>;
close(): Promise<void>;
}
ALSO: readme on DNS Server are outdated:
Lines 160 to 163 in b2e994c
server.listen({
// Optionally specify port and/or address for each server:
//DELETABLE: old
//udp: { port: 5333 }
//udp: 5333
});
After discussing with a member of the 1.1.1.1 team at Cloudflare, the reason for this problem is that dns2 is not passing in the RD
bit in the request header.
I added the following line right above the client.send
call in client/udp.js
, and it seems to have fixed the problem completely.
query.header.rd = 1;
According to the member at Cloudflare, the RD
bit is required by the Cloudflare resolver, and is also required by most other resolvers.
I'd be happy to submit a PR to fix this @song940, however, I'm not sure we want to hard code it to 1. Should this be a dynamic option passed in by the user? If so, how should the syntax/API look for this?
Original report below.
If you run the following code.
(async () => {
const name = "avatars3.githubusercontent.com";
// dns2
const DNS = require('dns2');
const dnsClient = new DNS({
"nameServers": ["1.1.1.1"]
});
console.log(await dnsClient.resolveA(name));
// Node dns
const { Resolver } = require('dns');
const resolver = new Resolver();
resolver.setServers(['1.1.1.1']);
resolver.resolve(name, "A", (err, records) => {
console.log(records);
});
})();
It results in:
Packet {
header: {
id: 3559,
qr: 1,
opcode: 0,
aa: 0,
tc: 0,
rd: 0,
ra: 1,
z: 0,
rcode: 2,
qdcount: 1,
nscount: 0,
arcount: 0,
ancount: 0
},
questions: [ { name: 'avatars3.githubusercontent.com', type: 1, class: 1 } ],
answers: [],
authorities: [],
additionals: []
}
[
'151.101.128.133',
'151.101.64.133',
'151.101.0.133',
'151.101.192.133'
]
As you can see, when running the command through the native Node.js DNS client I get 4 answers back, whereas when running it through dns2
I get 0 answers back in the array.
It looks like part of the problem is the ancount
is 0 for some reason. The rcode
is also 2. Which according to the spec means:
Server failure - The name server was unable to process this query due to a problem with the name server.
However, this doesn't make sense. I'm hitting the same name server (1.1.1.1) for both the native Node.js DNS client (where it's obviously successful), and the dns2
query.
Is there a problem with the request being made in dns2
where the name server can't understand it? Or is there a problem with parsing the response in dns2
?
Any ideas what is going on here?
I will also mention, this issue occurs the majority of the time. But every once in a while (rarely). It succeeds and works just fine (with no code changes on my part).
EDNS Client Subnet support does not work because the call to resolve
in query
is malformed.
query
Line 46 in b2fdf66
resolve
Line 9 in b2fdf66
The fixed call should be:
return resolve(name, type, cls, { clientIp, recursive });
I cannot get ECS to work even after this change. Entering the same CDN domain but with one clientIp
in Europe and another in the USA, I get the same resolved IP address. This is with both Google's DNS (8.8.8.8) as well as Quad9's ECS-enabled DNS (9.9.9.11).
If I use Resolve-DnsName
or dig
then the same CDN domain's resolved IP changes depending on the provided subnet / source IP address.
The above is why I've opted to raise an issue and not a PR, as I do not know how to fix the underlying ECS support.
I noticed that quite a few bigger commits have happened since the last npm publication.
What is your criteria for publishing the npm package?
When running the following code I'm having an issue where the responses don't match the dig
command.
(async () => {
const DNS = require('dns2');
const dns = new DNS({"nameServers": ["1.1.1.1"], "retries": 1});
console.log(await dns.resolve("vod-ap1-aoc.tv.apple.com", 1, 1));
})();
charliefish@Charlies-MacBook-Pro tmp % node index.js
Packet {
header: {
id: 7626,
qr: 1,
opcode: 0,
aa: 0,
tc: 0,
rd: 1,
ra: 1,
z: 0,
rcode: 0,
qdcount: 1,
nscount: 1,
arcount: 0,
ancount: 1
},
questions: [ { name: 'vod-ap1-aoc.tv.apple.com', type: 0, class: 1 } ],
answers: [
{
name: 'vod-ap1-aoc.tv.apple.com',
ttl: 3571,
type: 5,
class: 1,
domain: 'vod-ap1-aoc-aec.tv.g.apple.com'
}
],
authorities: [
{
name: 'vod-ap1-aoc-aec.tv.g.apple.com',
ttl: 271,
type: 6,
class: 1,
primary: 'v1.gslb.aaplimg.com',
admin: 'hostmaster.apple.com',
serial: 1622748988,
refresh: 1800,
retry: 300,
expiration: 60480,
minimum: 300
}
],
additionals: []
}
charliefish@Charlies-MacBook-Pro tmp % dig @1.1.1.1 vod-ap1-aoc.tv.apple.com
; <<>> DiG 9.10.6 <<>> @1.1.1.1 vod-ap1-aoc.tv.apple.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63692
;; flags: qr rd ra; QUERY: 1, ANSWER: 16, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;vod-ap1-aoc.tv.apple.com. IN A
;; ANSWER SECTION:
vod-ap1-aoc.tv.apple.com. 3589 IN CNAME vod-ap1-aoc-aec.tv.g.apple.com.
vod-ap1-aoc-aec.tv.g.apple.com. 229 IN CNAME vod-ap-aoc.tv.apple.com.
vod-ap-aoc.tv.apple.com. 86389 IN CNAME vod-ap-aoc.tv.apple.com.akadns.net.
vod-ap-aoc.tv.apple.com.akadns.net. 49 IN CNAME hls-svod-aoc-ve.itunes.g.aaplimg.com.
hls-svod-aoc-ve.itunes.g.aaplimg.com. 4 IN CNAME hls-svod-aoc-us-lb.itunes-apple.com.akadns.net.
hls-svod-aoc-us-lb.itunes-apple.com.akadns.net. 19 IN CNAME hls-svod-aoc.itunes.apple.com.edgesuite.net.
hls-svod-aoc.itunes.apple.com.edgesuite.net. 21589 IN CNAME a1936.dscw11.akamai.net.
a1936.dscw11.akamai.net. 9 IN A 23.62.236.113
a1936.dscw11.akamai.net. 9 IN A 23.62.236.19
a1936.dscw11.akamai.net. 9 IN A 23.62.236.97
a1936.dscw11.akamai.net. 9 IN A 23.62.236.67
a1936.dscw11.akamai.net. 9 IN A 23.62.236.121
a1936.dscw11.akamai.net. 9 IN A 23.62.236.11
a1936.dscw11.akamai.net. 9 IN A 23.62.236.123
a1936.dscw11.akamai.net. 9 IN A 23.62.236.8
a1936.dscw11.akamai.net. 9 IN A 23.62.236.10
;; Query time: 18 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Sat Jun 12 22:12:09 MDT 2021
;; MSG SIZE rcvd: 699
charliefish@Charlies-MacBook-Pro tmp %
As you can see the dig
command gives 16 answers, however the dns2 code does not.
Any ideas what could be causing this?
udp4 is currently hardcoded in the udp.js
. It cannot be accessed udp via IPv6 address.
Lines 9 to 11 in b2e994c
createResolver is broken in master branch
If i want to resolve a dns attribute using the current master branch, it throw this error :
/code/eviltik/node-dns/index.js:46
const resolve = createResolver({ dns: address, port });
^
TypeError: createResolver is not a function
at /code/eviltik/node-dns/index.js:46:23
at Array.map (<anonymous>)
at DNS.query (/code/eviltik/node-dns/index.js:45:37)
at DNS.resolve (/code/eviltik/node-dns/index.js:57:17)
at DNS.resolveCNAME (/code/eviltik/node-dns/index.js:69:17)
.....
CreateResolver is created here
Line 39 in 182d88e
Everything was OK before DoH Server implementation (#26)
Lines 76 to 79 in 452ab97
After DoH Server implementation, no more udp client by default
Lines 79 to 82 in 182d88e
Except if i'm missing something, we have no option to choose which Client we want (DOH, TCP, UDP, Google) to use for resolver.
I'd like to suggest a new config option for solve it, but not sure it's the way to go : a new config option and a code change
const Dns2 = require('dns2');
const dns2 = new Dns2({
resolverProtocol:'UDP' // or TCP, DOH, Google
});
I'd like to purpose a PR, but my coding style does not match with the current one.
In the idea :
class DNS extends EventEmitter {
constructor(options) {
super();
Object.assign(this, {
port: 53,
resolverProtocol:'UDP' // new option
...........................
---------------------------
query(name, type, cls, clientIp) {
const { port, nameServers, resolverProtocol } = this;
// Choose the good Client
if (resolverProtocol === 'TCP') {
const{ ClientUDP: createResolver } = DNS;
} else if (resolverProtocol === 'TCP') {
const{ ClientTCP: createResolver } = DNS;
} .......
@DSorlov, @song940, what do you think ?
Thank you
It's not clear how a status of NXDOMAIN should be returned (see https://serverfault.com/questions/373629/what-is-the-correct-response-for-a-dns-server-when-a-domain-does-not-exist).
Is this not possible in the current implementation?
I dont see where i can answer with nox existant domain
Version 1.4.2 to 1.4.3 included breaking changes, but was designated as a patch version. See this commit from @DSorlov: 6437180. Many functions and things were renamed, which is considered a breaking change according to SEMVER.
@song940 Why was the version number not bumped to 2.0.0 after this commit?
Is there any way to close the UDP socket after I'm done with the client class instance?
Any destroy()/dispose() method of some kind?
Hi,
i have developed a small demo based on your example like seen here:
const udp = require('dgram');
const dns = require('dns2');
const Packet = dns.Packet;
let rip=null;
let localPort=53;
var server = dns.createServer(function(request, send){
var query = request.questions[0].name;
console.log('> request %s', query);
var response = new Packet(request);
response.header.qr = 1;
response.header.ra = 1;
console.log('a');
response.answers.push({
name: query,
type: Packet.TYPE.A,
class: Packet.CLASS.IN,
ttl: 300,
address: rip
});
console.log('b');
send(response);
});
require('dns').resolve4('ip8s.com',(err,addr)=>{
if (err) {
console.log(err.stack);
process.exit(1);
}
rip=addr.shift();
console.log('Will respond '+rip);
server.listen(localPort,()=>{
console.log("Server has been started at port *:"+localPort);
});
});
I do run 9.2.1 on mac pro, everything seems to work fine. But i do get
node-dns > unknow encoder undefined(41) node-dns > unknow parser type: undefined(41)
on node 4/6/8. I have not tried node9 on that ubuntu 16 machine. Is that just a requirement issue or some other problem on my side please?
As I am now endeavouring to add a number of features that I personally need and also wish to contribute back I wanted to rename some in the class DNS such as:
This also aligns more closely with the server naming and allows for furthering the features and methods available. This would also involve updating examples and the actual class names inside each client. Any thoughts on this?
I have created an example of this based on my already open PR to show what I mean. Hope that clarifies a bit.
When running the following code:
const DNS = require('dns2');
(async () => {
const result1 = await DNS.DOHClient({"dns": "1.1.1.1"})("rrainn.com", "A", 1);
const result2 = await new DNS({"nameserver": ["1.1.1.1"]}).resolve("rrainn.com", "A", 1);
console.log(result1);
console.log(result2);
})();
I get the following output:
charliefish@Charlies-MacBook-Pro tmp2 % node index.js
Packet {
header: {
id: 0,
qr: 1,
opcode: 0,
aa: 0,
tc: 0,
rd: 0,
ra: 1,
z: 0,
rcode: 2,
qdcount: 1,
nscount: 0,
arcount: 0,
ancount: 0
},
questions: [ { name: 'rrainn.com', type: 1, class: 1 } ],
answers: [],
authorities: [],
additionals: []
}
Packet {
header: {
id: 3827,
qr: 1,
opcode: 0,
aa: 0,
tc: 0,
rd: 1,
ra: 1,
z: 0,
rcode: 0,
qdcount: 1,
nscount: 0,
arcount: 0,
ancount: 2
},
questions: [ { name: 'rrainn.com', type: 1, class: 1 } ],
answers: [
{
name: 'rrainn.com',
ttl: 132,
type: 1,
class: 1,
address: '172.67.141.137'
},
{
name: 'rrainn.com',
ttl: 132,
type: 1,
class: 1,
address: '104.21.79.36'
}
],
authorities: [],
additionals: []
}
As you can see, for the DOH Client I get no answers back. Which is incorrect. Also the headers have different values. The code should print identical objects.
Hi song940,
was searching around for a node based DNS server, and found this.
What I really want is some simple Node code which would respond with records for DNS01 AMCE challenges from LetsEncrypt.
E.g. I found
https://github.com/krtab/agnos
but want to do it in node.
Has anyone suggested this use case to you?
br,
Simon
my code:
const dns2 = require('dns2');
const chalk = require('chalk');
const { Packet } = dns2;
var port = process.env['SERVER_PORT'];
if (!port) {
console.log(chalk.yellow(`\t'SERVER_PORT' env variable not found, using port of config: ${53}`))
port = 53;
}
const server = dns2.createServer({
udp: true,
tcp: true,
handle: (request, send, rinfo) => {
const response = Packet.createResponseFromRequest(request);
const [ question ] = request.questions;
const { name } = question;
response.answers.push({
name,
type: Packet.TYPE.A,
class: Packet.CLASS.IN,
ttl: 300,
address: '8.8.8.8'
});
send(response);
}
});
server.on('request', (request, response, rinfo) => {
console.log(request.header.id, request.questions[0]);
});
server.on('requestError', (error) => {
console.log('Client sent an invalid request', error);
});
server.on('listening', () => {
console.log(server.addresses());
});
server.on('close', () => {
console.log('server closed');
});
server.listen({
// Optionally specify port, address and/or the family of socket() for udp server:
udp: {
port: port,
address: "0.0.0.0",
type: "udp4", // IPv4 or IPv6 (Must be either "udp4" or "udp6")
},
// Optionally specify port and/or address for tcp server:
tcp: {
port: port,
address: "0.0.0.0",
},
});
// eventually
server.close();
logs:
Action reload started
Action reload completed
'SERVER_PORT' env variable not found, using port of config: 53
server closed
Client sent an invalid request RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: Attempt to write outside buffer bounds
at boundsError (internal/buffer.js:47:11)
at Buffer.readUInt8 (internal/buffer.js:137:5)
at Function.BufferReader.read (/var/lib/pterodactyl/volumes/d09a0f8c-ede3-4ae8-9dd0-6f423af44b74/node_modules/dns2/lib/reader.js:38:24)
at BufferReader.read (/var/lib/pterodactyl/volumes/d09a0f8c-ede3-4ae8-9dd0-6f423af44b74/node_modules/dns2/lib/reader.js:48:28)
at Function.Packet.Header.parse (/var/lib/pterodactyl/volumes/d09a0f8c-ede3-4ae8-9dd0-6f423af44b74/node_modules/dns2/packet.js:219:22)
at Function.Packet.parse (/var/lib/pterodactyl/volumes/d09a0f8c-ede3-4ae8-9dd0-6f423af44b74/node_modules/dns2/packet.js:121:33)
at Server.handle (/var/lib/pterodactyl/volumes/d09a0f8c-ede3-4ae8-9dd0-6f423af44b74/node_modules/dns2/server/tcp.js:16:30)
at process._tickCallback (internal/process/next_tick.js:68:7)
'path' is not defined error when using createDOHServer(options)
The following readStream
function is the culprit:
Lines 22 to 28 in b2fdf66
It's initialising the buffer as a string and not converting it for the resolve()
call.
It should be:
const readStream = stream => new Promise((resolve, reject) => {
let buffer = '';
stream
.on('error', reject)
.on('data', chunk => { buffer += chunk; })
.on('end', () => resolve(Buffer.from(buffer)));
});
Hello,
When i execute : "dig wbc.weble.ch +trace"
I've this result :
; <<>> DiG 9.10.3-P4-Raspbian <<>> wbc.weble.ch +trace
;; global options: +cmd
. 72776 IN NS e.root-servers.net.
. 72776 IN NS f.root-servers.net.
. 72776 IN NS g.root-servers.net.
. 72776 IN NS h.root-servers.net.
. 72776 IN NS i.root-servers.net.
. 72776 IN NS j.root-servers.net.
. 72776 IN NS k.root-servers.net.
. 72776 IN NS l.root-servers.net.
. 72776 IN NS m.root-servers.net.
. 72776 IN NS a.root-servers.net.
. 72776 IN NS b.root-servers.net.
. 72776 IN NS c.root-servers.net.
. 72776 IN NS d.root-servers.net.
;; Received 811 bytes from 172.16.1.1#53(172.16.1.1) in 3 ms
ch. 172800 IN NS a.nic.ch.
ch. 172800 IN NS b.nic.ch.
ch. 172800 IN NS c.nic.ch.
ch. 172800 IN NS d.nic.ch.
ch. 172800 IN NS e.nic.ch.
ch. 172800 IN NS f.nic.ch.
ch. 172800 IN NS g.nic.ch.
ch. 172800 IN NS h.nic.ch.
ch. 86400 IN DS 11896 13 2 24EE6537B1C452D3AEBF439DCF74024717054152DA7F206D5FCBA1A9 0F70711F
ch. 86400 IN RRSIG DS 8 1 86400 20190930050000 20190917040000 59944 . kaGRIHYMMuruHaWAIHb9kVXZNH9tzDNkqgQcX9oFotbd86puoY6/sRp6 +y8lhBxUgm7qi7GM3JxTZ3iZ3/dpgNv7PTVLskDUwrscSQC5jkxzOzvB 5oo59keBmC9X2UlJ+rLJoLNLNuao+6LyMPZtSgW7DudvN1rMQpZM39is XuG5URCG9qSBzkJt3FPESMBT+h356sbvN4Jz8GvwPLaE2mpdNnuBwAIG qBYaqDiWhE0pLuSVwdLlPftCnJ7RT1dNfTI3wJfSl2fDI6TpHPgr8bSt 4H5HDutqvsZuTQp1p2CqKLtAJOCIKBPOfact7SyYaVFlmuqhQMZLwFDP UnZDiQ==
;; Received 860 bytes from 193.0.14.129#53(k.root-servers.net) in 11 ms
weble.ch. 3600 IN NS ns1.switchplus.ch.
weble.ch. 3600 IN NS ns2.switchplus.ch.
HS53IQDLBM00MIRD1LPS0J47BPJP5SF8.ch. 900 IN NSEC3 1 1 2 87E195EB HS63KNDB8F15206UBJQDIRIISQ1EK7N7 NS SOA RRSIG DNSKEY NSEC3PARAM
HS53IQDLBM00MIRD1LPS0J47BPJP5SF8.ch. 900 IN RRSIG NSEC3 13 2 900 20191013161405 20190913160114 7967 ch. GZsRnHBemsdnY1WI6R9+O9NjL9a7s479t3Oqcw6j28LVsYZWOjqUPnSK bjRHaSKp4hZrtxX9gMzIRAJChgL3AQ==
LBHUG80GC3VGPEU435F60L91DBJ3LJE8.ch. 900 IN NSEC3 1 1 2 87E195EB LBK2U02LTLKUCOCKTKJG1O2EMMOK0HBB NS DS RRSIG
LBHUG80GC3VGPEU435F60L91DBJ3LJE8.ch. 900 IN RRSIG NSEC3 13 2 900 20191010205442 20190911113001 7967 ch. UdhiNXu1UZx2JE1qg/WI+I51OMtCanyanuqtArGcuMc+GyFZR7NeLK9l GpMKl5wmdz3EDm+TL+y8X7XWncNf8w==
;; Received 487 bytes from 194.146.106.10#53(f.nic.ch) in 13 ms
wbc.weble.ch. 3600 IN NS ns1.weble.ch.
wbc.weble.ch. 3600 IN NS ns2.weble.ch.
;; Received 109 bytes from 193.223.77.3#53(ns2.switchplus.ch) in 119 ms
**;; Warning: Message parser reports malformed message packet.**
wbc.weble.ch. 300 IN A 213.193.121.210
;; Received 67 bytes from 213.193.121.211#53(ns1.weble.ch) in 31 ms
Here the response object :
var response = new dns.Packet(request);
response.header.qr = 1;
response.answers.push({
name: oDomain,
address: target.target,
type : dns.Packet.TYPE.A,
ttl : ttl,
class : dns.Packet.CLASS.IN
});
Is there a link between this error and the warning ;; Warning: Message parser reports malformed message packet. ?
Is there something wrong ?
Hey @song940 first, great project!
Can you perhaps give all sockets the proxy protocol header? I would like to give the real client IP from the proxy. That the DNS server gets the correct IP from the client.
https://github.com/moznion/proxy-protocol-js
I imagined it in such a way that you can specify in the config whether you use it or not.
It should be enough to read the sockets and parse the header first before parsing the packets:
const proto = proxyProtocol.V1ProxyProtocol.parse(dnspacket);
console.log(proto);
// => V1ProxyProtocol {
// inetProtocol: 'TCP4',
// source: Host { ipAddress: '127.0.0.1', port: 12345 },
// destination: Host { ipAddress: '192.0.2.1', port: 54321 },
// data: '' }
const dnsrequest = proto.data
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.