tailscale-status icon indicating copy to clipboard operation
tailscale-status copied to clipboard

Custom server - exit nodes

Open lennartbrandin opened this issue 2 years ago • 4 comments

When using a different tailscale control server (Such as headscale) you need to specify the server with most of the commands:

/usr/bin/tailscale up --login-server https://tail.domain.com --exit-node=100.10.0.4 --reset --operator=user --reset

Tailscale-status does not respect this when trying to switch exit nodes, it tries the command without --login-server:

pkexec[38133]: user: Executing command [USER=root] [TTY=unknown] [CWD=/home/user] [COMMAND=/usr/bin/tailscale up --exit-node=100.10.0.4 --reset --operator=user --reset]
gnome-shell[28872]: failed @ cmdTailscale

lennartbrandin avatar May 10 '23 21:05 lennartbrandin

@lennartbrandin Support for this has been added in the latest commit, let me know if you have any suggestions for improvements!

maxgallup avatar Jul 18 '23 19:07 maxgallup

I deleted my previous answer because i missed the tailscale-status extension settings. Switching exit nodes is still faulty but im missing whats going wrong.

Issue

Switching via ts-status does not work:

Executing command [USER=root] [TTY=unknown] [CWD=/home/myhome] [COMMAND=/usr/bin/tailscale up --exit-node=myexitnode --reset --login-server=https//my.headscale.com --operator=myuser --reset --login-server=https//my.headscale.com]
🟡 [tailscale-status]: failed @ cmdTailscale

because:

$ sudo /usr/bin/tailscale up --exit-node=myexitnode --reset --login-server=https//my.headscale.com --operator=myuser --reset --login-server=https//my.headscale.com
can't change --login-server without --force-reauth

This is odd because i made sure the domain is the same when initially connecting and executing the command with an exit node. Even more odd, adding --force-reauth does raise issues with the client (this is probably headscales issue):

Jul 18 21:50:22 myhostname sudo[7155]: pam_unix(sudo:session): session opened for user root(uid=0) by user(uid=1000)
Jul 18 21:50:22 myhostname tailscaled[1133]: Start
Jul 18 21:50:22 myhostname tailscaled[1133]: control: client.Shutdown()
Jul 18 21:50:22 myhostname tailscaled[1133]: control: client.Shutdown: inSendStatus=0
Jul 18 21:50:22 myhostname tailscaled[1133]: control: mapRoutine: quit
Jul 18 21:50:22 myhostname tailscaled[1133]: control: Client.Shutdown done.
Jul 18 21:50:22 myhostname tailscaled[1133]: active login:
Jul 18 21:50:22 myhostname tailscaled[1133]: control: NetInfo: NetInfo{varies=false hairpin=false ipv6=false ipv6os=true udp=true icmpv4=false derp=#4 portmap=UC link=""}
Jul 18 21:50:22 myhostname tailscaled[1133]: Backend: logs: be:b959e4b5b189b3c9ca2ab8b9ed1d1ec03aa558b3ba28fe898c67f9147c8b790a fe:
Jul 18 21:50:22 myhostname tailscaled[1133]: control: client.Login(false, 0)
Jul 18 21:50:22 myhostname tailscaled[1133]: control: doLogin(regen=false, hasUrl=false)
Jul 18 21:50:22 myhostname tailscaled[1133]: Received error: fetch control key: Get "https//my.headscale.com/key?v=63": unsupported protocol scheme ""
Jul 18 21:50:22 myhostname tailscaled[1133]: StartLoginInteractive: url=false
Jul 18 21:50:22 myhostname tailscaled[1133]: control: client.Login(false, 2)
Jul 18 21:50:22 myhostname tailscaled[1133]: control: LoginInteractive -> regen=true
Jul 18 21:50:22 myhostname tailscaled[1133]: control: doLogin(regen=true, hasUrl=false)
Jul 18 21:50:22 myhostname tailscaled[1133]: Received error: fetch control key: Get "https//my.headscale.com/key?v=63": unsupported protocol scheme ""
Jul 18 21:50:22 myhostname tailscaled[1133]: control: LoginInteractive -> regen=true
Jul 18 21:50:22 myhostname tailscaled[1133]: control: doLogin(regen=true, hasUrl=false)
Jul 18 21:50:22 myhostname tailscaled[1133]: Received error: fetch control key: Get "https//my.headscale.com/key?v=63": unsupported protocol scheme ""
Jul 18 21:50:22 myhostname tailscaled[1133]: control: LoginInteractive -> regen=true
Jul 18 21:50:22 myhostname tailscaled[1133]: control: doLogin(regen=true, hasUrl=false)
Jul 18 21:50:22 myhostname tailscaled[1133]: Received error: fetch control key: Get "https//my.headscale.com/key?v=63": unsupported protocol scheme ""
Jul 18 21:50:22 myhostname tailscaled[1133]: control: LoginInteractive -> regen=true
Jul 18 21:50:22 myhostname tailscaled[1133]: control: doLogin(regen=true, hasUrl=false)
Jul 18 21:50:22 myhostname tailscaled[1133]: [RATELIMIT] format("control: doLogin(regen=%v, hasUrl=%v)")
Jul 18 21:50:22 myhostname tailscaled[1133]: Received error: fetch control key: Get "https//my.headscale.com/key?v=63": unsupported protocol scheme ""
Jul 18 21:50:22 myhostname tailscaled[1133]: [RATELIMIT] format("Received error: %v")
Jul 18 21:50:23 myhostname tailscaled[1133]: control: LoginInteractive -> regen=true
Jul 18 21:50:23 myhostname tailscaled[1133]: [RATELIMIT] format("control: LoginInteractive -> regen=true")
Jul 18 21:50:28 myhostname tailscaled[1133]: health("overall"): error: not logged in, last login error=fetch control key: Get "https//my.headscale.com/key?v=63": unsupported protocol scheme ""
Jul 18 21:50:29 myhostname tailscaled[1133]: Accept: TCP{100.64.0.5:22000 > 100.64.0.2:22000} 417 ok out
Jul 18 21:50:29 myhostname tailscaled[1133]: Drop: TCP{100.64.0.2:22000 > 100.64.0.5:22000} 232 destination not allowed
Jul 18 21:50:29 myhostname tailscaled[1133]: Drop: TCP{100.64.0.2:22000 > 100.64.0.5:22000} 64 destination not allowed
Jul 18 21:50:29 myhostname tailscaled[1133]: Drop: TCP{100.64.0.2:22000 > 100.64.0.5:22000} 231 destination not allowed
Jul 18 21:50:29 myhostname tailscaled[1133]: Drop: TCP{100.64.0.2:22000 > 100.64.0.5:22000} 64 destination not allowed
Jul 18 21:50:29 myhostname tailscaled[1133]: [RATELIMIT] format("%s: %s %d %s\n%s")
Jul 18 21:50:29 myhostname tailscaled[1133]: [RATELIMIT] format("control: doLogin(regen=%v, hasUrl=%v)") (7 dropped)
Jul 18 21:50:29 myhostname tailscaled[1133]: control: doLogin(regen=true, hasUrl=false)
Jul 18 21:50:29 myhostname tailscaled[1133]: [RATELIMIT] format("Received error: %v") (7 dropped)
Jul 18 21:50:29 myhostname tailscaled[1133]: Received error: fetch control key: Get "https//my.headscale.com/key?v=63": unsupported protocol scheme ""
Jul 18 21:50:31 myhostname gnome-shell[2148]: 🔴 [tailscale-status]: Error: unknown state

This completely breaks tailscale until (Even logout returns an error) logging in again (Either tailscale login or --login-server=https://my.headscale.com) works.

Solution

Using the simplest form of the exit node command works totally fine:

sudo tailscale up --exit-node=myexitnode --accept-routes --login-server=https://my.headscale.com --operator=myuser

lennartbrandin avatar Jul 18 '23 20:07 lennartbrandin

Weird, the only real difference between the command from ts-status and the one you put under solution seems to be that in the solution you also put --accept-routes and it doesn't include --reset. Could you maybe try the following commands and report back if they work so we can pin point the problem better? (can't reproduce any of the errors myself)

  • with --accept-routes only (should work, like you said): sudo tailscale up --exit-node=myexitnode --accept-routes --login-server=https://my.headscale.com --operator=myuser

  • with --reset only sudo tailscale up --exit-node=myexitnode --login-server=https://my.headscale.com --operator=myuser --reset

  • with --reset and --accept-routes sudo tailscale up --exit-node=myexitnode --accept-routes --login-server=https://my.headscale.com --operator=myuser --reset

  • without either sudo tailscale up --exit-node=myexitnode --login-server=https://my.headscale.com --operator=myuser

maxgallup avatar Jul 19 '23 17:07 maxgallup

  • with --accept-routes only sudo tailscale up --exit-node=myexitnode --accept-routes --login-server=https://my.headscale.com --operator=myuser it works as expected

  • with --reset only sudo tailscale up --exit-node=myexitnode --login-server=https://my.headscale.com --operator=myuser --reset it works

  • with --reset and --accept-routes sudo tailscale up --exit-node=myexitnode --accept-routes --login-server=https://my.headscale.com --operator=myuser --reset it works

  • without either sudo tailscale up --exit-node=myexitnode --login-server=https://my.headscale.com --operator=myuser fails:

Error: changing settings via 'tailscale up' requires mentioning all
non-default flags. To proceed, either re-run your command with --reset or
use the command below to explicitly mention the current value of
all non-default settings:

	tailscale up --exit-node=myexitnode --login-server=https://my.headscale.com --operator=myuser --accept-routes
  • with the intial flags + --force-reauth sudo tailscale up --exit-node=myexitnode --reset --login-server=https//my.headscale.com --operator=myuser --reset --login-server=https//my.headscale.com --force-reauth it gets stuck
Aug 01 13:46:18 myhostname sudo[25058]:  myuser : TTY=pts/3 ; PWD=/home/myuser ; USER=root ; COMMAND=/usr/bin/tailscale up --exit-node=myexitnode --reset --login-server=https//my.headscale.com --operator=myuser --reset --login-server=https//my.headscale.com --force-reauth
Aug 01 13:46:18 myhostname sudo[25058]: pam_unix(sudo:session): session opened for user root(uid=0) by myuser(uid=1000)
Aug 01 13:46:18 myhostname tailscaled[1019]: Start
Aug 01 13:46:18 myhostname tailscaled[1019]: control: client.Shutdown()
Aug 01 13:46:18 myhostname tailscaled[1019]: control: client.Shutdown: inSendStatus=0
Aug 01 13:46:18 myhostname tailscaled[1019]: control: mapRoutine: quit
Aug 01 13:46:18 myhostname tailscaled[1019]: control: Client.Shutdown done.
Aug 01 13:46:18 myhostname tailscaled[1019]: active login:
Aug 01 13:46:18 myhostname tailscaled[1019]: control: NetInfo: NetInfo{varies=false hairpin=false ipv6=false ipv6os=true udp=true icmpv4=false derp=#8 portmap=UC link=""}
Aug 01 13:46:18 myhostname tailscaled[1019]: Backend: logs: be:b959e4b5b189b3c9ca2ab8b9ed1d1ec03aa558b3ba28fe898c67f9147c8b790a fe:
Aug 01 13:46:18 myhostname tailscaled[1019]: control: client.Login(false, 0)
Aug 01 13:46:18 myhostname tailscaled[1019]: control: doLogin(regen=false, hasUrl=false)
Aug 01 13:46:18 myhostname tailscaled[1019]: Received error: fetch control key: Get "https//my.headscale.com/key?v=65": unsupported protocol scheme ""
Aug 01 13:46:18 myhostname tailscaled[1019]: StartLoginInteractive: url=false
Aug 01 13:46:18 myhostname tailscaled[1019]: control: client.Login(false, 2)
Aug 01 13:46:18 myhostname tailscaled[1019]: control: LoginInteractive -> regen=true
Aug 01 13:46:18 myhostname tailscaled[1019]: control: doLogin(regen=true, hasUrl=false)
Aug 01 13:46:18 myhostname tailscaled[1019]: Received error: fetch control key: Get "https//my.headscale.com/key?v=65": unsupported protocol scheme ""
Aug 01 13:46:18 myhostname tailscaled[1019]: control: LoginInteractive -> regen=true
Aug 01 13:46:18 myhostname tailscaled[1019]: control: doLogin(regen=true, hasUrl=false)
Aug 01 13:46:18 myhostname tailscaled[1019]: Received error: fetch control key: Get "https//my.headscale.com/key?v=65": unsupported protocol scheme ""
Aug 01 13:46:19 myhostname tailscaled[1019]: control: LoginInteractive -> regen=true
Aug 01 13:46:19 myhostname tailscaled[1019]: control: doLogin(regen=true, hasUrl=false)
Aug 01 13:46:19 myhostname tailscaled[1019]: Received error: fetch control key: Get "https//my.headscale.com/key?v=65": unsupported protocol scheme ""
Aug 01 13:46:19 myhostname tailscaled[1019]: Accept: TCP{100.64.0.5:22000 > 100.64.0.2:22000} 472 ok out
Aug 01 13:46:19 myhostname tailscaled[1019]: control: LoginInteractive -> regen=true
Aug 01 13:46:19 myhostname tailscaled[1019]: control: doLogin(regen=true, hasUrl=false)
Aug 01 13:46:19 myhostname tailscaled[1019]: [RATELIMIT] format("control: doLogin(regen=%v, hasUrl=%v)")
Aug 01 13:46:19 myhostname tailscaled[1019]: Received error: fetch control key: Get "https//my.headscale.com/key?v=65": unsupported protocol scheme ""
Aug 01 13:46:19 myhostname tailscaled[1019]: [RATELIMIT] format("Received error: %v")
Aug 01 13:46:19 myhostname tailscaled[1019]: Drop: TCP{100.64.0.2:22000 > 100.64.0.5:22000} 197 destination not allowed
Aug 01 13:46:19 myhostname tailscaled[1019]: control: LoginInteractive -> regen=true
Aug 01 13:46:19 myhostname tailscaled[1019]: [RATELIMIT] format("control: LoginInteractive -> regen=true")
Aug 01 13:46:19 myhostname tailscaled[1019]: Drop: TCP{100.64.0.2:22000 > 100.64.0.5:22000} 197 destination not allowed
Aug 01 13:46:19 myhostname tailscaled[1019]: Drop: TCP{100.64.0.2:22000 > 100.64.0.5:22000} 197 destination not allowed
Aug 01 13:46:19 myhostname tailscaled[1019]: Drop: TCP{100.64.0.2:22000 > 100.64.0.5:22000} 64 destination not allowed
Aug 01 13:46:19 myhostname tailscaled[1019]: [RATELIMIT] format("%s: %s %d %s\n%s")
Aug 01 13:46:19 myhostname tailscaled[1019]: health("overall"): error: not logged in, last login error=fetch control key: Get "https//my.headscale.com/key?v=65": unsupported protocol scheme ""
Aug 01 13:46:25 myhostname tailscaled[1019]: [RATELIMIT] format("Received error: %v") (7 dropped)
Aug 01 13:46:25 myhostname tailscaled[1019]: Received error: fetch control key: Get "https//my.headscale.com/key?v=65": unsupported protocol scheme ""
Aug 01 13:46:27 myhostname tailscaled[1019]: Received error: fetch control key: Get "https//my.headscale.com/key?v=65": unsupported protocol scheme ""
Aug 01 13:46:27 myhostname tailscaled[1019]: [RATELIMIT] format("Received error: %v")
Aug 01 13:46:29 myhostname tailscaled[1019]: [RATELIMIT] format("control: LoginInteractive -> regen=true") (8 dropped)
Aug 01 13:46:29 myhostname tailscaled[1019]: control: LoginInteractive -> regen=true
Aug 01 13:46:29 myhostname tailscaled[1019]: [RATELIMIT] format("control: doLogin(regen=%v, hasUrl=%v)") (9 dropped)
Aug 01 13:46:29 myhostname tailscaled[1019]: control: doLogin(regen=true, hasUrl=false)
Aug 01 13:46:30 myhostname tailscaled[1019]: portmapper: failed to get PCP mapping: PCP is implemented but not enabled in the router
Aug 01 13:46:31 myhostname tailscaled[1019]: portmapper: failed to get PCP mapping: PCP is implemented but not enabled in the router

It can be resolved using sudo tailscale up --accept-routes --force-reauth --login-server=https://my.headscale.com --exit-node= --operator=myuser Note that it fails with --exit-node=myexitnode (invalid value "myexitnode" for --exit-node; must be IP or unique node name) but it works without specifying one or using the IP address instead.

lennartbrandin avatar Aug 01 '23 12:08 lennartbrandin