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: TRR2 resolver #846

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

feat: TRR2 resolver #846

wants to merge 8 commits into from

Conversation

DecFox
Copy link
Contributor

@DecFox DecFox commented Jul 22, 2022

Checklist

Description

This intoduces a TRR2 resolver to measurexlite allowing us to opportunistcally test for DoH and make use of it whenever we can. The resolver uses the system resolver (getaddrinfo) as a fallback when DoH fails

decfox added 3 commits July 20, 2022 15:32
This intoduces a TRR2 resolver to measurexlite allowing
us to opportunistcally test for DoH and make use of it
whenever we can. The resolver uses the system resolver
(getaddrinfo) as a fallback when DoH fails
Copy link
Contributor

@bassosimone bassosimone left a comment

Choose a reason for hiding this comment

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

I like the work you did so far. As I mention to you in private, we probably need to figure out some design details around this functionality, which won't cause dramatic changes, so we can discuss them in parallel with the code review proper. I highlighted a bunch of places in which I think you should tweak/refactor your code for improved robustness.

Additionally, I've seen quite a large coverage drop (-0.5%) which most likely means that we have added a bit too much code that we're not testing. I would recommend for you to check which are the new functions that we're not testing and add tests.

@@ -64,6 +64,20 @@ func (r *resolverTrace) LookupNS(ctx context.Context, domain string) ([]*net.NS,
return r.r.LookupNS(netxlite.ContextWithTrace(ctx, r.tx), domain)
}

// NewTrustedRecursiveResolver2 returns a trace-aware TRR2 resolver
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
// NewTrustedRecursiveResolver2 returns a trace-aware TRR2 resolver
// NewTrustedRecursiveResolver2 returns a trace-aware TRR2 resolver.

"github.com/ooni/probe-cli/v3/internal/netxlite"
)

// NewTrustedRecursiveResolver2 returns a new trusted recursive resolver
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
// NewTrustedRecursiveResolver2 returns a new trusted recursive resolver
// NewTrustedRecursiveResolver2 returns a new trusted recursive resolver.

Copy link
Contributor

Choose a reason for hiding this comment

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

You should document that logger is MANDATORY while URL is OPTIONAL and you should say what happens if you provide an empty URL. You should probably say, for future robustness, that we're going to choose a suitable URL (or you could also be specific, up to you).

}
}

// TrustedRecursiveResolver2 emulates Firefox's TRR2 mode
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
// TrustedRecursiveResolver2 emulates Firefox's TRR2 mode
// TrustedRecursiveResolver2 emulates Firefox's TRR2 mode.

Comment on lines 31 to 32
Logger model.Logger
URL string
Copy link
Contributor

Choose a reason for hiding this comment

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

Please, document Logger and URL (and mention they're MANDATORY)

// we can't return a decisive address here since we don't know if LookupHost
// succeeds with the DoH resolver or the system resolver
func (trr *TrustedRecursiveResolver2) Address() string {
return ""
Copy link
Contributor

Choose a reason for hiding this comment

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

How about returning the URL here?


//
// Trusted Recursive Resolver
//
Copy link
Contributor

Choose a reason for hiding this comment

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

Either call the file trr2.go and keep this comment or call this file resolver.go and say it contains resolvers

)

func TestNewTrustedRecursiveResolver(t *testing.T) {
var called bool
Copy link
Contributor

Choose a reason for hiding this comment

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

Please, put suitable copies of this variable in the narrowest possible scope to avoid mistakes caused by the variable in a subtest using a value previously computed by another subtest.

Copy link
Contributor

Choose a reason for hiding this comment

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

(I see how in the code you only use it once, but I'd like to recommend you probably just create the resolver you need each time rather than having too much shared state for tests. The issue with shared state is that it's not robust to refactoring, so I'd rather just initialize each time the specific calls I need and leave others as nil)

Comment on lines 58 to 59
resolver := NewTrustedRecursiveResolver2(&mocks.Logger{}, "")
resolvert := resolver.(*TrustedRecursiveResolver2)
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
resolver := NewTrustedRecursiveResolver2(&mocks.Logger{}, "")
resolvert := resolver.(*TrustedRecursiveResolver2)
resolver := NewTrustedRecursiveResolver2(&mocks.Logger{}, "").(*TrustedRecursiveResolver2)

This should save you a variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right. Thanks!

resolvert := resolver.(*TrustedRecursiveResolver2)
resolvert.NewParallelDNSOverHTTPSResolverFn = newResolver
ctx := context.Background()
t.Run("LookupHost", func(t *testing.T) {
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
t.Run("LookupHost", func(t *testing.T) {
t.Run("LookupHost", func(t *testing.T) {

Please always add spaces around t.Run invocations. This allows for easy navigation of blocks using vi's { and } commands.

@@ -52,7 +52,7 @@ func TestGetMeasurementMetaWorkingAsIntended(t *testing.T) {
if mmeta.Input == nil || *mmeta.Input != config.Input {
t.Fatal("unexpected input value")
}
if mmeta.MeasurementStartTime.String() != "2020-12-09 05:22:25 +0000 UTC" {
if mmeta.MeasurementStartTime.String() != "2020-12-09 04:22:25 +0000 UTC" {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't fully understand why this change is necessary and the commit does not seem to explain in detail why this was behaving in a flaky way. Would you mind clarifying?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There was a bug in the data pipeline (as I had informed in our 1:1). I have reverted this back since the bug has been fixed now: f71c4e2

Copy link
Contributor

@bassosimone bassosimone left a comment

Choose a reason for hiding this comment

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

Additional issues that I discovered while writing a design document for this feature

if reso == nil {
reso = netxlite.NewParallelDNSOverHTTPSResolver(trr.Logger, trr.URL)
}
addrs, err := reso.LookupHost(ctx, hostname)
Copy link
Contributor

Choose a reason for hiding this comment

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

I forgot to mention: if we want to implement TRR2 correctly, this lookup should be strictly time bounded (i.e., we should timeout the lookup after N seconds have elapsed)

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 have added a timeout to the DoH resolver here: 286c78f#diff-4c58fee97f07a0f47542cb08705a81d5f43f76be1d6235538ceb3e4c51725e72R33,
this is currently configured to use Firefox's default timeout value of 1.5s

}
out, err := reso.LookupHTTPS(ctx, domain)
if err != nil {
out, err = trr.ResolverSystem.LookupHTTPS(ctx, domain)
Copy link
Contributor

Choose a reason for hiding this comment

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

Because the system resolver only implements LookupHost, we should consider implementing model.SimpleResolver rather than model.Resolver.

decfox added 2 commits August 2, 2022 11:02
We discussed this @hellais and it was a bug in the data pipeline
which seems to be have been fixed. We can therefore revert back to the
original implementation.
@DecFox
Copy link
Contributor Author

DecFox commented Aug 2, 2022

I like the work you did so far. As I mention to you in private, we probably need to figure out some design details around this functionality, which won't cause dramatic changes, so we can discuss them in parallel with the code review proper. I highlighted a bunch of places in which I think you should tweak/refactor your code for improved robustness.

Additionally, I've seen quite a large coverage drop (-0.5%) which most likely means that we have added a bit too much code that we're not testing. I would recommend for you to check which are the new functions that we're not testing and add tests.

Thank you for the feedback! I have made some changes based on the review. I have also added more tests, but the coverage still seems to be decreased. So we probably need to write some more.

@DecFox DecFox marked this pull request as ready for review August 8, 2022 05:37
@DecFox DecFox requested a review from hellais as a code owner August 8, 2022 05:37
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