Description
Problem
Browser SSH fails to connect to a host whose SSH access rule uses action: "check".
The session hangs and ends with:
ssh: handshake failed: read tcp ...:22: i/o timeout
Native tailscale ssh to the same host works, and browser SSH works with
action: "accept" — only check is affected.
Cause
In check mode, tailscaled on the target sends the re-authentication URL
(# To authenticate, visit: https://...) as a pre-auth SSH banner
(tailssh SendAuthBanner). The WASM client in internal/hp_ipn/ssh.go builds
its ssh.ClientConfig without a BannerCallback, so the banner — and with it
the URL — is silently dropped. The user never sees the URL, the check is never
completed, and the connection runs into the read deadline.
Suggested fix
Set a BannerCallback that forwards the banner to the terminal, and extend the
read deadline once a banner arrives (completing SSO takes longer than 30s):
BannerCallback: func(msg string) error {
s.Config.OnData(strings.ReplaceAll(msg, "\n", "\r\n"))
conn.SetReadDeadline(time.Now().Add(60 * time.Second))
return nil
},
Since the terminal has copy/selection disabled, the printed URL is not clickable;
ideally it is opened directly (e.g. window.open from the WASM side) or rendered
as a clickable link.
Workaround
Use action: "accept" instead of "check" for the SSH rule (loses periodic
re-authentication).
Info
I know more a upstream topic but the client ist part of your release and you already implement patches for the client.
Headplane Version
v0.7
Headscale Version
v0.29.2
Description
Problem
Browser SSH fails to connect to a host whose SSH access rule uses
action: "check".The session hangs and ends with:
ssh: handshake failed: read tcp ...:22: i/o timeout
Native
tailscale sshto the same host works, and browser SSH works withaction: "accept"— onlycheckis affected.Cause
In check mode,
tailscaledon the target sends the re-authentication URL(
# To authenticate, visit: https://...) as a pre-auth SSH banner(tailssh
SendAuthBanner). The WASM client ininternal/hp_ipn/ssh.gobuildsits
ssh.ClientConfigwithout aBannerCallback, so the banner — and with itthe URL — is silently dropped. The user never sees the URL, the check is never
completed, and the connection runs into the read deadline.
Suggested fix
Set a
BannerCallbackthat forwards the banner to the terminal, and extend theread deadline once a banner arrives (completing SSO takes longer than 30s):
Since the terminal has copy/selection disabled, the printed URL is not clickable;
ideally it is opened directly (e.g. window.open from the WASM side) or rendered
as a clickable link.
Workaround
Use action: "accept" instead of "check" for the SSH rule (loses periodic
re-authentication).
Info
I know more a upstream topic but the client ist part of your release and you already implement patches for the client.
Headplane Version
v0.7
Headscale Version
v0.29.2