From nobody Fri May 17 11:05:20 2024 Delivered-To: importer@patchew.org Received-SPF: none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; spf=none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1713521655230282.8599475707225; Fri, 19 Apr 2024 03:14:15 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 276761D59; Fri, 19 Apr 2024 06:14:14 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 102921D37; Fri, 19 Apr 2024 06:12:42 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 65DFD1BA8; Fri, 19 Apr 2024 06:12:38 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id EE27C1BDC for ; Fri, 19 Apr 2024 06:12:37 -0400 (EDT) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-377-WSqovzp8O5SD1QdJoe9f4g-1; Fri, 19 Apr 2024 06:12:36 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id EBDBB8ABE05 for ; Fri, 19 Apr 2024 10:12:35 +0000 (UTC) Received: from maggie.brq.redhat.com (unknown [10.43.3.102]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9774F3543A for ; Fri, 19 Apr 2024 10:12:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.7 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 X-MC-Unique: WSqovzp8O5SD1QdJoe9f4g-1 From: Michal Privoznik To: devel@lists.libvirt.org Subject: [PATCH 1/4] datatypes: Declare g_autoptr cleanup functions for more public objects Date: Fri, 19 Apr 2024 12:12:30 +0200 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.5 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Message-ID-Hash: U5M2TBQNXBZHGTSIJSMLK2WEOGTXYPBU X-Message-ID-Hash: U5M2TBQNXBZHGTSIJSMLK2WEOGTXYPBU X-MailFrom: mprivozn@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: Content-Type: text/plain; charset="utf-8"; x-default="true" Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1713521655926100001 Some public objects (like virDomain, virInterface, and so on) are missing g_autoptr() cleanup functions. Provide missing declarations. Note, this is only for our internal use - hence datatypes.h. Signed-off-by: Michal Privoznik Reviewed-by: Daniel P. Berrang=C3=A9 --- src/datatypes.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/datatypes.h b/src/datatypes.h index f8b1a83407..c5a7ece786 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -604,6 +604,9 @@ struct _virDomain { unsigned char uuid[VIR_UUID_BUFLEN]; /* the domain unique identifier */ }; =20 +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomain, virObjectUnref); + + /** * _virNetwork: * @@ -647,6 +650,9 @@ struct _virInterface { char *mac; /* the interface MAC address */ }; =20 +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virInterface, virObjectUnref); + + /** * _virStoragePool: * @@ -706,6 +712,7 @@ struct _virNodeDevice { =20 G_DEFINE_AUTOPTR_CLEANUP_FUNC(virNodeDevice, virObjectUnref); =20 + /** * _virSecret: * @@ -751,6 +758,8 @@ struct _virDomainCheckpoint { virDomainPtr domain; }; =20 +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainCheckpoint, virObjectUnref); + =20 /** * _virDomainSnapshot @@ -763,6 +772,9 @@ struct _virDomainSnapshot { virDomainPtr domain; }; =20 +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainSnapshot, virObjectUnref); + + /** * _virNWFilter: * @@ -775,6 +787,8 @@ struct _virNWFilter { unsigned char uuid[VIR_UUID_BUFLEN]; /* the network filter unique iden= tifier */ }; =20 +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virNWFilter, virObjectUnref); + =20 /** * _virNWFilterBinding: @@ -788,6 +802,8 @@ struct _virNWFilterBinding { char *filtername; /* the network filter name */ }; =20 +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virNWFilterBinding, virObjectUnref); + =20 /* * Helper APIs for allocating new object instances --=20 2.43.2 _______________________________________________ Devel mailing list -- devel@lists.libvirt.org To unsubscribe send an email to devel-leave@lists.libvirt.org From nobody Fri May 17 11:05:20 2024 Delivered-To: importer@patchew.org Received-SPF: none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; spf=none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1713521785963538.9957373161752; Fri, 19 Apr 2024 03:16:25 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id DB1051D44; Fri, 19 Apr 2024 06:16:24 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 482F31DA6; Fri, 19 Apr 2024 06:12:46 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 1568C1BA8; Fri, 19 Apr 2024 06:12:40 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 017841BA8 for ; Fri, 19 Apr 2024 06:12:38 -0400 (EDT) Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-471-ZTZPDe8QODyP8BGqZ2RFjw-1; Fri, 19 Apr 2024 06:12:36 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 9B0021C54463 for ; Fri, 19 Apr 2024 10:12:36 +0000 (UTC) Received: from maggie.brq.redhat.com (unknown [10.43.3.102]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2B5C043FAC for ; Fri, 19 Apr 2024 10:12:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 X-MC-Unique: ZTZPDe8QODyP8BGqZ2RFjw-1 From: Michal Privoznik To: devel@lists.libvirt.org Subject: [PATCH 2/4] tools: Introduce SSH proxy Date: Fri, 19 Apr 2024 12:12:31 +0200 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.5 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Message-ID-Hash: JKKNAWXWDO7MP7OL3V7IBZUZVWJWWDIO X-Message-ID-Hash: JKKNAWXWDO7MP7OL3V7IBZUZVWJWWDIO X-MailFrom: mprivozn@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: Content-Type: text/plain; charset="utf-8"; x-default="true" Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1713521786308100001 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-system= d-ssh-proxy.conf.in Resolves: https://gitlab.com/libvirt/libvirt/-/issues/579 Signed-off-by: Michal Privoznik --- 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 diff --git a/libvirt.spec.in b/libvirt.spec.in index 64018192b6..9069b3792f 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -91,6 +91,7 @@ # Other optional features %define with_numactl 0%{!?_without_numactl:1} %define with_userfaultfd_sysctl 0%{!?_without_userfaultfd_sysctl:1} +%define with_ssh_proxy 0%{!?_without_ssh_proxy:1} =20 # A few optional bits off by default, we enable later %define with_fuse 0 @@ -1017,6 +1018,9 @@ Summary: Client side utilities of the libvirt library Requires: libvirt-libs =3D %{version}-%{release} # Needed by virt-pki-validate script. Requires: gnutls-utils + %if %{with_ssh_proxy} +Recommends: libvirt-ssh-proxy =3D %{version}-%{release} + %endif =20 # Ensure smooth upgrades Obsoletes: libvirt-bash-completion < 7.3.0 @@ -1099,6 +1103,15 @@ Requires: libvirt-daemon-driver-network =3D %{versio= n}-%{release} Libvirt plugin for NSS for translating domain names into IP addresses. %endif =20 +%if %{with_ssh_proxy} +%package ssh-proxy +Summary: Libvirt SSH proxy +Requires: libvirt-libs =3D %{version}-%{release} + +%description ssh-proxy +Allows SSH into domains via VSOCK without need for network. +%endif + %if %{with_mingw32} %package -n mingw32-libvirt Summary: %{summary} @@ -1290,6 +1303,12 @@ exit 1 %define arg_userfaultfd_sysctl -Duserfaultfd_sysctl=3Ddisabled %endif =20 +%if %{with_ssh_proxy} + %define arg_ssh_proxy -Dssh_proxy=3Denabled +%else + %define arg_ssh_proxy -Dssh_proxy=3Ddisabled +%endif + %define when %(date +"%%F-%%T") %define where %(hostname) %define who %{?packager}%{!?packager:Unknown} @@ -1371,6 +1390,7 @@ export SOURCE_DATE_EPOCH=3D$(stat --printf=3D'%Y' %{_= specdir}/libvirt.spec) -Dtls_priority=3D%{tls_priority} \ -Dsysctl_config=3Denabled \ %{?arg_userfaultfd_sysctl} \ + %{?arg_ssh_proxy} \ %{?enable_werror} \ -Dexpensive_tests=3Denabled \ -Dinit_script=3Dsystemd \ @@ -1455,6 +1475,7 @@ export SOURCE_DATE_EPOCH=3D$(stat --printf=3D'%Y' %{_= specdir}/libvirt.spec) -Dstorage_zfs=3Ddisabled \ -Dsysctl_config=3Ddisabled \ -Duserfaultfd_sysctl=3Ddisabled \ + -Dssh_proxy=3Ddisabled \ -Dtests=3Ddisabled \ -Dudev=3Ddisabled \ -Dwireshark_dissector=3Ddisabled \ @@ -2425,6 +2446,12 @@ exit 0 %{_libdir}/libnss_libvirt.so.2 %{_libdir}/libnss_libvirt_guest.so.2 =20 + %if %{with_ssh_proxy} +%files ssh-proxy +%config(noreplace) %{_sysconfdir}/ssh/ssh_config.d/30-libvirt-ssh-proxy.co= nf +%{_libexecdir}/libvirt-ssh-proxy + %endif + %if %{with_lxc} %files login-shell %attr(4750, root, virtlogin) %{_bindir}/virt-login-shell diff --git a/meson.build b/meson.build index 1518afa1cb..b19f9b1ed1 100644 --- a/meson.build +++ b/meson.build @@ -113,6 +113,11 @@ endif confdir =3D sysconfdir / meson.project_name() pkgdatadir =3D datadir / meson.project_name() =20 +sshconfdir =3D get_option('sshconfdir') +if sshconfdir =3D=3D '' + sshconfdir =3D sysconfdir / 'ssh/ssh_config.d' +endif + =20 # generate configmake.h header =20 @@ -690,12 +695,14 @@ if host_machine.system() =3D=3D 'linux' symbols +=3D [ # process management [ 'sys/syscall.h', 'SYS_pidfd_open' ], + # vsock + [ 'linux/vm_sockets.h', 'struct sockaddr_vm', '#include = ' ], ] endif =20 foreach symbol : symbols if cc.has_header_symbol(symbol[0], symbol[1], args: '-D_GNU_SOURCE', pre= fix: symbol.get(2, '')) - conf.set('WITH_DECL_@0@'.format(symbol[1].to_upper()), 1) + conf.set('WITH_DECL_@0@'.format(symbol[1].underscorify().to_upper()), = 1) endif endforeach =20 @@ -2033,6 +2040,12 @@ if not get_option('pm_utils').disabled() endif endif =20 +if not get_option('ssh_proxy').disabled() and conf.has('WITH_DECL_STRUCT_S= OCKADDR_VM') + conf.set('WITH_SSH_PROXY', 1) +elif get_option('ssh_proxy').enabled() + error('ssh proxy requires vm_sockets.h which wasn\'t found') +endif + if not get_option('sysctl_config').disabled() and host_machine.system() = =3D=3D 'linux' conf.set('WITH_SYSCTL', 1) elif get_option('sysctl_config').enabled() @@ -2344,6 +2357,7 @@ misc_summary =3D { 'virt-login-shell': conf.has('WITH_LOGIN_SHELL'), 'virt-host-validate': conf.has('WITH_HOST_VALIDATE'), 'TLS priority': conf.get_unquoted('TLS_PRIORITY'), + 'SSH proxy': conf.has('WITH_SSH_PROXY'), 'sysctl config': conf.has('WITH_SYSCTL'), 'userfaultfd sysctl': conf.has('WITH_USERFAULTFD_SYSCTL'), } diff --git a/meson_options.txt b/meson_options.txt index ed91d97abf..35af27306d 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -40,6 +40,7 @@ option('sanlock', type: 'feature', value: 'auto', descrip= tion: 'sanlock support' option('sasl', type: 'feature', value: 'auto', description: 'sasl support') option('selinux', type: 'feature', value: 'auto', description: 'selinux su= pport') option('selinux_mount', type: 'string', value: '', description: 'set SELin= ux mount point') +option('sshconfdir', type: 'string', value: '', description: 'directory fo= r SSH client configuration') option('udev', type: 'feature', value: 'auto', description: 'udev support') option('wireshark_dissector', type: 'feature', value: 'auto', description:= 'wireshark support') option('wireshark_plugindir', type: 'string', value: '', description: 'wir= eshark plugins directory for use when installing wireshark plugin') @@ -107,6 +108,7 @@ option('numad', type: 'feature', value: 'auto', descrip= tion: 'use numad to manag option('nbdkit', type: 'feature', value: 'auto', description: 'Build nbdki= t storage backend') option('nbdkit_config_default', type: 'feature', value: 'auto', descriptio= n: 'Whether to use nbdkit storage backend for network disks by default (con= figurable)') option('pm_utils', type: 'feature', value: 'auto', description: 'use pm-ut= ils for power management') +option('ssh_proxy', type: 'feature', value: 'auto', description: 'Build ss= h-proxy for ssh over vsock') option('sysctl_config', type: 'feature', value: 'auto', description: 'Whet= her to install sysctl configs') option('userfaultfd_sysctl', type: 'feature', value: 'auto', description: = 'Whether to install sysctl config for enabling unprivileged userfaultfd') option('tls_priority', type: 'string', value: 'NORMAL', description: 'set = the default TLS session priority string') diff --git a/po/POTFILES b/po/POTFILES index 6fbff4bef2..cec7e4abf4 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -359,6 +359,7 @@ src/vz/vz_utils.c src/vz/vz_utils.h tests/virpolkittest.c tools/libvirt-guests.sh.in +tools/ssh-proxy/ssh-proxy.c tools/virsh-backup.c tools/virsh-checkpoint.c tools/virsh-completer-host.c diff --git a/tools/meson.build b/tools/meson.build index 15be557dfe..1bb84be0be 100644 --- a/tools/meson.build +++ b/tools/meson.build @@ -343,3 +343,5 @@ endif if wireshark_dep.found() subdir('wireshark') endif + +subdir('ssh-proxy') 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 diff --git a/tools/ssh-proxy/meson.build b/tools/ssh-proxy/meson.build new file mode 100644 index 0000000000..e9f312fa25 --- /dev/null +++ b/tools/ssh-proxy/meson.build @@ -0,0 +1,25 @@ +if conf.has('WITH_SSH_PROXY') + executable( + 'libvirt-ssh-proxy', + [ + 'ssh-proxy.c' + ], + dependencies: [ + src_dep, + ], + link_with: [ + libvirt_lib, + ], + install: true, + install_dir: libexecdir, + install_rpath: libvirt_rpath, + ) + + configure_file( + input : '30-libvirt-ssh-proxy.conf.in', + output: '@BASENAME@', + configuration: tools_conf, + install: true, + install_dir : sshconfdir, + ) +endif diff --git a/tools/ssh-proxy/ssh-proxy.c b/tools/ssh-proxy/ssh-proxy.c new file mode 100644 index 0000000000..90f30d4f49 --- /dev/null +++ b/tools/ssh-proxy/ssh-proxy.c @@ -0,0 +1,233 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * For given domain and port create a VSOCK socket and pass it onto STDOUT. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" +#include "virsocket.h" +#include "virstring.h" +#include "virfile.h" +#include "datatypes.h" +#include "virgettext.h" +#include "virxml.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +#define SYS_ERROR(...) \ +do { \ + int err =3D errno; \ + fprintf(stderr, "ERROR %s:%d : ", __FUNCTION__, __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, " : %s\n", g_strerror(err)); \ + fprintf(stderr, "\n"); \ +} while (0) + +#define ERROR(...) \ +do { \ + fprintf(stderr, "ERROR %s:%d : ", __FUNCTION__, __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ +} while (0) + +#define HOSTNAME_PREFIX "qemu/" + +static void +dummyErrorHandler(void *opaque G_GNUC_UNUSED, + virErrorPtr error G_GNUC_UNUSED) +{ + +} + +static void +printUsage(const char *argv0) +{ + const char *progname; + + if (!(progname =3D strrchr(argv0, '/'))) + progname =3D argv0; + else + progname++; + + printf(_("\n" + "Usage:\n" + "%1$s hostname port\n" + "\n" + "Hostname should be in form '%2$s$domname'\n"), + progname, HOSTNAME_PREFIX); +} + +static int +parseArgs(int argc, + char *argv[], + const char **domname, + unsigned int *port) +{ + if (argc !=3D 3 || + !(*domname =3D STRSKIP(argv[1], HOSTNAME_PREFIX))) { + ERROR(_("Bad usage")); + printUsage(argv[0]); + return -1; + } + + if (virStrToLong_ui(argv[2], NULL, 10, port) < 0) { + ERROR(_("Unable to parse port: %1$s"), argv[2]); + printUsage(argv[0]); + return -1; + } + + return 0; +} + +static virDomainPtr +lookupDomain(const char *domname, + const char *uri, + virConnectPtr *connRet) +{ + g_autoptr(virConnect) conn =3D NULL; + virDomainPtr dom =3D NULL; + + if (!(conn =3D virConnectOpenReadOnly(uri))) + return NULL; + + dom =3D virDomainLookupByName(conn, domname); + if (!dom) + dom =3D virDomainLookupByUUIDString(conn, domname); + if (!dom) { + int id; + + if (virStrToLong_i(domname, NULL, 10, &id) >=3D 0) + dom =3D virDomainLookupByID(conn, id); + } + if (!dom) + return NULL; + + *connRet =3D g_steal_pointer(&conn); + return dom; +} + + +#define VSOCK_CID_XPATH "/domain/devices/vsock/cid" + +static int +extractCID(virDomainPtr dom, + unsigned long long *cidRet) +{ + g_autofree char *domxml =3D NULL; + g_autoptr(xmlDoc) doc =3D NULL; + g_autoptr(xmlXPathContext) ctxt =3D NULL; + g_autofree xmlNodePtr *nodes =3D NULL; + int nnodes =3D 0; + size_t i; + + if (!(domxml =3D virDomainGetXMLDesc(dom, 0))) + return -1; + + doc =3D virXMLParseStringCtxtWithIndent(domxml, "domain", &ctxt); + if (!doc) + return -1; + + if ((nnodes =3D virXPathNodeSet(VSOCK_CID_XPATH, ctxt, &nodes)) < 0) { + return -1; + } + + for (i =3D 0; i < nnodes; i++) { + unsigned long long cid; + + if (virXMLPropULongLong(nodes[i], "address", 10, 0, &cid) > 0) { + *cidRet =3D cid; + return 0; + } + } + + return -1; +} + +#undef VSOCK_CID_XPATH + +static int +processVsock(const char *domname, + unsigned int port) +{ + const char *uris[] =3D {"qemu:///system", "qemu:///session"}; + struct sockaddr_vm sa =3D { + .svm_family =3D AF_VSOCK, + .svm_port =3D port, + }; + VIR_AUTOCLOSE fd =3D -1; + unsigned long long cid =3D -1; + size_t i; + + for (i =3D 0; i < G_N_ELEMENTS(uris); i++) { + g_autoptr(virConnect) conn =3D NULL; + g_autoptr(virDomain) dom =3D NULL; + + if (!(dom =3D lookupDomain(domname, uris[i], &conn))) + continue; + + if (extractCID(dom, &cid) >=3D 0) + break; + } + + if (cid =3D=3D -1) { + ERROR(_("No usable vsock found")); + return -1; + } + + sa.svm_cid =3D cid; + + fd =3D 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=3D%1$llu port=3D%2$u)= "), + cid, port); + return -1; + } + + /* OpenSSH wants us to send a single byte along with the file descript= or, + * hence do so. */ + if (virSocketSendFD(STDOUT_FILENO, fd) < 0) { + SYS_ERROR(_("Failed to send file descriptor %1$d"), fd); + return -1; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + const char *domname =3D NULL; + unsigned int port; + + if (virGettextInitialize() < 0) + return EXIT_FAILURE; + + if (virInitialize() < 0) { + ERROR(_("Failed to initialize libvirt")); + return EXIT_FAILURE; + } + + virSetErrorFunc(NULL, dummyErrorHandler); + + if (parseArgs(argc, argv, &domname, &port) < 0) + return EXIT_FAILURE; + + if (processVsock(domname, port) < 0) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} --=20 2.43.2 _______________________________________________ Devel mailing list -- devel@lists.libvirt.org To unsubscribe send an email to devel-leave@lists.libvirt.org From nobody Fri May 17 11:05:20 2024 Delivered-To: importer@patchew.org Received-SPF: none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; spf=none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1713521918154341.0872724527138; Fri, 19 Apr 2024 03:18:38 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 1146B1D65; Fri, 19 Apr 2024 06:18:36 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id E6828175E; Fri, 19 Apr 2024 06:17:50 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 1FF71175E; Fri, 19 Apr 2024 06:17:47 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 6773F10B for ; Fri, 19 Apr 2024 06:17:46 -0400 (EDT) Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-126-BlrvEN1qOLiN_rIVWXa-3A-1; Fri, 19 Apr 2024 06:17:44 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 2EDC1286A9D6 for ; Fri, 19 Apr 2024 10:12:37 +0000 (UTC) Received: from maggie.brq.redhat.com (unknown [10.43.3.102]) by smtp.corp.redhat.com (Postfix) with ESMTP id CE6F243FAC for ; Fri, 19 Apr 2024 10:12:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.7 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 X-MC-Unique: BlrvEN1qOLiN_rIVWXa-3A-1 From: Michal Privoznik To: devel@lists.libvirt.org Subject: [PATCH 3/4] docs: Document SSH proxy Date: Fri, 19 Apr 2024 12:12:32 +0200 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.5 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Message-ID-Hash: LM47CCGJ7TW7V2WJSS2FUJK3TQ5424ZY X-Message-ID-Hash: LM47CCGJ7TW7V2WJSS2FUJK3TQ5424ZY X-MailFrom: mprivozn@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: Content-Type: text/plain; charset="utf-8"; x-default="true" Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1713521918831100001 Signed-off-by: Michal Privoznik --- docs/docs.rst | 3 +++ docs/meson.build | 1 + docs/nss.rst | 7 ++++++ docs/ssh-proxy.rst | 60 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 docs/ssh-proxy.rst diff --git a/docs/docs.rst b/docs/docs.rst index f57164b9e3..1a958e9cc7 100644 --- a/docs/docs.rst +++ b/docs/docs.rst @@ -47,6 +47,9 @@ Deployment / operation `Hooks `__ Hooks for system specific management =20 +`SSH Proxy `__ + Enable SSH into guests over a VSOCK + `NSS module `__ Enable domain host name translation to IP addresses =20 diff --git a/docs/meson.build b/docs/meson.build index 87d728213c..2dda59f978 100644 --- a/docs/meson.build +++ b/docs/meson.build @@ -97,6 +97,7 @@ docs_rst_files =3D [ 'python', 'remote', 'securityprocess', + 'ssh-proxy', 'storage', 'strategy', 'styleguide', diff --git a/docs/nss.rst b/docs/nss.rst index 8f98330221..53955a3278 100644 --- a/docs/nss.rst +++ b/docs/nss.rst @@ -152,3 +152,10 @@ If there's no record for either of the aforementioned = commands, it's very likely that NSS module won't find anything and vice versa. As of ``v3.0.0`` libvi= rt provides ``libvirt_guest`` NSS module that doesn't have this limitation. However, the statement is still true for the ``libvirt`` NSS module. + +Alternatives +------------ + +As of ``v10.3.0`` libvirt implements an `SSH proxy `__ whi= ch +doesn't require any network interface to SSH into the guest as SSH flows +through a VSOCK device. diff --git a/docs/ssh-proxy.rst b/docs/ssh-proxy.rst new file mode 100644 index 0000000000..8528b6b9a8 --- /dev/null +++ b/docs/ssh-proxy.rst @@ -0,0 +1,60 @@ +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +Libvirt SSH proxy +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Sometimes it's necessary to run some commands inside a gust. While libvirt +already provides `NSS module `__ that can translate guest name t= o IP +address it has some limitations (e.g. guest has to have a network interface +plugged into a libvirt managed network). To resolve some of these limitati= ons, +libvirt offers SSH proxy. It consists of a SSH client config file +(``/etc/ssh/ssh_config.d/30-libvirt-ssh-proxy.conf``) and a small binary. = Both +are automatically installed by ``libvirt-client`` package. After running: + +``ssh user@qemu/virtualMachine`` + +the configuration file instructs SSH client to start the binary helper whi= ch +finds a VSOCK device inside the ``virtualMachine`` and establishes a conne= ction +to it. + +For now, only QEMU domains are implemented and the lookup of the +``virtualMachine`` is done under ``qemu:///system`` URI first, followed by +``qemu:///session``. Accepted values for ``virtualMachine`` are: domain na= me +(as reported by e.g. `virsh list`), domain UUID and finally domain ID. + +Guest requirements +------------------ + +It is obvious that SSH daemon inside the guest needs to be configured to l= isten +for incoming connections on a VSOCK. There are couple of ways to achieve t= his: + +* Run systemd-v256 or newer inside the guest. + + In this release, systemd started to deploy ``systemd-ssh-generator`` whi= ch + should configure socket activation for SSHD automagically. + +* Set up socket activation for VSOCK. + + We can take an inspiration in the unit file generated by + ``systemd-ssh-generator``: + +:: + + [Unit] + Description=3DOpenSSH Server Socket (systemd-ssh-generator, AF_VSOCK) + Documentation=3Dman:systemd-ssh-generator(8) + Wants=3Dssh-access.target + Before=3Dssh-access.target + + [Socket] + ListenStream=3Dvsock::22 + Accept=3Dyes + PollLimitIntervalSec=3D30s + PollLimitBurst=3D50 + +* Run a service that forwards VSOCK <=3D> SSHD communication + + For instance: + +:: + + socat VSOCK-LISTEN:22,reuseaddr,fork TCP:localhost:22 --=20 2.43.2 _______________________________________________ Devel mailing list -- devel@lists.libvirt.org To unsubscribe send an email to devel-leave@lists.libvirt.org From nobody Fri May 17 11:05:20 2024 Delivered-To: importer@patchew.org Received-SPF: none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; spf=none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1713521822752186.36439681924435; Fri, 19 Apr 2024 03:17:02 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id A33641D5E; Fri, 19 Apr 2024 06:17:01 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 9BEFD1DAF; Fri, 19 Apr 2024 06:12:51 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 3076E1BDC; Fri, 19 Apr 2024 06:12:40 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id BBEEF1C16 for ; Fri, 19 Apr 2024 06:12:39 -0400 (EDT) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-5-eYkz6ED8OpO5rHaEjiAYpg-1; Fri, 19 Apr 2024 06:12:38 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id B730F1044573 for ; Fri, 19 Apr 2024 10:12:37 +0000 (UTC) Received: from maggie.brq.redhat.com (unknown [10.43.3.102]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6271943FAC for ; Fri, 19 Apr 2024 10:12:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.7 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 X-MC-Unique: eYkz6ED8OpO5rHaEjiAYpg-1 From: Michal Privoznik To: devel@lists.libvirt.org Subject: [PATCH 4/4] NEWS: Document SSH proxy feature Date: Fri, 19 Apr 2024 12:12:33 +0200 Message-ID: <5d1a7d0e02a89884ab3aeac1ca7e47d0bc51020f.1713521526.git.mprivozn@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.5 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Message-ID-Hash: CUYQHBSQK3HQX7IVRNBNFF5GSYINNHNC X-Message-ID-Hash: CUYQHBSQK3HQX7IVRNBNFF5GSYINNHNC X-MailFrom: mprivozn@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: Content-Type: text/plain; charset="utf-8"; x-default="true" Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1713521824425100001 Signed-off-by: Michal Privoznik --- NEWS.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index 852dadf532..3bfd6d6919 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -17,6 +17,11 @@ v10.3.0 (unreleased) =20 * **New features** =20 + * SSH proxy for VM + + Libvirt now installs a binary helper that allows connecting to QEMU do= mains + via SSH using the following scheme: ``ssh user@qemu/virtualMachine``. + * **Improvements** =20 * **Bug fixes** --=20 2.43.2 _______________________________________________ Devel mailing list -- devel@lists.libvirt.org To unsubscribe send an email to devel-leave@lists.libvirt.org