-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Headscale: Added an option to set an Access-Control-Allow-Origin resp… #2302
base: main
Are you sure you want to change the base?
Conversation
http_Headscale_tutorial.md
Outdated
@@ -0,0 +1,99 @@ | |||
# Setting Up a Simple Headscale Control Server Using HTTP |
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 dont think this is the place for this documentation, and we have our own documentation. This looks like internal notes.
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.
You are correct this has been reverted
config-example.yaml
Outdated
# - "*" to allow access from any origin (not recommended for sensitive data). | ||
# - "http://example.com" to only allow access from a specific origin. | ||
# - "" to disable Cross-Origin Resource Sharing (CORS). | ||
Access-Control-Allow-Origin: "" |
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 does not follow the format of the config file and has not been discussed. This isnt really anything we need and people needing this can handle it in Nginx and the likes.
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 have modified the code to align with the requested configuration file format.
I did open an accompanying issue for discussion: #2301. I also see mentions of a project chat, could you point me to it?
The idea of this feature is to simplify the Headscale server setup and have everything in one place. Tailscale continues to grow in the browser sector; for example, they recently released their new SSH client.
Our company has just released WebVM 2.0, which is a virtual machine inside the browser. We use this product with Tailscale to establish fast peer-to-peer connections between machines.
With this small change, the Headscale setup for the browser would be much easier and much simpler, especially in combination with your integrated TLS support.
This feature has already been requested in two other issues but without success. Here are their references: #623 #1283 .
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 does not follow the format of the config file and has not been discussed. This isnt really anything we need and people needing this can handle it in Nginx and the likes.
FYI expecting people to rely on a reverse proxy to intercept requests and inject CORS is introducing a large amount of user-side complexity that doesn't need to be there. I (as the maintainer of headscale ui) get people confused about this pretty much twice a month and opening issues as a result, even when the troubleshooting steps are listed (twice) on the front page readme.
A simple UI_DOMAIN
configuration that optionally sets the appropriate CORS information would solve a lot of issues. I would not suggest allowing *
anyway since browsers are planning to block that syntax.
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.
A simple
UI_DOMAIN
configuration that optionally sets the appropriate CORS information would solve a lot of issues. I would not suggest allowing*
anyway since browsers are planning to block that syntax.
We do want to keep the flexibility of using the *
available, but if indeed browsers are planning to block this syntax, I will make sure to update the feature to check for this syntax. To avoid any confusion, I would prefer to stick with the normal CORS syntax. This *
is indeed another security risk, but this flexibility is also possible by using a reverse proxy. However, if Headscale agrees to not allow *
, then I would gladly make another commit with a fix.
e07c42b
to
dfad6a1
Compare
Hi, I would like to know if there is a possibility to further discuss this feature? |
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 posted some comments, I do not know enough about this topic other than how little I know and that I never do it correctly. I am uncomfortable to add something that has security implications that I do not have the knowledge to say if correct, or will be a problem/need change in the future.
This has been done a lot of times before, and it has currently led to a maintenance burden that is so large that I dont really have time to spend time on PRs like this where I need to figure out what is the correct way (which then will potentially have the recursive effect of having me do this again later).
My main thing is not to be negative, I am not saying no, I am just saying that all of this things needs thought, and I have a lot of other inflight things atm.
config-example.yaml
Outdated
# - "*" to allow access from any origin (not recommended for sensitive data). | ||
# - "http://example.com" to only allow access from a specific origin. | ||
# - "" to disable Cross-Origin Resource Sharing (CORS). | ||
access_control_allow_origin: "" |
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 do not like this being a global setting, maybe it should be under api, or grpc or something.
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 @kradalby,
Yes I suggest to have an structure like this:
api:
cors_allow_origins: [] # as a list
or
cors:
allow_origins: [] # as a list
I would value your input on which approach you prefer.
func (h *Headscale) createRouter(grpcMux *grpcRuntime.ServeMux) *mux.Router { | ||
router := mux.NewRouter() | ||
router.Use(prometheusMiddleware) | ||
|
||
if h.cfg.AccessControlAllowOrigins != "" { | ||
router.Use(h.corsHeadersMiddleware) |
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 do not think this should be added for all endpoints, it should only be needed for the 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.
Hi @kradalby,
Thank you for your feedback. I understand your concern about applying this to all endpoints.
I agree that not all endpoints require CORS headers. However, the Tailscale Client does use several non-API routes — specifically /register
, /key
, /machine
, /derp
, /verify
and /health
— to communicate with the Headscale server via HTTP requests. For these endpoints, implementing CORS headers is necessary to allow proper functionality when CORS is enabled. Additionally, the Tailscale SSH web client operates for example in a similar manner.
At the same time, I understand that certain endpoints such as /apple
, /windows
, and /swagger
do not need CORS headers.
I will give you a code draft of our idea on how to implement this in a simple matter.
If you have any questions feel free to ask me for any clarification if needed.
config-example.yaml
Outdated
@@ -40,6 +40,13 @@ grpc_listen_addr: 127.0.0.1:50443 | |||
# are doing. | |||
grpc_allow_insecure: false | |||
|
|||
# The Access-Control-Allow-Origin header specifies which origins are allowed to access resources. | |||
# Options: | |||
# - "*" to allow access from any origin (not recommended for sensitive data). |
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 dont really like giving people footguns, so I do not think we should allow *, and force people to do domains explicitly.
If it can be a list of domains, it should be a list data structure or something similar.
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 @kradalby,
Thank you for your input. I completely understand the concern about providing a wildcard *
and the importance of specifying domains explicitly.
We can certainly disable the use of *
for domain whitelisting and enforce explicit domain declarations. Our initial idea was to implement an "Allow list" where users can specify any allowed domain.
As recommended by MDN: If the server supports clients from multiple origins, it must return the origin for the specific client making the request.
Additionally, MDN advises adding the Vary: Origin
header to inform clients that the response varies based on the Origin
header.
Further information and recommendations can be found https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin.
I will show you a code draft to implement this feature soon. Feel free to give any feedback on the idea.
…onse header to enable Cross-Origin Resource Sharing (CORS)
dfad6a1
to
68ce697
Compare
… enable cors for specific endpoints (#2)
Hi @kradalby, I hope this message finds you well. As per your recent comments, I have made some changes to the code. I'll wait once you have the time available to review the updated code. |
Hi @kradalby, Would it be possible to continue the discussion of this PR? |
Sorry, I have been swamped, I've read up a bit this morning and this is my thoughts: I think these headers should be limited to the api, that covers the main use case of allowing CORS for the different WebUIs. I do not think we should add it to all the other endpoints, that is quite an exotic use case and while I agree with @routerino that it is bad UX to ask people using the API and WebUI to setup a proxy to have CORS, I do think that this is exotic enough to say that you need to do it in a proxy. I do not really want to support |
add a header to enable Cross-Origin Resource Sharing (CORS) #2301