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(derp): support verify-clients
#1580
base: main
Are you sure you want to change the base?
Conversation
support client verification Signed-off-by: kovacs <mritd@linux.com>
fix tailscale derper server nil pointer panic Signed-off-by: kovacs <mritd@linux.com>
add socket dir Signed-off-by: kovacs <mritd@linux.com>
update example config and change log Signed-off-by: kovacs <mritd@linux.com>
} | ||
|
||
log.Trace().Caller().Msg("Clean up fake status socket file") | ||
if err := os.RemoveAll(socketPath); err != nil { |
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.
It looks like this removes the socket at the default tailscale socket location. If the host is also running a seperate tailscale client, would this not break that?
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.
This is indeed a difficult decision. Since we are using a simulated socket API solution, we must be able to manage the socket files regardless of who created them before.
This implementation does not allow Tailscale and headscale DERP to coexist. If we consider the Tailscale client, we have only two options:
- 1、Headscale DERP fails to start to minimize the impact on the Tailscale client behavior.
- 2、Take direct control of the socket API to meet our own requirements, but this will cause the Tailscale client to fail to run.
Are we going to adopt the first solution?
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.
Theoretically, I'd assume if there's a Tailscale client on the same host as Headscale, the client is connected to the Headscale server. In that case, would it be possible to completely skip socket emulation, and use the existing socket for client verification? I'm not a maintainer of Headscale so you may want to wait for their opinion - but that seems to be the most optimal method. If the Tailscale DERP server includes an option for a Tailscale socket, that may be even better, to use a separate socket to not conflict with the default client. You could even do some detection where if the socket is found from the Tailscale client, it uses that to verify instead.
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 can suggest adding two security measures:
- 1、Add an
enable_socket_api
field in the configuration file to allow users to explicitly enable the simulation of the socket API. - 2、Before performing the cleanup, call tailscale.Status() to verify if it returns a result. If it does, it indicates that another tailscaled process is listening on the socket file. In this case, a warning should be issued or the execution should be terminated.
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.
Hi, thanks for this work, I think the way to move this forward is to require tailscale to run on the node hosting headscale for this feature to work.
In stead of messing around with sockets and potentially removing them, breaking things in a way that might trigger support, I think we should:
- Drop the fake status
- Check if the tailscaled socket is present
- Verify that it is running and is logged into the headscale of this machine,
- Fatal if these conditions do not hold
This means that the config option verify_clients
needs to state how it works and what the prerequisites are, and we need good error messages for the different failure conditions.
enable_socket_api
is dropped.
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.
It is not difficult to detect whether tailscaled is running locally, as it has already been implemented in PR #1400. By enabling the derper setting option, derper will automatically perform the detection.
However, we need to clarify what the ultimate goal of this feature is:
- If we still require deploying a separate tailscaled instance, it means we are not considering portability.
- If we verify whether tailscaled is logged into the current headscale, it means we are changing the operational mode of derper(the official derper doesn't care about which server tailscale is logged into).
If our goal is to "support verify-clients like the official derper" we simply need to add a configuration and make code modifications similar to PR #1400.
If our goal is to "support verify-clients like the official derper while making deployment more convenient" then we only need to simulate a local socket API.
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 think I would not have it mess with the official socket, I'm not oppose to the simulation, but I do not want a scenario where sockets might be deleted causing very hard to debug scenarios.
An alternative could be that the simulation uses a different socket, and if that option is set, then derper is told to look at that socket, instead of the official path. e.g. /var/lib/headscale/derp_sim.sock
Even better, if you can trick it to not need a socket, that would be ideal.
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.
Changing the socket file path is indeed the best way to go, but it cannot be achieved currently without modifying the official derper code of tailscale.
The official derper will always use tailscale.Status() to get the status, and this code will always use the default socket path.
add `enable_socket_api` config Signed-off-by: kovacs <mritd@linux.com>
reformat changelog Signed-off-by: kovacs <mritd@linux.com>
How can this PR be improved? Is there any clear direction? |
|
||
# If true, headscale will simulate a socket API, which allows client authentication to be | ||
# completed without running tailscaled independently. | ||
enable_socket_api: false |
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.
If you managed to implement the alternative socket route as proposed, I'm tempted to say that we don't have this option, and always use the simulated socket if someone turns on verify_clients.
If not, I think this needs a better name.
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.
It is currently unlikely to adjust the fake socket file path 😥. Do you have any suggestions for naming this field? (I apologize for English not being my native language.)
Hi all, Just a quick check-in, what's the current status of this PR? Do we have a specific direction we're heading in? It seems like there hasn't been any progress lately. Could anyone please provide an update? |
Add a local api to support derper's client validation #740
Signed-off-by: kovacs mritd@linux.com