tungd / elixir-dns Goto Github PK
View Code? Open in Web Editor NEWDNS library for Elixir
License: BSD 3-Clause "New" or "Revised" License
DNS library for Elixir
License: BSD 3-Clause "New" or "Revised" License
I would like to return resource records whose types are not encoded by the Erlang library (such as LOC
). I can do the encoding myself but I don't know how to put this in a DNS.Resource. If I send a binary, DNS.Resource.to_record
complains. What is the proper way to do so and is it even possible?
Elixir-dns seems to work only with the previous century protocol. If I pass an IPv6 address to query()
, I get (Socket.Error) non-existing domain
. If I feed the data
of a %DNS.Resource
to query()
and it's IPv6, I have (Socket.Error) address family not supported by protocol family
.
Matching on :nxdomain would certainly be cooler than matching on 3.
I think my home WiFi net is secure, but tonight I upgraded my FarmBot OS to 6.4.11-beta and I'm seeing these wacky domains in the Logger output.
Aside from the effort of getting tcpdump going on a Nerves-based platform, how can I dig deeper ?
Thanks
[ Edit ] Sorry, on more thought, this is likely to be client code in FarmbotOS ( ?mDNS? ) causing these log records.
Please CLOSE this issue if you agree.
This looks like a bug in this project to me (?).
02:25:33.688 [error] GenServer Mdns.Server terminating
** (FunctionClauseError) no function clause matching in DNS.Resource.from_record/1
(dns) lib/dns/resource.ex:26: DNS.Resource.from_record({:dns_rr_opt, '.', :opt, 1440, 0, 0, 4500, <<0, 4, 0, 8, 0, 0, 76, 114, 185, 217, 99, 221>>})
(elixir) lib/enum.ex:1294: Enum."-map/2-lists^map/1-0-"/2
(elixir) lib/enum.ex:1294: Enum."-map/2-lists^map/1-0-"/2
(dns) lib/dns/record.ex:39: DNS.Record.from_record/1
(mdns) lib/mdns/server.ex:93: Mdns.Server.handle_packet/3
(mdns) lib/mdns/server.ex:89: Mdns.Server.handle_info/2
(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:711: :gen_server.handle_msg/6
Last message: {:udp, #Port<0.259>, {192, 168, 5, 3}, 5353, <<0, 0, 132, 0, 0, 0, 0, 18, 0, 0, 0, 0, 6, 77, 73, 78, 78, 73, 69, 9, 95, 110, 118, 115, 116, 114, 101, 97, 109, 4, 95, 116, 99, 112, 5, 108, 111, 99, 97, 108, 0, 0, 16, 128, 1, ...>>}
State: %Mdns.Server.State{ip: {192, 168, 5, 219}, services: [%Mdns.Server.Service{data: :ip, domain: "nerves-f447.local", ttl: 120, type: :a}], udp: #Port<0.259>}
This (arguably awesome) library currently only supports DNS lookups over UDP. This is acceptable for most use-cases of DNS. It is, however, very useful to have the ability to respond over TCP. This is useful in cases of, for example: zone transfers and DNSSEC. Therefore, implementing a TCP frontend as well, is a necessity.
Hi,
the version (0.0.3
) on hex doesn't yet have the socket
dependency, and therefore doesn't build. The master
version in this repo on the other hand does.
Do you think you could please push an updated version to hex
?
Thank you!
Sebastian
Mix.Config was deprecated since Elixir 1.9.0
This is possibly an issue with the underlying Socket library, instead of this one.
iex(1)> DNS.resolve("google.com")
** (FunctionClauseError) no function clause matching in anonymous fn/1 in Socket.arguments/1
lib/socket.ex:170: anonymous fn(:binary) in Socket.arguments/1
(elixir) lib/enum.ex:966: Enum.flat_map_list/2
(elixir) lib/enum.ex:967: Enum.flat_map_list/2
lib/socket/udp.ex:150: Socket.UDP.arguments/1
lib/socket/udp.ex:81: Socket.UDP.open/2
lib/socket/udp.ex:89: Socket.UDP.open!/2
lib/dns.ex:24: DNS.query/2
lib/dns.ex:10: DNS.resolve/2
using 0.0.4
, I get this for a simple dns resolve. Similar results for other urls.
Today, when the domain name does not exist, DNS.resolve()
returns {:error, :not_found}
. But it also returns the same when the name exists, but does not have the required type (DNS.resolve("github.com", :aaaa)
, for instance).
At the very least, this calls for two separate codes (something like {:error, :no_data}
but I would prefer {:ok, :no_data}
since it is not an error).
The only workaround seems to be using DNS.query()
, which is at a lower level.
The client can connect with TCP but the server only listens on UDP.
Dear Elixir-DNS,
Would it make sense to split this package into two? One with the passive code (structs and so on) and one with the more active code (server). Maybe the could be called dns-core and dns.
Pros:
Cons:
Kind regards
Niklas
I found the DNS server is using a module Socket
, but the module is not provided in this project.
Is that the package - socket on Hex.pm? If it is, why didn't we add it to deps?
Maybe, I can help to do this.
If you wish to add a list of the programs using your library (thanks!), you can add Drink, now publically available.
It would be nice to add support for parsing EDNS OPT record, and also to parse the options in it (cookie, NSID, etc). It does not seem there is support for that in the Erlang library. I added one in the Drink server (lib/drink/parsing.ex
), you're welcome to reuse the code if you want.
Using resolve/3
like so:
DNS.resolve("google.com", :a, {"not.a.dns.server.com", 53})
Results in the call hanging indefinitely (or at least appears to hang indefinitely). This can be corrected by using recv!/2
rather than recv!/1
with a timeout option here:
https://github.com/tungd/elixir-dns/blob/master/lib/dns.ex#L48
I forked and made this change for my own purposes for now (jdppettit@08c535a) but figured I'd raise the issue to see what folks think about doing something like this in master.
My use case here is a monitoring application where users supply the record to check as well as the DNS server to query.
Could you post a new release to hex.pm? The change to query different record types and the cleaned up warnings would be useful for another projects on hex. Thanks!
Calling :inet_dns.decode
results different dns_query
structure
Erlang 24.1.2
iex(1)> :inet_dns.decode(<<94, 236, 1, 32, 0, 1, 0, 0, 0, 0, 0, 1, 6, 110, 101, 114, 118, 101, 115, 5, 108, 111, 99, 97, 108, 0, 0, 1, 0, 1, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0>>)
{:ok,
{:dns_rec,
{:dns_header, 24300, false, :query, false, false, true, false, false, 0},
[{:dns_query, 'nerves.local', :a, :in}], [], [],
[{:dns_rr_opt, '.', :opt, 4096, 0, 0, 0, ""}]}}
Erlang 24.2.1
iex(1)> :inet_dns.decode(<<94, 236, 1, 32, 0, 1, 0, 0, 0, 0, 0, 1, 6, 110, 101, 114, 118, 101, 115, 5, 108, 111, 99, 97, 108, 0, 0, 1, 0, 1, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0>>)
{:ok,
{:dns_rec,
{:dns_header, 24300, false, :query, false, false, true, false, false, 0},
[{:dns_query, 'nerves.local', :a, :in, false}], [], [],
[{:dns_rr_opt, '.', :opt, 4096, 0, 0, 0, ""}]}}
Notice false
as 5th element of a tupple
It would be nice if the README could state that you need the Erlang/OTP source files to compile this library. On Ubuntu, without the erlang-src
package, I get the following error:
== Compilation error in file lib/dns/header.ex ==
** (RuntimeError) error parsing file /usr/lib/erlang/lib/kernel-5.4/src/inet_dns.hrl, got: {:error, :enoent}
because the src
directory is missing from the kernel application.
The library uses Erlang/OTP DNS code. I've been told that, if this Erlang code is undocumented, this is because it it no supposed to be used by external programs, but only by Erlang itself, for its internal use. Do you agree? Would it be better to develop specific code to be independent of Erlang?
When I follow the docs I get:
mix deps.get
** (Mix) No matching version for dns ~> 2.1.3 (from: mix.exs) in registry
The latest version is: 2.1.2
I've been playing with the examples, and from looking at the readme, it isn't clear how I would return a not found or server error return code to a request.
I think it would be helpful to have an example.
Thanks!
Why is the DNS.resolve and DNS.query contact information fixed to "8.8.8.8" in "lib/dns.ex"?
Some organizations and companies may not be able to use such DNS, and I feel that this is a problem.
I want to refer to the DNS used by the OS, what should I do?
Can we cut a current release that includes the compiler clean up? Thanks! :)
Hi, I was trying out this library and querying with dig,
for example:
$ dig @localhost -p 8000 facebook.com
;; Warning: query response not set
....
from reading online, it means I'm missing a field called QR
Where should I set it?
The outgoing DNS query ID is always zero, which removes a protection against some poisoning attempts (for instance a Kaminsky attack). This may not be an issue when querying a local resolver but more annoying when sending queries to a far away server. The query ID should be random.
Hey,
I am wondering how to respond with other query types than the ones provided in the server example:
result =
case query.type do
:a -> {127, 0, 0, 1}
:cname -> 'your.domain.com'
:txt -> ['your txt value']
_ -> nil
end
...
resource = %DNS.Resource{
domain: query.domain,
class: query.class,
type: query.type,
ttl: 0,
data: result
}
For instance, I am looking to how to respond with :aaaa and :mx. Any idea/pointer? Couldn't find the erlang documentation.
Thanks
Hi, I'm testing the package locally, running DNS.resolve("google.com")
works, but running DNS.resolve("google.com", {"8.8.8.8", 53})
gives me the following error:
** (CaseClauseError) no case clause matching: {"8.8.8.8", 53}
(kernel) inet_dns.erl:346: :inet_dns.encode_type/1
(kernel) inet_dns.erl:267: :inet_dns.encode_query_section/3
(kernel) inet_dns.erl:240: :inet_dns.encode/1
(dns) lib/dns.ex:46: DNS.query/3
(dns) lib/dns.ex:15: DNS.resolve/3
Any ideas? by the examples in the readme it looks like this should work.
Thanks
Hey,
Great package. I however experienced an issue by using the readme example as is (DNS server).
I believe this line:
%{record | anlist: [resource]}
should be replaced by
%{record | anlist: [resource], header: %{record.header | qr: true}}
otherwise you will get ";; Warning: query response not set" when you dig it - https://serverfault.com/questions/193238/what-does-warning-query-response-not-set-mean-in-dig-output
Thanks
Martin
If record types like NS are quite straightforward, there is apparently no documentation for a server wishing to reply to types like SOA which are not so obvious (and the error messages from the Erlang DNS library are unhelpful). Add an example like:
result =
case query.type do
:a -> {127, 0, 0, 1}
:aaaa -> {8193, 3512, 2989, 56495, 0, 0, 65535, 1}
:cname -> 'your.domain.example'
:txt -> ['General value', 'Other value']
:ns -> 'ns1.op.example'
:soa -> {'me.example', 'root.me.example', 1, 1800, 1800, 1800, 86400}
_ -> nil
end
Hey,
We're something seeing timeout errors on GitHub Actions when omitting the timeout value.
According to this line
Line 32 in a32f699
:infinity
.
In that case, how is it possible to get a timeout error with the following code?
DNS.resolve("default._domainkey.#{@domain_name}", :txt)
If we try to encode a response which has an Authority (nslist) section, the library crashes
** (FunctionClauseError) no function clause matching in :inet_dns.encode_res_section/3
(kernel) inet_dns.erl:275: :inet_dns.encode_res_section(<<155, 118, 133, 0, 0, 1, 0, 0, 0, 1, 0, 1, 5, 100, 114, 105, 110, 107, 4, 116, 101, 115, 116, 0, 0, 29, 0, 1>>, {2, {["drink", "test"], 12, nil, {["test"], 18, nil, nil}}}, [%DNS.Resource{bm: [], class: :in, cnt: 0, data: {'ns1.test', 'root.drink.test', 2022082613, 1800, 300, 604800, 86400}, domain: 'drink.test', func: false, tm: :undefined, ttl: 0, type: :soa}])
(kernel) inet_dns.erl:242: :inet_dns.encode/1
(drink) lib/drink/server.ex:315: Drink.Server.make_response/4
(drink) lib/drink/server.ex:157: Drink.Server.serve/6
Answer or Additional section do not have the problem.
Hello,
I tried to use the library but I can't get a simple DNS.resolve to work correctly, is the README up to date ?
Here is what I get :
iex(3)> DNS.resolve("google.com")
** (MatchError) no match of right hand side value: []
(dns) lib/dns.ex:10: DNS.resolve/2
Using {:dns, "~> 0.0.3"}
Thank you.
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.