dns
Version, currently 0.1.12 versions
- 0.1.1latestApr 26, 2020
- 0.1.0not indexedJan 31, 2020
gitlab.com/jgillich/crystal-dns
DNS protocol library
Installation
# Add this to your shard.yml
dependencies:
dns:
gitlab: jgillich/crystal-dns
version: ~> 0.1.1Then run:
shards installshard.yml
- Crystal
- no constraint declared
- License
- MIT
- Author
- Jakob Gillich
Dependencies
This version declares no dependencies.
README
DNS for Crystal
crystal-dns implements the DNS protocol and provides a resolver. It can also be used to implement a name server, but there might be some missing pieces.
This is beta quality software. The API is not stable and some features are missing. Further testing is needed. No support for DNSSEC and DNS-over-TLS at this time.
crystal-dns was developed for Everbase, our Crystal-powered API that makes you a more productive developer. Check it out!
Installation
Add this to your project's shard.yml:
dependencies:
dns:
gitlab: jgillich/crystal-dns
Resolver Usage
resolver = DNS::Resolver.new
response = resolver.query("example.com", DNS::RecordType::AAAA)
response.answers.each do |answer|
puts "got ipv6 address #{answer.data}"
end
resolver.close
Advanced Usage
If you are already familiar with DNS, most of this library should be self-explanatory. The main
information carrier in DNS is a Message. The format is identical for both queries and responses,
but some fields vary. In a nutshell, a message contains:
- A header. This includes information about the message (is it a query or a response, number of results, etc)
- A question. It consists of a domain name, a record type (A, CNAME, MX etc) and a record class (in most cases IN for internet). Technically DNS allows for more than one question, but very few name servers support this.
- A number of records with a data payload. If your question's record type is A, the payload is an IPv4 address.
First we need a Socket to communicate over. This can be either a client or a
server, but for this example we'll talk to a server.
require "socket"
require "dns"
socket = UDPSocket.new
socket.connect("8.8.8.8", 53)
Now we build a message with the format from above:
header = DNS::Header.new(op_code: DNS::OpCode::Query, recursion_desired: true)
message = DNS::Message.new(header: header)
message.questions << DNS::Question.new(name: DNS::Name.new("www.example.com"), query_type: DNS::ResourceType::A)
This is a valid DNS query that will return the IPv4 address for the domain www.example.com.
Message implements #to_io(IO, IO::ByteFormat) and .from_io(IO, IO::ByteFormat), but they do
not work well with a Socket. We need IO#seek to resolve pointers, but sockets do not implement
this method. There are also some slight variations in the data format between UDP and TCP. So
instead, we provide #to_socket(Socket, IO::ByteFormat) and Message.from_socket(Socket, IO::ByteFormat).
Let's use them to send our message:
message.to_socket socket
Done! Now we can read the response:
response = Message.from_socket socket
response.answers.each do |answer|
puts "got ipv4 address #{answer.data}"
end
Links
Documentation
Built from the current release. The first visit to a release nobody has asked for starts its build.
Links
This release
- Version
0.1.1- Tagged
- Apr 26, 2020
- Commit
e664d8561144- Indexed
- yes
Dependents
Repository
gitlab.com/jgillich/crystal-dns
Metadata
- Created
- Aug 16, 2026
- Updated
- Oct 14, 2026
- Synced
- Oct 14, 2026
- Versions
- 2