SRV lookup request doesn't return an IP address - linux

I am writing an XMPP client. The RFC says I need to connect to the server (like this one) using a SRV query.
When I use the trust_dns_resolver crate to do so, the query seems to be empty. Is this the normal behavior?
use trust_dns_resolver::Resolver;
use trust_dns_resolver::Name;
use std::str::FromStr;
fn main() {
let resolver = Resolver::from_system_conf().unwrap();
match resolver.srv_lookup(Name::from_str("_xmpp-client._tcp.xmpp.jp").unwrap()) {
Ok(response) => {
for ip in response.ip_iter() {
println!("{}", ip.to_string());
}
},
Err(e) => println!("{}", e),
}
}
The dig SRV _xmpp-client._tcp.xmpp.jp command line return the following:
; <<>> DiG 9.16.18 <<>> SRV _xmpp-client._tcp.xmpp.jp
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16710
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 2605a5d828b394e22ffbec3e61010461a668fc990570d859 (good)
;; QUESTION SECTION:
;_xmpp-client._tcp.xmpp.jp. IN SRV
;; ANSWER SECTION:
_xmpp-client._tcp.xmpp.jp. 23 IN SRV 20 10 5222 sapporo.xmpp.jp.
_xmpp-client._tcp.xmpp.jp. 23 IN SRV 30 10 5222 gw.lb.xmpp.jp.
_xmpp-client._tcp.xmpp.jp. 23 IN SRV 10 10 5222 tokyo.xmpp.jp.
;; Query time: 13 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: mer. juil. 28 09:16:49 CEST 2021
;; MSG SIZE rcvd: 183
I will have three IP addresses right ?
I think I'm misunderstanding something, but I don't know what.

It's ok if the SRV lookup return no IP address. in my case, the query return only few tuples composed of a domain name and a port number. After getting them, I have to resolve each one to get its IP address with its port number.
The trust_dns_proto crate is mandatory to deal with SRV lookup. So I add it to the Cargo.toml file, and the compiler stop crying...
Then I can write the following code to extract both port number and domain name:
use trust_dns_resolver::Resolver;
use trust_dns_resolver::Name;
use std::str::FromStr;
[...]
let resolver = Resolver::from_system_conf().unwrap();
match resolver.srv_lookup(Name::from_str("_xmpp-client._tcp.xmpp.jp.").unwrap()) {
Ok(response) => {
for srv in response.iter() {
println!("Port number:\t{}", srv.port());
println!("Domain name:\t{}\n", srv.target().to_utf8());
// have to resolve the domain name here
}
println!("{}", response.query().name());
},
Err(e) => println!("{}", e),
}
Thanks to Zeppi. His solution was far from perfect, but it put me on the right track to finding my own.

Related

why server can't find pihole.service.consul: NXDOMAIN and how can I fix this?

I have following configuration for consul.
{
"service": {
"name": "pihole",
"Address": "192.168.0.15",
"tags": [
"pi"
],
"port": 8165,
"check": {
"args": [
"curl",
"192.168.0.15"
],
"interval": "10s"
}
}
}
using dig i get no error now,
$ dig #127.0.0.1 -p 8600 pihole.service.consul
; <<>> DiG 9.9.7-P3 <<>> #127.0.0.1 -p 8600 pihole.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63573
;; 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: 4096
;; QUESTION SECTION:
;pihole.service.consul. IN A
;; ANSWER SECTION:
pihole.service.consul. 0 IN A 192.168.0.15
;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Sun Aug 30 23:02:34 BST 2020
;; MSG SIZE rcvd: 66
but when I do nslookup, i get the error server can't find pihole.service.consul: NXDOMAIN
$ nslookup pihole.service.consul
Server: 192.168.0.15
Address: 192.168.0.15#53
** server can't find pihole.service.consul: NXDOMAIN
I actually have a pihole running at this ip address 192.168.0.15
on the consul health check is passing.
2020-08-30T23:10:58.707+0100 [DEBUG] agent: Check status updated: check=service:pihole status=passing
In the command dig #127.0.0.1 -p 8600 pihole.service.consul you explicitly instructed host to use server 127.0.0.1 and port 8600.
Nslookup uses nameserver from your /etc/resolv.conf file and port 53 by default.
You can try
nslookup pihole.service.consul 127.0.0.1 -port=8600

Node.js I can't resolve TXT record

I have an question about dns.resolveTxt.
https://nodejs.org/api/dns.html#dns_dns_resolvetxt_hostname_callback
Basically I can resolve TXT record, but for specific DNS zone, I can't resolve TXT record. For example, microsoft.com and so on.
I wrote the following code.
var dns = require('dns');
dns.resolveTxt('microsoft.com', (err, record) => {
console.log(record);
});
Does any one know the issue?
import * as dns from "dns";
dns.resolveTxt('microsoft.com', (err, addresses) => {
console.log(JSON.stringify(addresses));
});
outputs
[["v=spf1 include:_spf-a.microsoft.com include:_spf-b.microsoft.com include:_spf-c.microsoft.com include:_spf-ssg-a.microsoft.com include:spf-a.hotmail.com include:_spf1-meo.microsoft.com -all"],["d365mktkey=3uc1cf82cpv750lzk70v9bvf2"]
,["adobe-idp-site-verification=8aa35c528af5d72beb19b1bd3ed9b86d87ea7f24b2ba3c99ffcd00c27e9d809c"],["fg2t0gov9424p2tdcuo94goe9j"],["apple-domain-verification=0gMeaYyYy6GLViGo"],["d365mktkey=4d8bnycx40fy3581petta4gsf"],["docusign=d5a3737
c-c23c-4bd0-9095-d2ff621f2840"],["adobe-sign-verification=c1fea9b4cdd4df0d5778517f29e0934"],["google-site-verification=Zv1IvEEZg4N9wbEXpBSSyAiIjDyyB3S-fzfFClb7D1E"],["google-site-verification=8-zFCaUXhhPcvN29EVw2RvtASDCaDPQ02L1HJ8Om8I0
"],["google-site-verification=pjPOauSPcrfXOZS9jnPPa5axowcHGCDAl1_86dCqFpk"],["google-site-verification=1TeK8q0OziFl4T1tF-QR65JkzHZ1rcdgNccDFp78iTk"],["8RPDXjBzBS9tu7Pbysu7qCACrwXPoDV8ZtLfthTnC4y9VJFLd84it5sQlEITgSLJ4KOIA8pBZxmyvPujuUvh
Og=="],["docusign=52998482-393d-46f7-95d4-15ac6509bfdd"],["facebook-domain-verification=fwzwhbbzwmg5fzgotc2go51olc3566"]]
So, clearly seems to work fine.
The problem is DNS results over 512 bytes long. As near as I can tell, Node's dns.resolve* functions do not support EDNS, which allows up to 4096 byte responses, at least as of Node 14. Given this code:
const { Resolver } = require('dns');
const dns = new Resolver();
dns.resolveTxt(process.argv[2], (err, res) => {
if (err) {
console.log(err);
} else {
console.log(res);
}
});
I get this result:
$ node dns-test2.js google.com
Error: queryTxt ESERVFAIL google.com
at QueryReqWrap.onresolve [as oncomplete] (dns.js:206:19) {
errno: undefined,
code: 'ESERVFAIL',
syscall: 'queryTxt',
hostname: 'google.com'
}
And you can see that dig returns 715 bytes for the same query:
$ dig TXT google.com
; <<>> DiG 9.10.3-P4-Debian <<>> TXT google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32543
;; flags: qr rd ra; QUERY: 1, ANSWER: 9, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;google.com. IN TXT
;; ANSWER SECTION:
google.com. 30 IN TXT "google-site-verification=TV9-DBe4R80X4v0M4U_bd_J9cpOJM0nikft0jAgjmsQ"
google.com. 30 IN TXT "v=spf1 include:_spf.google.com ~all"
google.com. 30 IN TXT "docusign=1b0a6754-49b1-4db5-8540-d2c12664b289"
google.com. 30 IN TXT "globalsign-smime-dv=CDYX+XFHUw2wml6/Gb8+59BsH31KzUr6c1l2BPvqKX8="
google.com. 30 IN TXT "google-site-verification=wD8N7i1JTNTkezJ49swvWW48f8_9xveREV4oB-0Hf5o"
google.com. 30 IN TXT "facebook-domain-verification=22rm551cu4k0ab0bxsw536tlds4h95"
google.com. 30 IN TXT "docusign=05958488-4752-4ef2-95eb-aa7ba8a3bd0e"
google.com. 30 IN TXT "apple-domain-verification=30afIBcvSuDV2PLX"
google.com. 30 IN TXT "MS=E4A68B9AB2BB9670BCE15412F62916164C0B20BB"
;; Query time: 4 msec
;; SERVER: 10.0.0.10#53(10.0.0.10)
;; WHEN: Fri Sep 10 21:02:16 UTC 2021
;; MSG SIZE rcvd: 715
Running tcpdump, I see that the node query does not include the UDPsize=4096 option:
TXT? google.com. (28)
Whereas the dig request does:
TXT? google.com. ar: . OPT UDPsize=4096 (39)
A similar query for a TXT record that only returns 244 bytes works fine:
$ node dns-test2.js partechgss.com
[
[ 'ryb3spm2r33rtxl189nqs5n41xxrzmlz' ],
[ 'v=spf1 include:_spf.google.com ~all' ],
[ 'MS=ms32721923' ],
[ 'MS=ms56152555' ]
]
$ dig TXT partechgss.com
; <<>> DiG 9.10.3-P4-Debian <<>> TXT partechgss.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56392
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;partechgss.com. IN TXT
;; ANSWER SECTION:
partechgss.com. 30 IN TXT "MS=ms56152555"
partechgss.com. 30 IN TXT "MS=ms32721923"
partechgss.com. 30 IN TXT "v=spf1 include:_spf.google.com ~all"
partechgss.com. 30 IN TXT "ryb3spm2r33rtxl189nqs5n41xxrzmlz"
;; Query time: 14 msec
;; SERVER: 10.0.0.10#53(10.0.0.10)
;; WHEN: Fri Sep 10 21:15:21 UTC 2021
;; MSG SIZE rcvd: 244
Unfortunately, having identified the problem, I have yet to find a solution. I've opened a bug report against the node.js project on github.

"dig domain_name" is working only locally. What's wrong with configuration?

I have configured bind9 on ubuntu 16.04 server, on our local network.
dig legalact.uz returns follows:
; <<>> DiG 9.10.3-P4-Ubuntu <<>> legalact.uz
;; global options: +cmd
;; Got answer:x
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27505
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;legalact.uz. IN A
;; ANSWER SECTION:
legalact.uz. 604800 IN A 46.255.68.41
;; AUTHORITY SECTION:
legalact.uz. 604800 IN NS ns.legalact.uz.
;; ADDITIONAL SECTION:
ns.legalact.uz. 604800 IN A 46.255.68.41
;; Query time: 0 msec
;; SERVER: 192.168.1.107#53(192.168.1.107)
;; WHEN: Mon Jan 16 10:30:44 +05 2017
;; MSG SIZE rcvd: 89
But if I try dig legalact.uz from another network, it returns following answer:
; <<>> DiG 9.10.3-P4-Ubuntu <<>> leagalact.uz
;; global options: +cmd
;; connection timed out; no servers could be reached
dig #46.255.68.41 legalact.uz returns correct answer:
; <<>> DiG 9.10.3-P4-Ubuntu <<>> #46.255.68.41 legalact.uz
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40237
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;legalact.uz. IN A
;; ANSWER SECTION:
legalact.uz. 604800 IN A 46.255.68.41
;; AUTHORITY SECTION:
legalact.uz. 604800 IN NS ns.legalact.uz.
;; ADDITIONAL SECTION:
ns.legalact.uz. 604800 IN A 46.255.68.41
;; Query time: 48 msec
;; SERVER: 46.255.68.41#53(46.255.68.41)
;; WHEN: Mon Jan 16 10:51:25 +05 2017
;; MSG SIZE rcvd: 89
Here is my configuration files:
named.conf
include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";
named.conf.local
zone "legalact.uz" {
type master;
file "/etc/bind/zones/db.legalact.uz";
allow-query { any; };
};
zone "68.255.46.in-addr.arpa" {
type master;
file "/etc/bind/zones/db.46";
allow-query { any; };
};
named.conf.options
options {
directory "/var/cache/bind";
forwarders {
8.8.8.8;
8.8.4.4;
};
listen-on { any; };
dnssec-enable yes;
dnssec-validation yes;
recursion yes;
forward only;
auth-nxdomain yes; # conform to RFC1035
listen-on-v6 { any; };
allow-query { any; };
};
db.46
$TTL 604800
# IN SOA ns.legalact.uz. admin.legalact.uz. (
1 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
# IN NS ns.legalact.uz.
41 IN PTR legalact.uz.
db.legalact.uz
$TTL 604800
# IN SOA ns.legalact.uz. admin.legalact.uz. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;dnsserver
# IN NS ns.legalact.uz.
# IN A 46.255.68.41
ns IN A 46.255.68.41
If we ask the UZ servers who is authoritative for legalact.uz, they say...
sarnath:~% dig ns legalact.uz #ns.uz.
; <<>> DiG 9.11.0-P2 <<>> ns legalact.uz #ns.uz.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11032
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;legalact.uz. IN NS
;; AUTHORITY SECTION:
legalact.uz. 14400 IN NS ns1.activeby.net.
legalact.uz. 14400 IN NS ns2.activeby.net.
;; Query time: 90 msec
;; SERVER: 91.212.89.8#53(91.212.89.8)
;; WHEN: Mon Jan 16 09:14:18 CET 2017
;; MSG SIZE rcvd: 88
Looking closer at the two activeby.net servers, they give SERVFAIL for your domain name and they don't seem to have the IP addresses you use in your configuration example. So it looks like you need to contact your registrar to have them update the delegation information at the UZ level. Until your own servers are pointed out there, it doesn't matter how well you configure your name servers, since nobody will know that they should talk to them.

Why does Mesos-DNS not provide a SRV answer?

I have a vagrant box which is running Mesos, Marathon and Chronos (publicly packaged as playa-mesos). It is a sane environment (I have customized to a 192.168.. ip address though) and I can launch different apps incl. docker containerized ones.
I have tried a new demo, where there is a DNS requirement and the mesos application launch definition is as below :
{
"id": "mesos-dns",
"instances": 1,
"cpus": 0.2,
"mem": 50,
"cmd": "/mesos-dns -config=/config.json",
"container": {
"type": "DOCKER",
"docker": {
"image": "mesosphere/mesos-dns:latest",
"network": "HOST"
},
"volumes": [
{
"containerPath": "/config.json",
"hostPath": "/etc/mesos-dns/config.json",
"mode": "RO"
}
]
}
}
The config.json is as under :
{
"zk": "zk://127.0.0.1:2181/mesos",
"refreshSeconds": 60,
"ttl": 60,
"domain": "mesos",
"port": 53,
"resolvers": ["10.0.2.3"],
"timeout": 5,
"email": "root.mesos-dns.mesos"
}
The /etc/resolv.conf contains nameserver 10.0.2.3
Below is the dig response I get to my DNS query; both are shown below :-
dig _webdis-site-m-shop._tcp.marathon.mesos SRV
; <<>> DiG 9.9.5-3ubuntu0.1-Ubuntu <<>> _webdis-site-m-shop._tcp.marathon.mesos SRV
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 4759
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 8192
;; QUESTION SECTION:
;_webdis-site-m-shop._tcp.marathon.mesos. IN SRV
;; AUTHORITY SECTION:
. 56521 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2016021800 1
800 900 604800 86400
;; Query time: 155 msec
;; SERVER: 10.0.2.3#53(10.0.2.3)
;; WHEN: Thu Feb 18 13:38:21 UTC 2016
;; MSG SIZE rcvd: 143`
As you can see there is no ANSWER and the status NXDOMAIN means that this query resulted in a non-existent domain.
Can someone help me fix this ?
TIA.
This is now fixed. I have taken some thoughts from other posts on SO. I have changed the OOTB setting for ip address etc...
Broadly I added the 127.0.0.1 loopback ip addr, virtualbox generated ip addr (which in my case is 192.168.x.y) and retained the existing nameserver entry.
The results of the dig command is now :-
dig _webdis-site-m-shop._tcp.marathon.mesos SRV
; <<>> DiG 9.9.5-3ubuntu0.1-Ubuntu <<>> _webdis-site-m-shop._tcp.marathon.mesos SRV
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6284
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;_webdis-site-m-shop._tcp.marathon.mesos. IN SRV
;; ANSWER SECTION:
_webdis-site-m-shop._tcp.marathon.mesos. 60 IN SRV 0 0 31720 webdis-site-m-shop-39847-s0.marathon.mesos.
;; ADDITIONAL SECTION:
webdis-site-m-shop-39847-s0.marathon.mesos. 60 IN A 192.168.56.106
;; Query time: 2 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Feb 18 16:55:57 UTC 2016
;; MSG SIZE rcvd: 216

How can I read consul SRV records in my go application?

I am trying to implement consul for service discovery, and I am having trouble with two things: connecting to a custom DNS server, and formatting my net.LookupSRV() request.
Here is what I'm trying to look up from within my go app:
$ dig #127.0.0.1 -p 8600 serviceb.service.consul SRV
; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> #127.0.0.1 -p 8600 serviceb.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4511
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 2
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;serviceb.service.consul. IN SRV
;; ANSWER SECTION:
serviceb.service.consul. 0 IN SRV 1 1 80 az1-serviceb1.node.dc1.consul.
serviceb.service.consul. 0 IN SRV 1 1 80 az2-serviceb2.node.dc1.consul.
;; ADDITIONAL SECTION:
az1-serviceb1.node.dc1.consul. 0 IN A 10.6.41.22
az2-serviceb2.node.dc1.consul. 0 IN A 10.6.41.20
;; Query time: 6 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Fri May 16 15:09:28 2014
;; MSG SIZE rcvd: 275
and here is the relevant code. (I know it's wrong, but just so you can see what I'm trying to do)
cname, addrs, err := net.LookupSRV("serviceb", "service", "consul")
log.Printf("%+v %+v %+v", cname, addrs, err)
and the output:
2014/05/16 15:24:31 [] lookup _serviceb._service.consul: no such host
Any help would be appreciated! thanks
Try to use a more sharp tool such as the github.com/miekg/dns package. Last time I looked at it, it allowed to control virtually every bit of the client-side setup to do DNS resolution.
Consul does support strict RFC 2782 and lookup can be done using the standard library only:
resolver := &net.Resolver{
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
return (&net.Dialer{}).DialContext(ctx, network, "127.0.0.1:8600")
},
}
_, addrs, err := resolver.LookupSRV(
context.Background(), "svcname", "tcp", "consul",
)
While this doesn't answer your exact question, I find it's an easier way to access service data for greenfield apps.
It's quite easy to call the HTTP API with net/http:
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
resp, _ := http.Get("http://localhost:8500/v1/catalog/service/serviceb")
body, _ := ioutil.ReadAll(resp.Body)
fmt.Print(string(body))
}
The basics of the HTTP API are documented in the Services Guide.
The best way is to use PreparedQueries, as Posted here
import (
"fmt"
consulapi "github.com/hashicorp/consul/api"
)
func main() {
config := consulapi.DefaultConfig()
consul, err := consulapi.NewClient(config)
if err != nil {
fmt.Println(err)
}
preparedQuery := consul.PreparedQuery()
queryID, _, err := preparedQuery.Create(&consulapi.PreparedQueryDefinition{
Name: "DnsQuery",
Service: consulapi.ServiceQuery{
Service: "serviceb",
OnlyPassing: true,
},
}, &consulapi.WriteOptions{})
if err != nil {
fmt.Println(err)
}
res, _, _ := preparedQuery.Execute(queryID, &consulapi.QueryOptions{})
for _, node := range res.Nodes {
fmt.Println(node.Service.Address, node.Service.Port)
}

Resources