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

Podman over SSH in native mode does not use custom config ~/.ssh/config #23831

Closed
evolutics opened this issue Sep 1, 2024 · 14 comments · Fixed by #23847
Closed

Podman over SSH in native mode does not use custom config ~/.ssh/config #23831

evolutics opened this issue Sep 1, 2024 · 14 comments · Fixed by #23847
Labels
kind/bug Categorizes issue or PR as related to a bug. stale-issue

Comments

@evolutics
Copy link

Issue Description

Connecting to a remote Podman socket over native SSH (e.g., podman --host ssh://my-host --ssh native ps) fails, despite the local ~/.ssh/config file containing an entry for Host my-host (i.e., ssh my-host succeeds).

Steps to reproduce the issue

Set up:

  1. Run a test VM locally using Vagrant:

    vagrant init bento/fedora-40
    vagrant up
  2. Set up SSH access to the VM:

    vagrant ssh-config --host my-host >>~/.ssh/config
    ssh my-host echo 'SSH setup is OK'
  3. Set up Podman on the VM (with Docker API), running an example container:

    ssh my-host <<EOF
    sudo dnf --assumeyes install podman
    podman info
    
    systemctl --user enable --now podman
    sudo loginctl enable-linger
    sudo ln --force --symbolic /usr/bin/podman /usr/local/bin/docker
    
    podman run --detach docker.io/hashicorp/http-echo:1.0
    EOF

Test:

  • Local Docker can connect to the remote Podman service, showing 1 container:

    docker --host ssh://my-host ps
    
  • But local Podman cannot connect to remote Podman – see error below:

    podman --host ssh://my-host --ssh native ps
    

Tear down:

  1. Remove Vagrant resources:

    vagrant destroy
    rm --force --recursive .vagrant Vagrantfile
    
  2. Undo changes to ~/.ssh/config.

Describe the results you received

$  podman --host ssh://my-host --ssh native ps
Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VM
Error: unable to connect to Podman socket: failed to connect: dial tcp: lookup my-host: device or resource busy: ssh://my-host

Describe the results you expected

$  docker --host ssh://my-host ps
CONTAINER ID   IMAGE                     COMMAND   CREATED              STATUS              PORTS     NAMES
abcdef123456   hashicorp/http-echo:1.0   ""        About a minute ago   Up About a minute             foo_bar

podman info output

$ podman version
Client:       Podman Engine
Version:      5.2.2
API Version:  5.2.2
Go Version:   go1.22.5
Built:        Tue Jan  1 01:00:00 1980
OS/Arch:      linux/amd64

$ uname --all
Linux foo-desktop 5.15.0-119-generic #129-Ubuntu SMP Fri Aug 2 19:25:20 UTC 2024 x86_64 GNU/Linux


$ vagrant ssh -- podman version
Client:       Podman Engine
Version:      5.2.2
API Version:  5.2.2
Go Version:   go1.22.6
Built:        Wed Aug 21 00:00:00 2024
OS/Arch:      linux/amd64

$ vagrant ssh -- uname --all
Linux fedora 6.8.7-300.fc40.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Apr 17 19:21:08 UTC 2024 x86_64 GNU/Linux

Podman in a container

No

Privileged Or Rootless

Rootless

Upstream Latest Release

Yes

Additional environment details

Additional information

Possibly related:

@evolutics evolutics added the kind/bug Categorizes issue or PR as related to a bug. label Sep 1, 2024
@afbjorklund
Copy link
Contributor

afbjorklund commented Sep 1, 2024

This is a known shortcoming, you have to add the basic ssh config to a podman "system connection"

Host
  HostName
  User
  Port
  IdentityFile

A workaround is to set up the ssh tunnel yourself (with the ssh config), and use unix: instead of ssh:

@evolutics
Copy link
Author

Thanks for your fast explanation!

This is a known shortcoming, you have to add the basic ssh config to a podman "system connection"

Does this mean that I'd have to unpack my (possibly generated) ~/.ssh/config file to translate the supported subset of options to podman system connection add? The manual seems to suggest so.

A workaround would be to extend the $PATH with a folder containing a custom ssh executable that essentially forwards to /usr/bin/ssh -F /my/ssh/config. This works with Docker, however not with Podman – I guess I am misunderstanding what --ssh native does exactly.

@afbjorklund
Copy link
Contributor

I think it should be possible for podman to parse the basics, but you would lose out on any other ssh features...

The same issue exists in Lima, and is worse now when Podman Desktop can parse connections but not forwards...

@afbjorklund
Copy link
Contributor

afbjorklund commented Sep 1, 2024

I guess I am misunderstanding what --ssh native does exactly.

It seems to be used a little inconsistently around the podman code base.

Some parts are using the "SSHMode", but some are still calling ssh.Dial.

i.e. not using the containers-common wrapper, but golang.org/x/crypto/ssh

@afbjorklund
Copy link
Contributor

afbjorklund commented Sep 1, 2024

I think it has been this way since Podman v2, that is before the connections...

e.g. https://boot2podman.github.io/2020/07/22/machine-replacement.html

export CONTAINER_HOST=ssh://[email protected]:2222/run/user/1000/podman/podman.sock
export CONTAINER_SSHKEY=$PWD/.vagrant/machines/default/virtualbox/private_key

But then came Podman Machine v3, and replaced the Fedora and the VirtualBox.

@Luap99
Copy link
Member

Luap99 commented Sep 1, 2024

ssh=native was never properly finished AFAIK, it doesn't seem to be tested either.

I do agree this should work with native mode as we call the ssh binary which should read you ssh config so yes this seems like a bug to me.

@afbjorklund
Copy link
Contributor

afbjorklund commented Sep 1, 2024

Most of the current systems seem to not be supporting ssh: at all (even though it was introduced in Docker 18.09), but instead rely on some other system creating a tunnel for them (in case the server does not support the old tcp: that is).

i.e. like Java or JavaScript, or what have you... (interestingly, even Windows supports unix domain sockets these days)
Like the library that Podman Desktop is using, that requires it to create a local tmp socket rather than use it directly.

@afbjorklund
Copy link
Contributor

If wanting to support the Docker syntax, then there also needs to be something added for the default path. With the docker client, the $DOCKER_HOST is coming from the environment on the remote side but with podman it is local...

So --host ssh://my-host is not going to fly with podman, because it doesn't have a path to podman.sock - in pretty much the same way that --host ssh://my-host/run/podman/podman.sock fails with a docker client because it does have a path.

@afbjorklund
Copy link
Contributor

afbjorklund commented Sep 1, 2024

The patched version looks like this:

Error: unable to connect to Podman socket: Get "http://d/v4.9.3/libpod/_ping": ssh: rejected: connect failed (open failed)

Instead of the default podman version:

Error: unable to connect to Podman socket: failed to connect: dial tcp: lookup lima-podman: no such host

So the parsing of the ssh config goes OK:

DEBU[0000] Alias: lima-podman                           
DEBU[0000] User: anders                                 
DEBU[0000] Hostname: 127.0.0.1                          
DEBU[0000] Port: 39901                                  
DEBU[0000] Identity: "/home/anders/.lima/_config/user"  

commit 59c8f28 (https://github.com/kevinburke/ssh_config)


But the connection still fails, due to path.

And it is hard to "guess" (need to read env)

The remote uid (and thus systemd dir) could be anything.


Something similar to this, connect to the remote server and try to find the socket path.

https://docs.docker.com/engine/security/rootless/#expose-docker-api-socket-through-ssh

I think with Podman, you would call podman info on the remote side and parse the output?

  remoteSocket:
    exists: true
    path: /run/user/1000/podman/podman.sock

Like so:

podman info --format '{{.Host.RemoteSocket.Path}}'

And use this value, instead of the empty path in url (if none has been provided by the caller)

DEBU[0000] Path: /run/user/1000/podman/podman.sock      

commit a928ac1 (https://pkg.go.dev/golang.org/x/crypto/ssh)


Found another bug with the user being required, similar to the earlier bug with port being required...

It tried to authenticate as user "", instead of the current user. The workaround was adding a $USER@

commit ce4ccbd (like 14ef6a9)

Will rebase to HEAD

@afbjorklund
Copy link
Contributor

afbjorklund commented Sep 1, 2024

Parsing the basic 4 values and querying for the 5th seems to be working - even with "golang":

$ podman-remote --host ssh://lima-podman version
Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VM
Error: unable to connect to Podman socket: failed to connect: dial tcp: lookup lima-podman: no such host
$ ./bin/podman-remote --host ssh://lima-podman version
Client:       Podman Engine
Version:      4.9.3
API Version:  4.9.3
Go Version:   go1.22.3
Git Commit:   a928ac1438058eaed6aacc17fd03dea41df8c432
Built:        Sun Sep  1 22:29:36 2024
OS/Arch:      linux/amd64

Server:       Podman Engine
Version:      5.2.2
API Version:  5.2.2
Go Version:   go1.22.6
Built:        Wed Aug 21 02:00:00 2024
OS/Arch:      linux/amd64

It doesn't use any of the other features of the ssh_config, so that does need the "native" ssh...

The most important one is the ControlMaster auto*


* https://docs.docker.com/engine/security/protect-access/#ssh-tips

Others include using AES hardware crypto (where available), etc etc

Lima handles this automatically, when setting up the port forwarding:

portForwards:
- guestSocket: "/run/user/{{.UID}}/podman/podman.sock"
  hostSocket: "{{.Dir}}/sock/podman.sock"

@evolutics
Copy link
Author

Thank you very much for your hard work on this.

For anyone stumbling across this issue, above mentioned workaround with the SSH tunnel looks like so:

Keep

ssh -F ssh_config -L "${PWD}/my.sock:/run/user/1000/podman/podman.sock" my-host

running, where -F ssh_config can be omitted if ~/.ssh/config should apply. Also, /run/user/1000/podman/podman.sock is just an example; it may be different on your remote host (see podman info).

Now podman --host "unix://${PWD}/my.sock" ps works.

@afbjorklund
Copy link
Contributor

afbjorklund commented Sep 7, 2024

For anyone stumbling across this issue, above mentioned workaround with the SSH tunnel...

It's not only a workaround, but also an optimization that is used by Podman Desktop (and Lima)

...podman.sock is just an example; it may be different on your remote host (see podman info).

i.e. ssh -F ssh_config my-host podman info, not the socket location on the local host (client).


One remaining issue is how to separate a local unix socket, versus a "remote" tunneled unix socket

It might need some kind of UUID for the host, to see if we are still on the same machine - or not.

@afbjorklund
Copy link
Contributor

afbjorklund commented Sep 8, 2024

Another (actual) workaround would be to use ssh -G, with the ssh -F if needed.

And let ssh handle the parsing of the ssh_config, and just look for the results:

$ ssh -G lima-podman | grep -E "^(user|hostname|port|identityfile) "
user anders
hostname 127.0.0.1
port 38241
identityfile /home/anders/.lima/_config/user

And then feed that as input to podman system connection add, to look up the path.

evolutics added a commit to evolutics/kerek that referenced this issue Sep 9, 2024
Docker supports `~/.ssh/config` but not custom SSH config files
(docker/cli#1301).

Podman does not support `~/.ssh/config` but might partially do so soon
(containers/podman#23831).
Copy link

github-actions bot commented Oct 9, 2024

A friendly reminder that this issue had no activity for 30 days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Categorizes issue or PR as related to a bug. stale-issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants