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

[vnet][2] DNS library #40972

Merged
merged 9 commits into from
May 8, 2024
Merged

[vnet][2] DNS library #40972

merged 9 commits into from
May 8, 2024

Conversation

nklaassen
Copy link
Contributor

@nklaassen nklaassen commented Apr 26, 2024

This is the third in a series of PRs implementing Teleport VNet RFD. parent child

This PR implements a DNS server library that will later be used by VNet to serve local address for all Teleport apps. It supports directly answering DNS questions where the answer is known, and forwarding DNS questions to upstream nameservers when the answer isn't known locally. It does not implement any caching, downstream DNS resolvers should do their own caching.

@nklaassen nklaassen added the no-changelog Indicates that a PR does not require a changelog entry label Apr 26, 2024
@github-actions github-actions bot requested review from fspmarshall and Joerger April 26, 2024 23:23
)

// Resolver represents an entity that can resolve DNS requests.
type Resolver interface {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I assume net.Resolver won't work here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

right - net.Resolver is a concrete type that is an actual DNS resolver, I'm using this interface to pass in my custom DNS resolver in the tests and in #41031

@nklaassen nklaassen mentioned this pull request Apr 30, 2024
@nklaassen nklaassen requested a review from ibeckermayer May 2, 2024 00:56
@nklaassen nklaassen force-pushed the nklaassen/vnet2 branch 2 times, most recently from 2142e2d to 969dd03 Compare May 3, 2024 22:22
Base automatically changed from nklaassen/vnet1 to master May 7, 2024 02:29
@nklaassen
Copy link
Contributor Author

friendly ping @Joerger @fspmarshall

lib/vnet/dns/dns.go Show resolved Hide resolved
lib/vnet/dns/dns.go Show resolved Hide resolved
lib/vnet/dns/dns.go Outdated Show resolved Hide resolved
)

const (
maxUDPMessageSize = 65535
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: would be good to document the significance of this value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks for encouraging me to actually put a bit more thought into this, since we're only handling DNS we can actually shrink this quite a bit to the (typical) maximum EDNS message size of 4096 bytes.

lib/vnet/dns/dns.go Outdated Show resolved Hide resolved
lib/vnet/dns/dns.go Outdated Show resolved Hide resolved
@nklaassen nklaassen enabled auto-merge May 8, 2024 17:12
@nklaassen nklaassen added this pull request to the merge queue May 8, 2024
Merged via the queue into master with commit 6833aab May 8, 2024
36 checks passed
@nklaassen nklaassen deleted the nklaassen/vnet2 branch May 8, 2024 17:43

var (
// vnetNotImplemented is an error indicating that VNet is not implemented on the host OS.
vnetNotImplemented = &trace.NotImplementedError{Message: "VNet is not implemented on " + runtime.GOOS}
Copy link
Contributor

Choose a reason for hiding this comment

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

vnetNotImplementedErr

Comment on lines +51 to +57
// ResolveA should return a Result for an A record question. If an empty Result is returned with no error,
// the question will be forwarded upstream.
ResolveA(ctx context.Context, domain string) (Result, error)

// ResolveAAAA should return a Result for an AAAA record question. If an empty Result is returned with no
// error, the question will be forwarded upstream.
ResolveAAAA(ctx context.Context, domain string) (Result, error)
Copy link
Contributor

Choose a reason for hiding this comment

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

Since "empty Result" means something here, it would be helpful to codify what "empty" means with a Result.isEmpty() method, or change this API to return a *Result and return nil on "empty".

}, nil
}

// getMessageBuffer returns a buffer of size [maxUDPMessageSize]. Call [returnBuf] to return the buffer to the
Copy link
Contributor

Choose a reason for hiding this comment

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

`// ... Callers MUST call [returnBuf] to return the buffer to the shared pool after use.

if err != nil {
return trace.Wrap(err, "failed to read from UDP conn")
}
if n >= maxUDPDNSMessageSize {
Copy link
Contributor

Choose a reason for hiding this comment

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

  1. n will never be > maxUDPDNSMessageSize, because all the buffers are maxUDPDNSMessageSize
  2. Shouldn't n == maxUDPDNSMessageSize be valid, because a message of the max size is allowed?
  3. I don't know exactly how things work here, but if this is a continuous conn then you may need some way to discard the rest of a too-big-message here. Otherwise the next call to HandleUDP may just be reading the end of the oversized message.


// ListendAndServeUDP reads all incoming UDP messages from [conn], handles DNS questions, and writes the
// responses back to [conn].
// This is not called by VNet code and basically exists so we can test the resolver outside of VNet.
Copy link
Contributor

Choose a reason for hiding this comment

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

Smells a bit fishy, like there should be a better way to simulate calling HandleUDP itself, but I don't know it. Maybe more will be revealed in the next PR.

lib/vnet/dns/dns.go Show resolved Hide resolved
lib/vnet/dns/osnameservers_darwin.go Show resolved Hide resolved
Comment on lines +311 to +312
// Not using the errgroup err, errors were written to channel.
_ = g.Wait()
Copy link
Contributor

Choose a reason for hiding this comment

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

Wherever you do this I suspect there's a simpler way just using go primitives instead of errgroup

errs := make(chan error, len(upstreamNameservers))
g, ctx := errgroup.WithContext(ctx)
ctx, cancel = context.WithCancel(ctx)
defer cancel()
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this cancel's redundant, the parent already has a deferred cancel.

lib/vnet/dns/dns.go Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no-changelog Indicates that a PR does not require a changelog entry size/lg
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants