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

Support for WireGuard only peers #1545

Open
Nemo157 opened this issue Sep 7, 2023 · 26 comments
Open

Support for WireGuard only peers #1545

Nemo157 opened this issue Sep 7, 2023 · 26 comments
Labels
enhancement New feature or request help wanted Extra attention is needed needs design doc needs investigation

Comments

@Nemo157
Copy link

Nemo157 commented Sep 7, 2023

Why

Tailscale just announced their support for integrated Mullvad exit nodes. Being able to configure a similar setup via Headscale and an independent Mullvad account (or other wireguard VPN provider) would be useful for those of us without a Tailscale account.

Description

I haven't looked deeply into the details, but it's my understanding that this is implemented via a "WireGuard only peer" feature, and then support in the Tailscale coordination server to synchronize these peers with Mullvad. I assume it would be possible for Headscale to allow manually configuring these peer types.

@Nemo157 Nemo157 added the enhancement New feature or request label Sep 7, 2023
@sachiniyer
Copy link

sachiniyer commented Sep 7, 2023

It also seems like mullvad publishes a script to connect to mullvad servers. The most interesting thing is that you basically link public keys with your account (which is why I think that there is a preconfiguration step to register devices in their announcement).

It seems like the simplest implementation could be to create an external script that calls registerNodeCmd on mullvad endpoints (marking them as WireguardOnly), and then calling the mullvad api with each of the node's public keys you want to link.

I think the RegisterMachine, machine config, and node conversion would need to be changed.

(I also am really not an expert in this, so please take it with a grain of salt)

Edit: what needs to be changed

@averywinters
Copy link

averywinters commented Sep 11, 2023

I think this was intended by the issue author, but to reiterate it seems more useful to me to allow any generic WireGuard-only peer as an exit node, not just Mullvad servers. That way headscale doesn't have to be tied to one VPN provider like the Tailscale coordination server currently is.

@averywinters
Copy link

It might be possible to support this for any WireGuard server peer by accepting peer config files like those generated by Mullvad's WireGuard config file generator like described in this guide, or by just asking the user to provide the generated fields we need at the CLI when adding the peer.

@Nemo157
Copy link
Author

Nemo157 commented Sep 11, 2023

I don't think it's possible to import a generated config file, because that contains a randomized private key. The provider needs to support uploading the existing public key from the devices that will connect. That doesn't seem possible through Mullvad's website, it wants the private key specified so it can embed it in the generated config files, but it is possible through the API. I haven't used other wireguard based vpn services so I'm not sure if being able to upload existing keys is common.

@JadedHearth
Copy link

Why would it be required to upload an existing public key?

@averywinters
Copy link

@WoodenMaxim From what I can tell, each Tailscale node only has a single private/public key pair that is generated when they are created, and then it uses that pair with every other node. So, when adding a non-Tailscale WireGuard endpoint like a Mullvad server, that other end needs to know (all of the) existing Tailscale nodes' public keys that are going to connect to it.

@noseshimself
Copy link

How does adding a Wireguard-only exit node get the public key of the nodes intending to use it into that node's configuration? If there was an easy solution for this we would not need Tailscale...

@infogulch
Copy link

How does mullvad do it?

@noseshimself
Copy link

How does mullvad do it?

No. "How does Tailscale do it?" Obviously by being a kind of "reseller" and having an interface to provision the mullvad IAM that way. The more interesting question is how the tailscale client is selecting the "exit node" it wants to use.

I was already wondering about this in other settings. If there are multiple possible exit nodes for a destination or multiple Internet gateways how is the most appropriate node selected and how can I influence the choice?

@infogulch
Copy link

infogulch commented Sep 27, 2023

https://tailscale.com/kb/1103/exit-nodes/?tab=linux

tailscale up --exit-node=<exit-node-ip>

With that resolved, we still need to figure out how to get the wireguard public keys of the tailscale nodes with permission to access the exit node into the wireguard-only peer, and vice-versa.

Maybe it's as simple as "run a command to dump the full list of keys in a form that the wireguard-only peer can consume, and expect the admin to put that configuration onto the node (and keep it up to date) manually". That may not be very palatable, but the alternative is writing software to sync keys automatically in which case why not just run a full tailscale node?

Maybe the best solution would be to just add some example docs showing how you can execute this pattern with a regular tailscale node...

@sosnik
Copy link

sosnik commented Sep 28, 2023 via email

@infogulch
Copy link

Very interesting, thanks for sharing sosnik.

https://github.com/mullvad/mullvad-wg.sh/blob/main/mullvad-wg.sh#L59

curl -sSL https://api.mullvad.net/wg -d account="$ACCOUNT" --data-urlencode pubkey="$(wg pubkey <<<"$PRIVATE_KEY")"

Roughly the script:

  • Reads your mullvad account number from stdin
  • Downloads a full listing of mullvad relays from the api, including the id/"CODE", location, public key, and endpoint of each.
  • Uploads your public key to the mullvad api using your account number (see code quoted above)
  • Creates a wg config file for each relay named /etc/wireguard/$CODE.conf with aforementioned connection details so you can connect by running wg-quick up $CODE

I also found this gist that loosely documents uploading and revoking keys which may also be useful for mullvad: https://gist.github.com/izzyleung/98bcc1c0ecf424c1896dac10a3a4a1f8


So mullvad relays are configured via simple https POSTs to their api (which great, I love that they use simple tech). This may be useful if we want to implement mullvad support into headscale.

That said, it doesn't help us much if we just have a random wireguard relay sitting on a vps and we want to add "Support for WireGuard only peers", as the title of this issue suggests. Honestly I'm not even sure how we would expect a plain WG exit node to work in theory: Either you configure it completely manually, exporting private keys from tailnet nodes and importing them into the WG node which is annoying; or just... you know, install tailscale on that node instead, tailscale was invented to solve that annoyance in the first place.

With that in mind, I think we should open a new issue / retitle this issue to "Support for mullvad exit nodes" (if desired), and add a recipe to the docs showing how to set up your own exit node by running a headscale node on a vps or something, because a "WireGuard only peer" is a non starter.

@Nemo157
Copy link
Author

Nemo157 commented Sep 28, 2023

Either you configure it completely manually, exporting private keys from tailnet nodes and importing them into the WG node which is annoying

Just to clarify, you need to export public keys to configure the WG node (and import the WG nodes' public key into headscale).

I think there are still situations where this could be useful. One thought is that you want to connect devices to an organization managed WG node, where you don't have permission to install tailscale but you are able to provide your public keys to be configured on the node.

The other main reason I think to target just supporting "wireguard only peers" first is that they are the only thing that the tailscale protocol knows about. If they are supported by headscale then scripts can be written to configure them for whatever situation is needed, while if headscale instead only supports talking to the Mullvad API it blocks being able to configure for other situations. That doesn't mean headscale shouldn't support talking to Mullvad itself, but I think it should build on the general functionality of wireguard only peers.

@sosnik
Copy link

sosnik commented Sep 28, 2023 via email

@almereyda
Copy link

almereyda commented Sep 28, 2023

I strongly believe this would come with all the overhead involved in implementing a WireGuard management API, for which exist many examples.

Examples

Do we already know the API surface of the Tailscale coordination server, which needs to be mimicked by Headscale for supporting the client feature implemented in tailscale/tailscale#7821?


Practically speaking, it appears this use case will be much easier to achieve with a Tailscale network and a given WireGuard network residing in the same namespace, and routing being allowed between their subnets.

To continute to distinguish between (1) sole support for WireGuard peers and (2) a default route via an external WireGuard VPN:

  • Maybe a node can announce a route to the WG subnet, and that would be about it for "native WireGuard clients", for now?
  • For the VPN use case, maybe an exit node can announce the ::/0 route, and that is locally forwarded through the above subnet, given another ::/0 route would be inherited from there?

@infogulch
Copy link

Just to clarify, you need to export public keys

Thanks for the correction, please excuse my typo.


I'll relax my stance a bit here, it seems perfectly reasonable to allow headscale users to manually configure wireguard peers by exporting node public keys and importing remote endpoint public keys by some cli or api, and to expect VPN configuration scripts to be layered on top of this feature. Though, how it interacts with ACL and other tailscale features appears to present some non-trivial remaining challenges.


Wrt namespacing and routing, are routing "announcements" a thing in wg? The mullvad script explicitly sets config on the client to route ips over the interface with AllowedIPs = 0.0.0.0/0, ::/0. From that I'd guess the admin would have to set the route manually.

@sosnik
Copy link

sosnik commented Sep 28, 2023 via email

Copy link
Contributor

This issue is stale because it has been open for 90 days with no activity.

@github-actions github-actions bot added the stale label Dec 28, 2023
@Victor239
Copy link

Still relevant.

@github-actions github-actions bot removed the stale label Dec 29, 2023
@noseshimself
Copy link

Still relevant.

But still without any idea about the implementation by those who want it. To summarize: Tailscale (and a few others) exist because there is no simple auto-configuration for Wireguard links in the basic protocol. You either tell us how to introduce the Tailnet to some arbitrary wireguard (exit-)node or we can just as well close this for good.

@Nemo157
Copy link
Author

Nemo157 commented Dec 29, 2023

Tailscale already has the client-side feature for this, someone needs to investigate exactly how it is represented by the server and add it to the details provided by Headscale, there is no design work needed for the tailnet side of it. I'm pretty sure once the backend side of how to represent it is investigated the interface to configure that from the CLI will be relatively self-evident, so I'm not sure if there's any point in trying to design it externally. (I would have worked on this myself already, except I really dislike golang, maybe one day I'll eventually give up waiting for someone else and get over my aversion).

@smehrens
Copy link

smehrens commented Feb 7, 2024

I think this feature would be very helpful in several scenarios:

  1. clients with ssh but without headscale/tailscale client
  2. clients controlled by a deployment system like ansible, chef, puppet, intune, apple mdm
  3. clients controlled by second headscale server
  4. nodes belong to different company.

if you can

I) import to headscale
a) a dataset of nodename, owner, publickey, wireguard ip address, external address ... for each wireguard only node
II) export
a) a list of datasets for the headscale nodes, which should be able to connect these nodes
b) a n*m matrix which headscale node should be able to connect to which "wireguard" node
III) send a webhook if reconfiguration ist needed
the deployment tools should be able to do the rest.

Company rules could require to use a specific deployment tool and automation process so headscale client may be no option for some systems. Or company rules do not allow headscale installation without a time consuming certification process for every new software version.

Some appliances do not have support for head/tailscale and dont allow installing third party software, but allow deloyment over ssh, api, ldap or whatever.

A second headscale server may import the exported list and use this for federation.

Of course all these scenarios dont fit to the general idea of headscale, but .... maybe there no other way ....

@unixfox
Copy link

unixfox commented Mar 11, 2024

Does anyone have a mullvad account for testing? I want to check the traffic between the tailscale control plane and the tailscale client in order to understand how mullvad servers are served to the client.

If so, email me at github1545 [at] unixfox.eu

@sefidel
Copy link

sefidel commented Mar 11, 2024

@unixfox I want to check the traffic between the tailscale control plane and the tailscale client in order to understand how mullvad servers are served to the client.

I think you need a Tailscale account with Mullvad add-on for that.

Copy link
Contributor

This issue is stale because it has been open for 90 days with no activity.

@github-actions github-actions bot added the stale label Jun 10, 2024
@aniqueta
Copy link

Not stale.

@github-actions github-actions bot removed the stale label Jun 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed needs design doc needs investigation
Projects
None yet
Development

No branches or pull requests