control/controlhttp: factor out some code in prep for future change

This pulls out the clock and forceNoise443 code into methods on the
Dialer as cleanup in its own commit to make a future change less
distracting.

Updates #13597

Change-Id: I7001e57fe7b508605930c5b141a061b6fb908733
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2024-10-01 09:13:57 -07:00 committed by Brad Fitzpatrick
parent d3f302d8e2
commit fd32f0ddf4
2 changed files with 24 additions and 12 deletions

View File

@ -86,7 +86,7 @@ func (a *Dialer) getProxyFunc() func(*http.Request) (*url.URL, error) {
// httpsFallbackDelay is how long we'll wait for a.HTTPPort to work before
// starting to try a.HTTPSPort.
func (a *Dialer) httpsFallbackDelay() time.Duration {
if forceNoise443() {
if a.forceNoise443() {
return time.Nanosecond
}
if v := a.testFallbackDelay; v != 0 {
@ -151,10 +151,7 @@ type dialResult struct {
// before we do anything.
if c.DialStartDelaySec > 0 {
a.logf("[v2] controlhttp: waiting %.2f seconds before dialing %q @ %v", c.DialStartDelaySec, a.Hostname, c.IP)
if a.Clock == nil {
a.Clock = tstime.StdClock{}
}
tmr, tmrChannel := a.Clock.NewTimer(time.Duration(c.DialStartDelaySec * float64(time.Second)))
tmr, tmrChannel := a.clock().NewTimer(time.Duration(c.DialStartDelaySec * float64(time.Second)))
defer tmr.Stop()
select {
case <-ctx.Done():
@ -268,6 +265,23 @@ type dialResult struct {
// fixed, this is a workaround. It might also be useful for future debugging.
var forceNoise443 = envknob.RegisterBool("TS_FORCE_NOISE_443")
// forceNoise443 reports whether the controlclient noise dialer should always
// use HTTPS connections as its underlay connection (double crypto). This can
// be necessary when networks or middle boxes are messing with port 80.
func (d *Dialer) forceNoise443() bool {
if forceNoise443() {
return true
}
return false
}
func (d *Dialer) clock() tstime.Clock {
if d.Clock != nil {
return d.Clock
}
return tstime.StdClock{}
}
var debugNoiseDial = envknob.RegisterBool("TS_DEBUG_NOISE_DIAL")
// dialHost connects to the configured Dialer.Hostname and upgrades the
@ -320,16 +334,13 @@ type tryURLRes struct {
}
// Start the plaintext HTTP attempt first, unless disabled by the envknob.
if !forceNoise443() {
if !a.forceNoise443() {
go try(u80)
}
// In case outbound port 80 blocked or MITM'ed poorly, start a backup timer
// to dial port 443 if port 80 doesn't either succeed or fail quickly.
if a.Clock == nil {
a.Clock = tstime.StdClock{}
}
try443Timer := a.Clock.AfterFunc(a.httpsFallbackDelay(), func() { try(u443) })
try443Timer := a.clock().AfterFunc(a.httpsFallbackDelay(), func() { try(u443) })
defer try443Timer.Stop()
var err80, err443 error

View File

@ -95,8 +95,9 @@ type Dialer struct {
omitCertErrorLogging bool
testFallbackDelay time.Duration
// tstime.Clock is used instead of time package for methods such as time.Now.
// If not specified, will default to tstime.StdClock{}.
// Clock, if non-nil, overrides the clock to use.
// If nil, tstime.StdClock is used.
// This exists primarily for tests.
Clock tstime.Clock
}