-
-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Add -4 and -6 flags #1802
Add -4 and -6 flags #1802
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
challenge/dns01/nameserver.go
Outdated
// networkStack is used to define which IP stack will be used. The default is | ||
// both IPv4 and IPv6. Set to "ipv4" for IPv4 only, and "ipv6" for IPv6 only. | ||
var networkStack = "both" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe an enum would be better here:
// networkStack is used to define which IP stack will be used. The default is | |
// both IPv4 and IPv6. Set to "ipv4" for IPv4 only, and "ipv6" for IPv6 only. | |
var networkStack = "both" | |
type networkStack int | |
const ( | |
DefaultNetworkStack networkStack = iota | |
IPv4Only | |
IPv6Only | |
) | |
// currentNetworkStack is used to define which IP stack will be used. The default is | |
// both IPv4 and IPv6. Set to IPv4Only or IPv6Only to select either version. | |
var currentNetworkStack = DefaultNetworkStack |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of a Go "enum": it's not a real enum, it's just a weak list of values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ldez what do you want to see?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this PR currently only updates the dns01
package (and leaves http01
and tlsalpn01
as a TODO), maybe we can find a way to pass the stack selection to dns01.NewChallenge
, http01.NewChallenge
and tlsalpn01.NewChallenge
as an option?
Looking at dns01.NewChallenge
, it already accepts a vararg for options:
lego/challenge/resolver/solver_manager.go
Lines 51 to 54 in 1cad41d
func (c *SolverManager) SetDNS01Provider(p challenge.Provider, opts ...dns01.ChallengeOption) error { | |
c.solvers[challenge.DNS01] = dns01.NewChallenge(c.core, validate, p, opts...) | |
return nil | |
} |
Maybe the networkStack
can move into the cmd
package (in whatever form), and passing the selection as option to the challenge solver can be done (centrally) in setupChallenges
?
Lines 25 to 26 in 1cad41d
if ctx.Bool("http") { | |
err := client.Challenge.SetHTTP01Provider(setupHTTPProvider(ctx)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(and leaves
http01
andtlsalpn01
as a TODO)
It does not leave them as todo items. This PR is in draft because I wanted guidance prior to actually working on the full solution. At this point I'm getting conflicting feedback and would like a clear direction. I need this feature and am willing to put in the work, but I don't want to flail around to get it done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the miscommunication, English isn't my first language. I didn't mean "left as TODO for others", but "for this to work, we need to think of http01 and tlsalpn01 as well".
This comment was marked as outdated.
This comment was marked as outdated.
de0df97
to
0cb6495
Compare
I know that that the code in the dns challenge is working as intended as I was able to test it in the situation where I need the patch via a local build. I didn't receive any further feedback on how we should avoid the enum, so I continued with that construct. I do not believe I am missing any places where these switches would apply, but I don't know the code base that well. Please point out if I have missed any. |
I'll try to review this on the weekend, I'm currently a bit constrained on time. |
😕 This test runs cleanly locally https://github.com/go-acme/lego/actions/runs/3934066967/jobs/6757026356#step:5:278 |
Yeah, I think these tests are flaky. The same suite failed after my last push, but this time on a different domain name after passing the domain name that failed in the prior run. https://github.com/go-acme/lego/actions/runs/3953224067/jobs/6769527173#step:5:279 |
I don't think those tests are flaky, because I have the same problem locally. Can you also lint the code? ( Can you run |
The issue was running that subtest in isolation worked, but failed when run with all other subtests. In other words, my added test needed to have a
These should be passing now. |
By setting the port to 0, we defer the actual port selection to the OS (and thus we're guaranteed to use a free port). This eliminates an external dependency (jsumners/go-getport), which tried to do the same, but has a race condition between it returning an unused socket address, and us using that address in our tests. When instructing dns.Server to use port 0, the source for the local port depends on the protocol: for UDP this is (*dns.Server).PacketConn, and for TCP we find it in (*dns.Server).Listener.
- The miekg/dns package has, similar to net/http, a dns.HandlerFunc helper, which turns a plain function into a handler. This eliminates a type. - For static v4 addresses, net.IPv4() is better than net.ParseIP(), as parsing is not needed.
In general, require.NoError() should be preferred to assert.NoError(), especially if further assertions follow after that. The stretchr/testify/assert package does not call (*testing.T).FailNow() when the assertion fails (and stop the test), which can lead to pretty unreadable error message, e.g. when the rest of the test code panics.
Introducing a new parameter to an exported (public) function changes the API and requires a major version bump. Remember that Lego is used as library, e.g. as part of the Traefic app proxy. It is possible to preserve the API by extending the interface on the ProviderServer structs though.
…rface Exporting the network stack type allow the consumer to create custom, but likely disfunct values, which might cause panics when used. This changes the API to use dedicated setter functions instead, and reuses the same names accross the dns01, http01 and tlsalpn01 packages: - SetIPv4Only() - SetIPv6Only() - SetDualStack()
@jsumners: I've added a bunch of review commits. The commit messages contain some reasoning, but to reiterate my major changes:
|
That is explicitly noted in the docs: https://github.com/jsumners/go-getport/blob/ef4d1d0da783a1930d39b868161a94609ab08c71/getport.go#L55-L58. It also has no bearing in these tests. In CI, they are isolated. Running locally, it's extremely unlikely that anything will acquire a port in the nanoseconds between finding the open port and the using it for a test. Still, 🤷♂️.
I received no further feedback on which direction to take after asking for it. So I went with the only feedback that had been provided.
This is fine by me.
I don't have a Windows environment for testing. All I know is that my last commit was passing with the GitHub CI. Regarding that statement about "my last commit". I'm rather put off by changes being made directly to the branch. I think they could have all been review comments with some suggestions (item 6 in https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/commenting-on-a-pull-request#adding-line-comments-to-a-pull-request) along the way. I feel like at this point the PR is yours @dmke. I still want to see this added, as the functionality has solved a problem out of my control (my ISP having a bad IPv6 implementation) and likely solves several other issues as stated in the original proposal. So I can provide feedback if desired. |
The failure was introduced here: func sendDNSQuery(m *dns.Msg, ns string) (*dns.Msg, error) {
- udp := &dns.Client{Net: "udp", Timeout: dnsTimeout}
+ network := getNetwork("udp")
+ udp := &dns.Client{Net: network, Timeout: dnsTimeout}
in, _, err := udp.Exchange(m, ns)
- if in != nil && in.Truncated {
- tcp := &dns.Client{Net: "tcp", Timeout: dnsTimeout}
+ network = getNetwork("tcp")
+ // We can encounter a net.OpError if the nameserver is not listening
+ // on UDP at all, i.e. net.Dial could not make a connection.
+ _, isOpErr := err.(*net.OpError)
+ if (in != nil && in.Truncated) || isOpErr {
+ tcp := &dns.Client{Net: network, Timeout: dnsTimeout}
// If the TCP request succeeds, the err will reset to nil
in, _, err = tcp.Exchange(m, ns)
} (You've changed the tests for this here; for that commit I forgot to approve a CI run though.) The issue is that the TCP-retry-branch is now taken in more cases, as the previous error ("read udp") also is a Tackling this is also a bit cumbersome, as a CI run takes forever to complete, and I haven't had a chance to revive my local Windows VM (I've also felt under the whether the last few days, so my capacity for patience to let Windows do its thing was much reduced).
Sorry about that, I didn't want to scare you off. I've started a review the normal way, but it quickly turned into a wild mess of cross-comment-references. Also, review suggestions can only be applied to changed lines, not arbitrary places. It turned out to be much cleaner to leave review commits and show the changes one-by-one, in separated contexts. In the end the commits will be squashed anyway, so the outcome would be the same. |
There's a small annoyance between GOOS=linux and GOOS=windows for net.DialContext when a TCP connection fails, due to the naming of the syscalls involved: On Linux, connect(2) is used, which can cause ECONNREFUSED, while the Windows equivalent is the ConnectEx syscall, which can cause WSAECONNREFUSED. The error generated by nameservers.FindZoneByFqdnCustom and FindPrimaryNsByFqdnCustom may hence contain a different error trance (one containing "connect:", the other "connectex:"). This commit tries to address that, by using a simple regular expression to match either error message.
I've spent the last 7 hours in my Windows VM to get the tests green again. Turns out I hate Windows Defender with a passion. I guess on the CI, Defender is active as well (log from here), and slows down operations considerably:
In I'm baffled. This part of the code didn't change, how come it stopped working? @ldez, do you have an idea? (I'm frustrated enough to consider proposing to downgrade Windows support for Lego to "experimental", and drop Windows from the CI workflow altogether... Maybe I should sleep on this for a bit before doing so :/) |
😨 |
What can I do to help get this to the finish line? |
I will spend some time on that in the following days |
I'm currently investigating as too why Windows performs abysmally poor, and seeking ways to improve that. However, that's going very slowly... |
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by @dmke in go-acme#1802. This PR is to resolve go-acme#1801.
Closing in favor of #1984. |
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by @dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by @dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by @dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by @dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by @dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by @dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by @dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by dmke in go-acme#1802. This PR is to resolve go-acme#1801.
This PR is a redo of go-acme#1802. Since that PR has been idle so long, the branches have diverged quite a bit and it was easier to start anew. The work in this PR includes the work originally done by dmke in go-acme#1802. This PR is to resolve go-acme#1801.
If completed, this PR will resolve #1801. At the moment I'm opening a draft PR to gauge interest in the overall proposal.
(outdated lint errors)
I do not understand these lint errors:
I do not know what "gci-ed" means.
I also don't understand this one because
recursiveNameservers
is also a global:I'm open to this not being a global if I can get some guidance on how it should be passed in from the CLI flags processing down to where the DNS query is actually invoked.
Items that remain:
lego/cmd/setup_challenges.go
Line 44 in e982d5a
lego/cmd/setup_challenges.go
Line 86 in e982d5a