From: Lennart Poettering Date: Sat, 11 May 2024 17:56:10 +0000 (+0200) Subject: ssh-proxy: add support for connecting to VMs by AF_VSOCK via "machine/…" host specs X-Git-Tag: v257-rc1~1063^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=26b455d8156500ea883ccef5e1e4c610b8f575d8;p=thirdparty%2Fsystemd.git ssh-proxy: add support for connecting to VMs by AF_VSOCK via "machine/…" host specs With this one can type "ssh machine/foobar" to connect to locally registered machine "foobar" via SSH-over-AF_VSOCK. --- diff --git a/src/ssh-generator/20-systemd-ssh-proxy.conf.in b/src/ssh-generator/20-systemd-ssh-proxy.conf.in index b97e0f5340b..912cc1f9ac4 100644 --- a/src/ssh-generator/20-systemd-ssh-proxy.conf.in +++ b/src/ssh-generator/20-systemd-ssh-proxy.conf.in @@ -1,8 +1,15 @@ # SPDX-License-Identifier: LGPL-2.1-or-later # -# Make sure unix/* and vsock/* can be used to connect to AF_UNIX and AF_VSOCK paths +# Allow connecting to the local host directly via ".host" +Host .host machine/.host + ProxyCommand {{LIBEXECDIR}}/systemd-ssh-proxy unix/run/ssh-unix-local/socket %p + ProxyUseFdpass yes + CheckHostIP no + +# Make sure unix/* and vsock/* can be used to connect to AF_UNIX and AF_VSOCK paths. +# Make sure machine/* can be used to connect to local machines registered in machined. # -Host unix/* vsock/* +Host unix/* vsock/* machine/* ProxyCommand {{LIBEXECDIR}}/systemd-ssh-proxy %h %p ProxyUseFdpass yes CheckHostIP no @@ -10,9 +17,3 @@ Host unix/* vsock/* # Disable all kinds of host identity checks, since these addresses are generally ephemeral. StrictHostKeyChecking no UserKnownHostsFile /dev/null - -# Allow connecting to the local host directly via ".host" -Host .host - ProxyCommand {{LIBEXECDIR}}/systemd-ssh-proxy unix/run/ssh-unix-local/socket %p - ProxyUseFdpass yes - CheckHostIP no diff --git a/src/ssh-generator/ssh-proxy.c b/src/ssh-generator/ssh-proxy.c index 7021ddd8a6e..36311136127 100644 --- a/src/ssh-generator/ssh-proxy.c +++ b/src/ssh-generator/ssh-proxy.c @@ -14,21 +14,19 @@ #include "socket-util.h" #include "string-util.h" #include "strv.h" +#include "varlink.h" -static int process_vsock(const char *host, const char *port) { +static int process_vsock_cid(unsigned cid, const char *port) { int r; - assert(host); + assert(cid != VMADDR_CID_ANY); assert(port); union sockaddr_union sa = { + .vm.svm_cid = cid, .vm.svm_family = AF_VSOCK, }; - r = vsock_parse_cid(host, &sa.vm.svm_cid); - if (r < 0) - return log_error_errno(r, "Failed to parse vsock cid: %s", host); - r = vsock_parse_port(port, &sa.vm.svm_port); if (r < 0) return log_error_errno(r, "Failed to parse vsock port: %s", port); @@ -47,6 +45,21 @@ static int process_vsock(const char *host, const char *port) { log_debug("Successfully sent AF_VSOCK socket via STDOUT."); return 0; + +} + +static int process_vsock_string(const char *host, const char *port) { + unsigned cid; + int r; + + assert(host); + assert(port); + + r = vsock_parse_cid(host, &cid); + if (r < 0) + return log_error_errno(r, "Failed to parse vsock cid: %s", host); + + return process_vsock_cid(cid, port); } static int process_unix(const char *path) { @@ -124,6 +137,43 @@ static int process_vsock_mux(const char *path, const char *port) { return 0; } +static int process_machine(const char *machine, const char *port) { + _cleanup_(varlink_unrefp) Varlink *vl = NULL; + int r; + + assert(machine); + assert(port); + + r = varlink_connect_address(&vl, "/run/systemd/machine/io.systemd.Machine"); + if (r < 0) + return log_error_errno(r, "Failed to connect to machined on /run/systemd/machine/io.systemd.Machine: %m"); + + _cleanup_(sd_json_variant_unrefp) sd_json_variant *result = NULL; + r = varlink_callbo_and_log( + vl, + "io.systemd.Machine.List", + &result, + SD_JSON_BUILD_PAIR("name", SD_JSON_BUILD_STRING(machine))); + if (r < 0) + return r; + + uint32_t cid = VMADDR_CID_ANY; + + const sd_json_dispatch_field dispatch_table[] = { + { "vSockCid", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint32, PTR_TO_SIZE(&cid), 0 }, + {} + }; + + r = sd_json_dispatch(result, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, NULL); + if (r < 0) + return log_error_errno(r, "Failed to parse Varlink reply: %m"); + + if (cid == VMADDR_CID_ANY) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Machine has no AF_VSOCK CID assigned."); + + return process_vsock_cid(cid, port); +} + static int run(int argc, char* argv[]) { log_setup(); @@ -135,7 +185,7 @@ static int run(int argc, char* argv[]) { const char *p = startswith(host, "vsock/"); if (p) - return process_vsock(p, port); + return process_vsock_string(p, port); p = startswith(host, "unix/"); if (p) @@ -145,6 +195,10 @@ static int run(int argc, char* argv[]) { if (p) return process_vsock_mux(p, port); + p = startswith(host, "machine/"); + if (p) + return process_machine(p, port); + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Don't know how to parse host name specification: %s", host); }