Short-Lived Certificate in Browser SSH doesn't work at all

TL; DR: I have exactly the same problem as “Short lived certificates and browser renderings (https://community.cloudflare.com/t/short-lived-certificates-and-browser-renderings/292326)”. Is there any workaround?

Situation: Browser SSH doesn’t treat short-lived cert

I’m using Cloudflare Tunnel proxying into my private network via SSH over HTTPS with short-lived certificate authentication enabled.
As the the server and IdP username don’t match, I adapted the workaround with AuthorizedPrincipalsFile directive in sshd_config.
With this setting, short-lived certs auth works really nicely with ssh command with cloudflared as a proxy command.
Then I tried to use it also on Browser SSH, as the documentation states (https://developers.cloudflare.com/cloudflare-one/identity/users/short-lived-certificates/#connect-through-a-browser-based-terminal):

End users can connect to the SSH session without any configuration by using Cloudflare’s browser-based terminal. Users visit the URL of the application and Cloudflare’s terminal handles the short-lived certificate flow. To enable, follow the instructions here.

As I’ve already set up Browser SSH, I open the tunnel URL in browser (both Safari and Google Chrome tested). But what I came up with is:

  1. Login Panel (if login info haven’t expired; otherwise this is skipped)
  2. Username prompt
  3. Login prompt for SSH, stating that Alternatively, you can use short-lived certificates for seamless authentication using your SSO., although I’ve already setup the server to accept short-lived certs!:

At this point, I have no idea how to proceed with short-lived cert auth with Browser SSH.
I would appreciate if someone provide a hint to enable short-lived certs only on Browser SSH.

I attach the configuration detail below for reference.

Thank you in advance.a


Configuration Details

I have the following configuration (with sub/domain and port details anonymised):

Server: Running SSH on non-well-known port (say, 2222)

Running cloudflared daemon.

Tunnel: configured with Cloudflare Web UI

  • Binding tunnel.<my-domain>.com to ssh://127.0.0.1:2222 in Public Hostname pane.
  • Private Network has no item at all.
  • At the first try, this was set up solely with cloudflared CLI command, which also did not work. Then I switched to

Application “Tunnel”: Pointing to tunnel.<my-domain>.com.

  • Type: Browser SSH
  • Overview:
    • Application Appearance:
      • Enable App Launcher
      • Use default (first domain will be used): tunnel..com
      • Use custom domain:
    • Block pages:
      • Identity failure block page: Cloudflare default
      • Cloudflare error text: Unauthorized
      • Non-identity failure block page: Cloudflare default
  • Policies: Only 1 (Allow admin)
    • Allow, include my email as the only rule.
    • Additional settings
      • Purpose Justification
      • Purpose justification prompt: empty
      • Temporary authentication
      • Email addresses of the approvers: empty
  • Authentication:
    • Accept all available identity providers
    • Manually select identity providers: GitHub only
    • Instant Auth
      • Skip identity provider selection if only one is configured

Settings

  • CORS Settigns
    • Access-Control-Allow-Credentials
    • Access-Control-Max-Age (seconds): 86400
    • Access-Control-Allow-Origin:
      • Allow all origins
      • values: *
    • Access-Control-Allow-Methods: Allow all methods
    • Access-Cotrol-Allow-Headers: Allow all headers, header name empty.
  • Cookie Settings:
    • HTTP Only
    • Enable Binding Cookie
    • Enforce cookie path attribute
    • Same Site Attribute:
  • Additional Settings:
    • Enable automatic cloudflared authentication
    • Browser Rendering: SSH
1 Like

Side note: sorry for unreadability due to the raw URL. It seems discourse bans making links in posts for newcommers (this is really annoying, but I understand that you must prevent ad-bots…)

Couple of quick sanity checks.

  1. Have you added the public CA ssh key to your sshd_config file?
  2. Have you restarted the sshd service after making the change?

Hi @Cyb3r-Jak3, thank you for your reply!

  1. Have you added the public CA ssh key to your sshd_config file?

Yes, and the server successfully authenticates with short-lived certs when I connect with ssh + cloudflared command, that said, it succeeds to login even I remove the publickey from server entirely. Short-lived cert auth fails only on Browser SSH.

For record, here is the related lines in sshd_config:

PubkeyAuthentication yes
TrustedUserCAKeys /etc/ssh/ca.pub
  1. Have you restarted the sshd service after making the change?

Yes. I even rebooted the server for several times.

Do you see anything in the systemd logs for either sshd (sudo systemctl status sshd) or cloudflared (sudo systemctl status cloudflared)? Can you check to see if you see WAF events (https://dash.cloudflare.com/?to=/:account/:zone/security/events) for your source IP address?

I skimmed through sshd log.

Setting: user as the login name in the Ubuntu, while mail.user an ID determined by IdP.


$ sudo journalctl -u ssh -f

9月 01 02:32:11 bastion sshd[41477]: pam_unix(sshd:session): session opened for user user(uid=1001) by (uid=0)

9月 01 02:32:28 bastion sshd[41565]: Accepted publickey for user from 127.0.0.1 port 47396 ssh2: ECDSA-CERT SHA256:RBSjyWQXLFvBQrUeLmfsO5CNQerwp6xf7UakqLaNQes ID c410b0a4a14f4b4f3931de861d3caff7 (serial 14329998133876782226) CA ECDSA SHA256:dPs2+6a+fHJ+dwMjlLAmAGt5+JR/J4VXYcLZlNinge4

9月 01 02:32:28 bastion sshd[41565]: pam_unix(sshd:session): session opened for user user(uid=1001) by (uid=0)

9月 01 02:32:43 bastion sshd[41671]: Invalid user mail.user from 127.0.0.1 port 44894

9月 01 02:32:43 bastion sshd[41671]: error: Received disconnect from 127.0.0.1 port 44894:13: Goodbye! [preauth]

9月 01 02:32:43 bastion sshd[41671]: Disconnected from invalid user mail.user 127.0.0.1 port 44894 [preauth]

The first successful login is through ssh command line, and the failed one is thru Browser SSH.

However, contrary to the expectation, it seems that ssh command login as user instead of mail.user. This seems because there is no UserName in ~/.ssh/config and the local user name is also user.

So, I tried to login explicitly as mail.user and it fails:


$ ssh -l mail.user tunnel.<my-domain>.com

mail.user@Username matches multiple emails: Permission denied (publickey).

And sshd log reports the failure:


9月 01 02:48:43 bastion sshd[42379]: Invalid user mail.user from 127.0.0.1 port 39832

9月 01 02:48:43 bastion sshd[42379]: Connection closed by invalid user mail.user 127.0.0.1 port 39832 [preauth]

This is rather suprising - I think I followed the “instruction in Username matches multiple emails(https://developers.cloudflare.com/cloudflare-one/identity/users/short-lived-certificates/)” and have the following lines at the end of /etc/ssh/sshd_config:


Match user user

AuthorizedPrincipalsFile /etc/ssh/users.txt

… and here is the contents of /etc/ssh/users.txt:


$ ls -lav /etc/ssh/users.txt

-rw-r--r-- 1 root root 18 8月 21 14:20 /etc/ssh/users.txt

$ cat /etc/ssh/users.txt

user

mail.user

I think this follows the instruction and mail.user should be able to logged in as user. Is there anything that I overlooked?

(sorry for the mess… It seems that I am not eligible to edit my own post for now and to have to delete and repost the editied version)

I’ve just reread through the document again, and now I realised that the AuthorizedPrincipals*-based approach always requires explicit specification of username on the server, otherwise SSHD cannot find the correct Matching AuthorizedPrincipalsFile rule(s).
It seems that SSH’s username parameter must exist as the Linux user name (https://stackoverflow.com/a/59759981).

So, here is what’s going on I guess:

  1. Browser SSH first tries to use mail.user as a user name to login to the ssh
  2. SSH denies it as the user mail.user doesn’t exist.
  3. Browser SSH fallbacks to the general login panel
  4. The general login panel doesn’t handle short-lived certs and so only Password and/or Pubkey auth is supported.

To overcome this issue, I think it would be good to have at least one of the following in short-lived cert mechanism:

  1. A mechanism to map identities from IdP to another one
    • In this case, I want to configure configure to map mail.user (from GitHub as an IdP) to user on the cloudflare side; or,
    • It would also mediate the concern that the different IdP accidentally provides the same identity to diffrent user (say, [email protected] and [email protected] could result in the same user name).
  2. Browser SSH additionally supports short-lived cert auth also after specifying login name after the internal failure of login failure with the principal provided by IdP.

Is there any possibility to support either (or both) of them in near future?

Hi, I’m also facing this exact issue, any update?