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

Fix auth.go not finding the tsnet.Listener. #70

Merged
merged 4 commits into from
Jun 20, 2024

Conversation

beep-beep-beep-boop
Copy link
Contributor

This fixes #68

auth.go was treating the listener as if it was a tsnet.Listener, but it was actually a tsServerListener which had a member (Listener) that implemented tsnet.Listener. This caused it to fall-through and try to authenticate the request through a locally-running tailscaled, which would fail if caddy was running in a container without one.

I'm not very familiar with go so IDK if there's a less messy-looking way to do this.

@beep-beep-beep-boop beep-beep-beep-boop force-pushed the fix-auth-listener branch 2 times, most recently from 4f76a64 to f2e3ea3 Compare June 17, 2024 08:06
Signed-off-by: hello <79901832+beep-beep-beep-boop@users.noreply.github.com>
@beep-beep-beep-boop
Copy link
Contributor Author

okay, this doesn't completely fix it. the issue still happens when trying to connect via https to the .ts.net domain. everything else will work, including the http .ts.net domain. (although if you put the https domain itself in the caddy file instead of :443 it seems like it tries to redirect to the https one which will essentially make the http .ts.net stop working as well.)

if you remove the tailscale_auth directive from the https route in the caddyfile it will work fine.

so this won't work:

https://caddytest.abc.ts.net {
  bind tailscale/caddytest
  tailscale_auth # this is causing the issue
  templates
  respond `Hello, {{placeholder "http.auth.user.id"}}`
}

but this will (but it won't authenticate):

https://caddytest.abc.ts.net {
  bind tailscale/caddytest
  templates
  respond `Hello, {{placeholder "http.auth.user.id"}}`
}

@willnorris
Copy link
Member

willnorris commented Jun 18, 2024

okay, so the problem is that ever since f2562ba, we no longer just have a tsnet.listener. We now have a tsnet.listener wrapped in a [crypto/tls].listener wrapped in a caddyhttp.http2Listener, and neither of the latter two expose methods to unwrap them and get the internal listener. We could send a patch to caddy to add an Unwrap() net.Listener method on caddyhttp.http2Listener, but tls.listener is more challenging.

@mholt, how gross would it be to have something like:

type wrappedListener struct {
	net.Listener
	wrapped net.Listener
}

func (h *wrappedListener) Unwrap() net.Listener {
	return h.wrapped
}

and then app.Start has something like:

	if useTLS {
		// create TLS listener - this enables and terminates TLS
		tlsln := tls.NewListener(ln, tlsCfg)
		ln = &wrappedListener{Listener: tlsln, wrapped: ln}
		// ...
	}

I just tested this, and along with an Unwrap method on caddyhttp.http2Listener, this works to let me recursively unwrap to get to the underlying listener.

So basically this: caddyserver/caddy@master...willnorris:caddy:wrappedListener

willnorris added a commit to willnorris/caddy that referenced this pull request Jun 18, 2024
Allow unwrapping the net.Listener values inside both http2Listener and
tls.listener, the latter with a little indirection.

Updates tailscale/caddy-tailscale#70
willnorris added a commit to willnorris/caddy that referenced this pull request Jun 18, 2024
Allow unwrapping the net.Listener values inside both http2Listener and
tls.listener, the latter with a little indirection.

Updates tailscale/caddy-tailscale#70
@beep-beep-beep-boop
Copy link
Contributor Author

I was thinking about using reflection to get to it. having a way to do it built into caddy would be better though i think.

Signed-off-by: hello <79901832+beep-beep-beep-boop@users.noreply.github.com>
@beep-beep-beep-boop
Copy link
Contributor Author

I updated the PR to use reflection for now but doing it on caddy's end is probably a better permanent solution.

@mholt
Copy link
Contributor

mholt commented Jun 18, 2024

@willnorris We could do that, but like you mentioned, that chain would stop with a listener out of our control (like tls.Listener). Is the unwrapping needed only in this specific case?

@willnorris
Copy link
Member

@willnorris We could do that, but like you mentioned, that chain would stop with a listener out of our control (like tls.Listener). Is the unwrapping needed only in this specific case?

Yes, the wrappedListener type is only needed for the case of listeners out of caddy's control. I don't know if tls.Listener is the only example of that... that's just the one at play in this specific instance.

@mholt
Copy link
Contributor

mholt commented Jun 18, 2024

What if we stick with the current solution (reflection -- not as ugly as I'd have thought!) and if other use cases start showing up, we can consider generalizing a solution upstream in Caddy?

@willnorris
Copy link
Member

The proposed changes to caddy are quite minimal as well, and far cleaner than having to resort to reflection. Though I do understand that we're likely one of the only ones using caddyhttp.Server.Listeners(), so this would be a change in a highly used code path for a very small number of users.

@mholt
Copy link
Contributor

mholt commented Jun 19, 2024

True -- and to clarify, I'm not opposed to that change in Caddy (someday, if needed) -- because it's so minimal. I'm just thinking that for now, let's see if this can work and if we need it to generalize then we can make the change 👍

Copy link
Member

@willnorris willnorris left a comment

Choose a reason for hiding this comment

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

@beep-beep-beep-boop let's add a note on this new func to revisit in the future if and when Caddy support unwrapping listeners. Otherwise, this LGTM

auth.go Outdated Show resolved Hide resolved
beep-beep-beep-boop and others added 2 commits June 19, 2024 21:23
…tself.


Signed-off-by: hello <79901832+beep-beep-beep-boop@users.noreply.github.com>

Co-authored-by: Will Norris <will@willnorris.com>
@willnorris
Copy link
Member

I pushed a new commit to go ahead and add the wrappedListener interface and use it when present, then use reflection as a fallback.

@willnorris willnorris merged commit 082211a into tailscale:main Jun 20, 2024
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants