Incorrect DNS status code

780 views
Skip to first unread message

smf

unread,
Jan 31, 2013, 1:51:55 PM1/31/13
to nod...@googlegroups.com
Hi,

Does anyone know what Node returns ECONNREFUSED insetad of ESERVFAIL for DNS queries that return SERVFAIL?

[root@mail1-ec2 ~]# dig servfail.test.snert.net

; <<>> DiG 9.7.3-P3-RedHat-9.7.3-2.11.amzn1 <<>> servfail.test.snert.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 51175
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Jan 31 18:49:40 2013
;; MSG SIZE  rcvd: 41


[root@mail1-ec2 ~]# cat a.js
var dns = require('dns');
dns.resolve4('servfail.test.snert.net', function (err, res) {
    if (err) {
        console.log(err);
    }
    else {
        console.log(res);
    }
});

[root@mail1-ec2 ~]# node a.js
{ [Error: queryA ECONNREFUSED]
  code: 'ECONNREFUSED',
  errno: 'ECONNREFUSED',
  syscall: 'queryA' }

Kind regards,
Steve.

Ben Noordhuis

unread,
Jan 31, 2013, 2:10:21 PM1/31/13
to nod...@googlegroups.com
Not sure, it seems to work for me:

$ out/Release/node tmp/dns-econn.js
{ [Error: queryA ENOTFOUND] code: 'ENOTFOUND', errno: 'ENOTFOUND',
syscall: 'queryA' }

The error code is ENOTFOUND for backwards compatibility but
essentially means NXDOMAIN (which is what dig returns for that
domain).

Maybe run strace on the script to see what it's doing.

Steve Freegard

unread,
Jan 31, 2013, 4:38:49 PM1/31/13
to nod...@googlegroups.com
Hi Ben,


On Thursday, 31 January 2013 19:10:21 UTC, Ben Noordhuis wrote:

Not sure, it seems to work for me:

  $ out/Release/node tmp/dns-econn.js
  { [Error: queryA ENOTFOUND] code: 'ENOTFOUND', errno: 'ENOTFOUND',
syscall: 'queryA' }

The error code is ENOTFOUND for backwards compatibility but
essentially means NXDOMAIN (which is what dig returns for that
domain).

Maybe run strace on the script to see what it's doing.


Can you try again with that hostname (servfail.test.snert.net) as this was only returning SERVFAIL for my IP at the time, we've since managed to break it properly for everyone ;-)

strace shows that packets are responded to and being as this is UDP - there's no connections being refused or any truncated data causing a TCP lookup:

     0.000218 connect(7, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
     0.000222 send(7, "Nx\1\0\0\1\0\0\0\0\0\0\10servfail\4test\5snert\3net\0\0\1\0\1", 41, MSG_NOSIGNAL) = 41
     0.000416 futex(0xb770046c, FUTEX_WAKE_PRIVATE, 1) = 1
     0.000264 epoll_ctl(3, EPOLL_CTL_ADD, 4, {EPOLLIN, {u32=4, u64=4294967300}}) = 0
     0.000147 epoll_ctl(3, EPOLL_CTL_ADD, 5, {EPOLLIN, {u32=5, u64=4294967301}}) = 0
     0.000141 epoll_ctl(3, EPOLL_CTL_ADD, 7, {EPOLLIN, {u32=7, u64=4294967303}}) = 0
     0.000168 epoll_wait(3, {{EPOLLIN, {u32=7, u64=4294967303}}}, 64, 0) = 1
     0.000207 clock_gettime(CLOCK_MONOTONIC, {18616500, 71519938}) = 0
     0.000183 recvfrom(7, "Nx\201\202\0\1\0\0\0\0\0\0\10servfail\4test\5snert\3net\0\0\1\0\1", 513, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, [16]) = 41
     0.000466 send(7, "Nx\1\0\0\1\0\0\0\0\0\0\10servfail\4test\5snert\3net\0\0\1\0\1", 41, MSG_NOSIGNAL) = 41
     0.000445 recvfrom(7, "Nx\201\202\0\1\0\0\0\0\0\0\10servfail\4test\5snert\3net\0\0\1\0\1", 513, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, [16]) = 41
     0.000506 send(7, "Nx\1\0\0\1\0\0\0\0\0\0\10servfail\4test\5snert\3net\0\0\1\0\1", 41, MSG_NOSIGNAL) = 41
     0.000860 recvfrom(7, 0xbf837b9f, 513, 0, 0xbf837da0, 0xbf837dbc) = -1 EAGAIN (Resource temporarily unavailable)
     0.000129 clock_gettime(CLOCK_MONOTONIC, {18616500, 74108425}) = 0
     0.000133 epoll_wait(3, {{EPOLLIN, {u32=7, u64=4294967303}}}, 64, 953) = 1
     0.107171 clock_gettime(CLOCK_MONOTONIC, {18616500, 181412884}) = 0
     0.000165 recvfrom(7, "Nx\201\202\0\1\0\0\0\0\0\0\10servfail\4test\5snert\3net\0\0\1\0\1", 513, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, [16]) = 41
     0.000449 send(7, "Nx\1\0\0\1\0\0\0\0\0\0\10servfail\4test\5snert\3net\0\0\1\0\1", 41, MSG_NOSIGNAL) = 41
     0.000431 recvfrom(7, "Nx\201\202\0\1\0\0\0\0\0\0\10servfail\4test\5snert\3net\0\0\1\0\1", 513, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, [16]) = 41
     0.000532 futex(0xb770046c, FUTEX_WAKE_PRIVATE, 1) = 1
     0.001138 ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
     0.001087 futex(0xb770046c, FUTEX_WAKE_PRIVATE, 1) = 1
     0.000390 ioctl(1, TIOCGWINSZ, {ws_row=32, ws_col=132, ws_xpixel=0, ws_ypixel=0}) = 0
     0.000336 rt_sigaction(SIGWINCH, {0x82003a0, ~[RTMIN RT_1], SA_RESTART}, NULL, 8) = 0
     0.000515 futex(0xb770046c, FUTEX_WAKE_PRIVATE, 1) = 1
     0.001139 futex(0xb770046c, FUTEX_WAKE_PRIVATE, 1) = 1
     0.000914 write(1, "{ [Error: queryA ECONNREFUSED]\n  code: 'ECONNREFUSED',\n  errno: 'ECONNREFUSED',\n  syscall: 'queryA' }\n", 102{ [Error: queryA ECONNREFUSED]
  code: 'ECONNREFUSED',
  errno: 'ECONNREFUSED',
  syscall: 'queryA' }
) = 102


Regards,
Steve.
 

Ben Noordhuis

unread,
Feb 1, 2013, 6:43:49 AM2/1/13
to nod...@googlegroups.com
Right, I can reproduce it now.

It seems to be a c-ares quirk (the DNS resolver library we use). If a
server replies with SERVFAIL, c-ares retries the query up to four
times, then gives up with an ARES_ECONNREFUSED error.

I don't think there is much we can do about that. Maybe you can bring
it up on the c-ares mailing list.

Steve Freegard

unread,
Feb 1, 2013, 10:01:27 AM2/1/13
to nod...@googlegroups.com
On Friday, 1 February 2013 11:43:49 UTC, Ben Noordhuis wrote:

Right, I can reproduce it now.

It seems to be a c-ares quirk (the DNS resolver library we use).  If a
server replies with SERVFAIL, c-ares retries the query up to four
times, then gives up with an ARES_ECONNREFUSED error.

I don't think there is much we can do about that.  Maybe you can bring
it up on the c-ares mailing list.


Ok - I've had a look through the c-ares documentation and found the cause of this,  basically SERVFAIL, NOTIMP, REFUSED and any mismatched questions are discarded by c-ares unless ares_init_options() is called with the ARES_FLAG_NOCHECKRESP flag set.   See http://c-ares.haxx.se/ares_init.html

I've no idea what they were thinking making this the default.  I can't see any benefit to this unless you have broken nameservers in /etc/resolv.conf.   In all other cases this is simply O(retries) overhead as you simply get the same result back for each retried query before receiving the ECONNREFUSED result.

I'd prefer to get the relevant error back immediately (which would also be 3x faster).

What do you think?

Regards,
Steve.

Ben Noordhuis

unread,
Feb 1, 2013, 12:10:58 PM2/1/13
to nod...@googlegroups.com
I've landed that in [1] (master only).

[1] https://github.com/joyent/node/commit/6aed61f

Steve Freegard

unread,
Feb 1, 2013, 1:08:38 PM2/1/13
to nod...@googlegroups.com
On Friday, 1 February 2013 17:10:58 UTC, Ben Noordhuis wrote:

I've landed that in [1] (master only).

[1] https://github.com/joyent/node/commit/6aed61f


Thanks Ben - I really appreciate it. 
Reply all
Reply to author
Forward
0 new messages