cloudflared icon indicating copy to clipboard operation
cloudflared copied to clipboard

Access SSH with short-lived-cert doesn't work on Windows

Open jreed509 opened this issue 4 years ago • 2 comments

Hi,

I've been following the short-lived-cert documentation, and I had no trouble setting things up on the server-side and on my Mac and Linux clients. But I haven't been able to get things working on Windows clients.

The issue appears to be with the ssh config generated by the cloudflared daemon. For example, running cloudflared access ssh-config --hostname mysever.mydomain.com --short-lived-cert as recommended in the docs generates the following ssh config entries:

Host mysever.mydomain.com
    ProxyCommand bash -c 'cloudflared access ssh-gen --hostname %h; ssh -tt %[email protected] >&2 <&1'

Host cfpipe-vm.example.com
    HostName mysever.mydomain.com
    ProxyCommand cloudflared access ssh --hostname %h
    IdentityFile ~/.cloudflared/mysever.mydomain.com-cf_key
    CertificateFile ~/.cloudflared/mysever.mydomain.com-cf_key-cert.pub

Copying these to the ssh config file and trying to run ssh [email protected] returns this error on Windows (typical error when a command in ProxyCommand does not exist):

> ssh [email protected]
CreateProcessW failed error:2
posix_spawnp: No such file or directory

I think I've narrowed this down to 2 issues in the generated ProxyCommand entry:

  1. The ProxyCommand relys on bash which is not installed on Windows
  2. Windows requires a full path to cloudflared.exe which is not present in the generated config.

I've tried a bit to resolve this by editing the ProxyCommand, but I haven't gotten things fully working yet. Here's what I've tried so far:

  • Replacing cloudflared and ssh with full paths to the respective .exe files
  • Re-writing the ProxyCommand to use cmd instead of bash
Host mysever.mydomain.com
    ProxyCommand /path/to/cloudflared.exe access ssh-gen --hostname %h && /path/to/ssh.exe -tt %[email protected] >&2 <&1

Host cfpipe-vm.example.com
    HostName mysever.mydomain.com
    ProxyCommand /path/to/cloudflared.exe access ssh --hostname %h
    IdentityFile ~/.cloudflared/mysever.mydomain.com-cf_key
    CertificateFile ~/.cloudflared/mysever.mydomain.com-cf_key-cert.pub

Running the ssh command with this change does open a browser window for Access authentication (and generates the short-lived-certs), but it doesn't redirect me to my remote terminal. Instead I get the following error:

> ssh [email protected]
kex_exchange_identification: Connection closed by remote host

Additionally, running just the 2nd half of the ProxyCommand manually (/path/to/ssh.exe -tt [email protected]) works as expected and directs me to the remote terminal.

However, the issue with this command alone is that the short-lived-certs aren't generated automatically so I won't be able to log in again after the certs expire.

Any recommendations on how to configure the SSH Config file for use on Windows?

jreed509 avatar May 21 '21 13:05 jreed509

After some more troubleshooting I managed to find a (imperfect) workaround. I modified the the ssh config to be only a single entry and to use cmd:

Host myserver.mydomain.com
  ProxyCommand cmd /c "\path\to\cloudflared.exe access ssh-gen --hostname %h && \path\to\cloudflared.exe access ssh --hostname %h"
  IdentityFile ~/.cloudflared/myserver.mydomain.com-cf_key
  CertificateFile ~/.cloudflared/myserver.mydomain.com-cf_key-cert.pub

Although this command "works" its not quite perfect. The first time the client executes the ssh command, the browser opens to the Cloudflare Access page to approve the connection and generates the cert files, but the connection fails with:

 Permission denied (publickey).

Attempting to log in a second time with the ssh command after the certs were created in the previous attempt works as expected and I'm connected to the remote terminal.

Obviously this workflow is not ideal and I needed to modify my ssh config fairly significantly from what was generated by the cloudflared daemon.

jreed509 avatar May 21 '21 16:05 jreed509

Not sure if you found another solution to this but I was struggling with a very similar issue. I kept getting the cf_key: No such file or Directory along with Permission denied (publickey) error.

After taking a closer look at the output I noticed that it was trying to use my local user and not the remote user to login. So simply added User remoteuser to my ssh config. The docs do mention that you need a user that matches your Identity Providers username. But fail to mention that you need add the User option to your ssh config. Below is the full example of my ssh config

Host jump.atmydomain.com
  ProxyCommand bash -c '/usr/local/bin/cloudflared access ssh-gen --hostname %h; ssh -tt %[email protected] >&2 <&1'
  User remoteusername

Host cfpipe-jump.atmydomain.com
  HostName jump.atmydomain.com
  ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h
  IdentityFile ~/.cloudflared/jump.atmydomain.com-cf_key
  CertificateFile ~/.cloudflared/jump.atmydomain.com-cf_key-cert.pub

eduardo-robles avatar Apr 21 '22 14:04 eduardo-robles