Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create DNS library #141

Merged
merged 15 commits into from
Jan 9, 2024
Merged

feat: create DNS library #141

merged 15 commits into from
Jan 9, 2024

Conversation

fortuna
Copy link
Contributor

@fortuna fortuna commented Dec 15, 2023

This PR introduces a library for DNS, and the concept of a DNS RoundTripper (similar to http.RoundTripper), to facilitate the exchange of DNS messages of various protocols.

It establishes the base for other functionality, such as the use in Dialers, caching and strategy selection.

I still need to add tests, but I believe it's in good shape to start a review.

I'm still not convinced about the name. I borrowed RoundTripper from the http library, but it's kind of an unusual name. It's particularly bad as a verb. Some other options that may be better for the function:

  • Exchange
  • Query
  • Lookup
  • Request
  • Answer
  • Ask

We could also add a DNS prefix like ExchangeDNS, AskDNS, ...

The DoH RFC uses both Exchange and Request. I'm inclined to use Exchange, since it clearly conveys there's a message back from the server, and it's a phrase that is in common use. Answer or Ask seems appropriate too, given we pass a question.

Any thoughts?

@fortuna fortuna requested a review from jyyi1 December 15, 2023 22:42
Copy link
Contributor

@jyyi1 jyyi1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exchange sounds good. Or we can use a name similar to net.Resolver, like Lookup()?

dns/roundtrip.go Outdated Show resolved Hide resolved
dns/roundtrip.go Outdated Show resolved Hide resolved
dns/roundtrip.go Outdated Show resolved Hide resolved
dns/roundtrip.go Outdated Show resolved Hide resolved
dns/roundtrip.go Outdated Show resolved Hide resolved
dns/roundtrip.go Outdated
// RoundTripper is an interface representing the ability to execute a
// single DNS transaction, obtaining the Response for a given Request.
// This abstraction helps hide the underlying transport protocol.
type RoundTripper interface {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up settling for Resolver and Query, since that's the nomenclature that is predominantly used in the standards (example: https://datatracker.ietf.org/doc/html/rfc1034)

dns/roundtrip.go Outdated Show resolved Hide resolved
dns/roundtrip.go Outdated Show resolved Hide resolved
dns/roundtrip.go Outdated Show resolved Hide resolved
dns/roundtrip.go Outdated Show resolved Hide resolved
dns/roundtrip.go Outdated Show resolved Hide resolved
Copy link
Contributor Author

@fortuna fortuna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests are done. This is ready for a full review.

Copy link
Contributor

@jyyi1 jyyi1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Submit some comments first, I'll review the rest tomorrow.

.github/workflows/test.yml Show resolved Hide resolved
dns/doc.go Show resolved Hide resolved
dns/resolver.go Outdated Show resolved Hide resolved
dns/resolver.go Show resolved Hide resolved
dns/resolver.go Show resolved Hide resolved
Header: dnsmessage.ResourceHeader{
Name: dnsmessage.MustNewName("."),
Type: dnsmessage.TypeOPT,
Class: maxDNSPacketSize,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Class: maxDNSPacketSize,
Class: dnsmessage.ClassINET,

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still by design?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The OPT RR is a fake record that overloads the unused fields for common attributes. See https://datatracker.ietf.org/doc/html/rfc6891#section-6.1.2.

I added a comment.

dns/resolver.go Outdated Show resolved Hide resolved
dns/resolver.go Outdated Show resolved Hide resolved
dns/resolver.go Outdated Show resolved Hide resolved
dns/resolver.go Show resolved Hide resolved
@fortuna fortuna requested a review from jyyi1 January 3, 2024 17:08
Copy link
Contributor

@jyyi1 jyyi1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is awesome! It's mostly LGTM with just a few minor comments.

dns/resolver.go Show resolved Hide resolved
dns/resolver.go Show resolved Hide resolved
dns/resolver.go Show resolved Hide resolved
dns/resolver.go Show resolved Hide resolved
@fortuna fortuna requested a review from jyyi1 January 8, 2024 16:27
Copy link
Contributor

@jyyi1 jyyi1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, approved!

Comment on lines +27 to +37
The Outline SDK is built upon a simple basic concepts, defined as interoperable interfaces that allow for composition and easy reuse.

**Connections** enable communication between two endpoints over an abstract transport. There are two types of connections:
- `transport.StreamConn`: stream-based connection, like TCP and the `SOCK_STREAM` Posix socket type.
- `transport.PacketConn`: datagram-based connection, like UDP and the `SOCK_DGRAM` Posix socket type. We use "Packet" instead of "Datagram" because that is the convention in the Go standard library.

Connections can be wrapped to create nested connections over a new transport. For example, a `StreamConn` could be over TCP, over TLS over TCP, over HTTP over TLS over TCP, over QUIC, among oter options.

**Dialers** enable the creation of connections given a host:port address while encapsulating the underlying transport or proxy protocol. The `StreamDialer` and `PacketDialer` types create `StreamConn` and `PacketConn` connections, respectively, given an address. Dialers can also be nested. For example, a TLS Stream Dialer can use a TCP dialer to create a `StreamConn` backed by a TCP connection, then create a TLS `StreamConn` backed by the TCP `StreamConn`. A SOCKS5-over-TLS Dialer could use the TLS Dialer to create the TLS `StreamConn` to the proxy before doing the SOCKS5 connection to the target address.

**Resolvers** (`dns.Resolver`) enable the answering of DNS questions while encapsulating the underlying algorithm or protocol. Resolvers are primarily used to map domain names to IP addresses.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lines can also be the package documentation of transport.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I think we need it in both. I'll leave the revamp of the transport Go doc to another PR.

@fortuna fortuna merged commit 525beac into main Jan 9, 2024
6 checks passed
@fortuna fortuna deleted the fortuna-dns-clean branch January 9, 2024 03:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants