On Fri, Apr 19, 2024 at 12:12:31PM +0200, Michal Privoznik wrote: > This allows users to SSH into a domain with a VSOCK device: > > ssh user@qemu/machineName > > So far, only QEMU domains are supported AND qemu:///system is > looked for the first for 'machineName' followed by > qemu:///session. I took an inspiration from SystemD's ssh proxy > [1] [2]. > > To just work out of the box, it requires (yet unreleased) systemd > to be running inside the guest to set up a socket activated SSHD > on the VSOCK. Alternatively, users can set up the socket > activation themselves, or just run a socat that'll forward vsock > <-> TCP communication. > > 1: https://github.com/systemd/systemd/blob/main/src/ssh-generator/ssh-proxy.c > 2: https://github.com/systemd/systemd/blob/main/src/ssh-generator/20-systemd-ssh-proxy.conf.in > > Resolves: https://gitlab.com/libvirt/libvirt/-/issues/579 > Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> > --- > libvirt.spec.in | 27 +++ > meson.build | 16 +- > meson_options.txt | 2 + > po/POTFILES | 1 + > tools/meson.build | 2 + > tools/ssh-proxy/30-libvirt-ssh-proxy.conf.in | 10 + > tools/ssh-proxy/meson.build | 25 ++ > tools/ssh-proxy/ssh-proxy.c | 233 +++++++++++++++++++ > 8 files changed, 315 insertions(+), 1 deletion(-) > create mode 100644 tools/ssh-proxy/30-libvirt-ssh-proxy.conf.in > create mode 100644 tools/ssh-proxy/meson.build > create mode 100644 tools/ssh-proxy/ssh-proxy.c > @@ -1017,6 +1018,9 @@ Summary: Client side utilities of the libvirt library > Requires: libvirt-libs = %{version}-%{release} > # Needed by virt-pki-validate script. > Requires: gnutls-utils > + %if %{with_ssh_proxy} > +Recommends: libvirt-ssh-proxy = %{version}-%{release} > + %endif I wonder if we should also have this present as a stronger 'Requires' in both libvirt-daemon-kvm & libvirt-daemon-qemu, as those are convenience RPMs intended to provide a set of RPMs to maxmimise the featureset. > diff --git a/meson.build b/meson.build > index 1518afa1cb..b19f9b1ed1 100644 > --- a/meson.build > +++ b/meson.build > @@ -113,6 +113,11 @@ endif > confdir = sysconfdir / meson.project_name() > pkgdatadir = datadir / meson.project_name() > > +sshconfdir = get_option('sshconfdir') > +if sshconfdir == '' > + sshconfdir = sysconfdir / 'ssh/ssh_config.d' Lets use the / operator consistently there sshconfdir = sysconfdir / 'ssh' / 'ssh_config.d' > diff --git a/tools/ssh-proxy/30-libvirt-ssh-proxy.conf.in b/tools/ssh-proxy/30-libvirt-ssh-proxy.conf.in > new file mode 100644 > index 0000000000..9a022826f7 > --- /dev/null > +++ b/tools/ssh-proxy/30-libvirt-ssh-proxy.conf.in > @@ -0,0 +1,10 @@ > +# SPDX-License-Identifier: LGPL-2.1-or-later > + > +Host qemu/* > + ProxyCommand @libexecdir@/libvirt-ssh-proxy %h %p > + ProxyUseFdpass yes > + CheckHostIP no > + > + # Disable all kinds of host identity checks, since these addresses are generally ephemeral. > + StrictHostKeyChecking no > + UserKnownHostsFile /dev/null I know systemd did this too, but I'm somewhat on the fence over whether turning this off is a good idea or not. I would assume it is recording "qemu/guestname" as the entry in the known hosts file, which is not that ephemeral for traditional guests ? I wonder if we should just let the user decide to turn this off if they so wish rather than forcing a less secure config by default. > +static int > +processVsock(const char *domname, > + unsigned int port) > +{ > + const char *uris[] = {"qemu:///system", "qemu:///session"}; We should be skipping the session driver, if running as root. > + struct sockaddr_vm sa = { > + .svm_family = AF_VSOCK, > + .svm_port = port, > + }; > + VIR_AUTOCLOSE fd = -1; > + unsigned long long cid = -1; > + size_t i; > + > + for (i = 0; i < G_N_ELEMENTS(uris); i++) { > + g_autoptr(virConnect) conn = NULL; > + g_autoptr(virDomain) dom = NULL; > + > + if (!(dom = lookupDomain(domname, uris[i], &conn))) > + continue; > + > + if (extractCID(dom, &cid) >= 0) > + break; > + } > + > + if (cid == -1) { > + ERROR(_("No usable vsock found")); > + return -1; > + } > + > + sa.svm_cid = cid; > + > + fd = socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC, 0); > + if (fd < 0) { > + SYS_ERROR(_("Failed to allocate AF_VSOCK socket")); > + return -1; > + } > + > + if (connect(fd, (const struct sockaddr *)&sa, sizeof(sa)) < 0) { > + SYS_ERROR(_("Failed to connect to vsock (cid=%1$llu port=%2$u)"), > + cid, port); > + return -1; > + } > + > + /* OpenSSH wants us to send a single byte along with the file descriptor, > + * hence do so. */ > + if (virSocketSendFD(STDOUT_FILENO, fd) < 0) { > + SYS_ERROR(_("Failed to send file descriptor %1$d"), fd); > + return -1; > + } > + > + return 0; > +} With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :| _______________________________________________ Devel mailing list -- devel@xxxxxxxxxxxxxxxxx To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxx