From: Matthieu Baerts (NGI0) Date: Mon, 7 Apr 2025 15:10:29 +0000 (+0200) Subject: ssh-proxy: add scp and rsync support X-Git-Tag: v258-rc1~781 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=defd5060d69ba31c1815e7d5427bde93a3db88c0;p=thirdparty%2Fsystemd.git ssh-proxy: add scp and rsync support ssh-generator and ssh-proxy are great features, it is very handy to be able to do: ssh vsock/1 But, because of the '/' used as a separator, scp and rsync don't interpret 'vsock/' as a hostname, e.g. $ scp /etc/machine-id vsock/2222:. cp: cannot create regular file 'vsock/2222:.': No such file or directory $ rsync /etc/machine-id vsock/2222:. rsync: [Receiver] change_dir#3 "(...)/vsock" failed: No such file or directory (2) rsync error: errors selecting input/output files, dirs (code 3) at main.c(829) [Receiver=3.4.1] An alternative is to use ',' as separator, e.g. $ scp /etc/machine-id vsock,2222:. This is what is being suggested here. The names with '/' are kept not to break anything here. Others are possible: '%', '=', '#', '@', ':', etc. As mentioned in commit 0abd510f7f ("ssh-proxy: add ssh ProxyCommand tool that can connect to AF_UNIX + AF_VSOCK sockets"), it is better to avoid ':' as it is already taken by SSH itself when doing sftp, and "@" is already taken for separating the user name. '#' will cause some issues with some shells like ZSH when quotes are not used. --- diff --git a/man/systemd-ssh-proxy.xml b/man/systemd-ssh-proxy.xml index 786d16b3ee0..79e28e201c9 100644 --- a/man/systemd-ssh-proxy.xml +++ b/man/systemd-ssh-proxy.xml @@ -24,7 +24,7 @@ -Host unix/* vsock/* vsock-mux/* +Host unix/* unix,* vsock/* vsock,* vsock-mux/* vsock-mux,* ProxyCommand /usr/lib/systemd/systemd-ssh-proxy %h %p ProxyUseFdpass yes @@ -46,7 +46,7 @@ Host unix/* vsock/* vsock-mux/* configuration fragment like the following: -Host unix/* vsock/* vsock-mux/* +Host unix/* unix,* vsock/* vsock,* vsock-mux/* vsock-mux,* ProxyCommand /usr/lib/systemd/systemd-ssh-proxy %h %p ProxyUseFdpass yes CheckHostIP no @@ -69,7 +69,9 @@ Host .host direct AF_VSOCK communication between the host and guests, and provide their own multiplexer over AF_UNIX sockets. See cloud-hypervisor VSOCK support - and Using the Firecracker Virtio-vsock Device. + and Using the Firecracker Virtio-vsock Device. + Note that , can be used as a separator instead of / to be + compatible with tools like scp and rsync. Moreover, connecting to .host will connect to the local host via SSH, without involving networking. @@ -113,6 +115,12 @@ Host .host ssh unix/run/ssh-unix-local/socket + + + Copy local 'foo' file to a local VM with CID 1348 + + scp foo vsock,1348: + diff --git a/src/ssh-generator/20-systemd-ssh-proxy.conf.in b/src/ssh-generator/20-systemd-ssh-proxy.conf.in index bcd0d456208..bafd9634d34 100644 --- a/src/ssh-generator/20-systemd-ssh-proxy.conf.in +++ b/src/ssh-generator/20-systemd-ssh-proxy.conf.in @@ -9,7 +9,7 @@ Host .host machine/.host # 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/* vsock-mux/* machine/* +Host unix/* unix,* vsock/* vsock,* vsock-mux/* vsock-mux,* machine/* machine,* ProxyCommand {{LIBEXECDIR}}/systemd-ssh-proxy %h %p ProxyUseFdpass yes CheckHostIP no diff --git a/src/ssh-generator/ssh-proxy.c b/src/ssh-generator/ssh-proxy.c index 94ba3d95ac0..c5c10adc6eb 100644 --- a/src/ssh-generator/ssh-proxy.c +++ b/src/ssh-generator/ssh-proxy.c @@ -175,6 +175,15 @@ static int process_machine(const char *machine, const char *port) { return process_vsock_cid(cid, port); } +static char *startswith_sep(const char *s, const char *prefix) { + const char *p = startswith(s, prefix); + + if (p && IN_SET(*p, '/', ',')) + return (char*) p + 1; + + return NULL; +} + static int run(int argc, char* argv[]) { log_setup(); @@ -184,19 +193,19 @@ static int run(int argc, char* argv[]) { const char *host = argv[1], *port = argv[2]; - const char *p = startswith(host, "vsock/"); + const char *p = startswith_sep(host, "vsock"); if (p) return process_vsock_string(p, port); - p = startswith(host, "unix/"); + p = startswith_sep(host, "unix"); if (p) return process_unix(p); - p = startswith(host, "vsock-mux/"); + p = startswith_sep(host, "vsock-mux"); if (p) return process_vsock_mux(p, port); - p = startswith(host, "machine/"); + p = startswith_sep(host, "machine"); if (p) return process_machine(p, port); diff --git a/test/units/TEST-74-AUX-UTILS.ssh.sh b/test/units/TEST-74-AUX-UTILS.ssh.sh index 18848e1220d..6a4f766b6a2 100755 --- a/test/units/TEST-74-AUX-UTILS.ssh.sh +++ b/test/units/TEST-74-AUX-UTILS.ssh.sh @@ -61,4 +61,13 @@ ssh -o StrictHostKeyChecking=no -v -i "$ROOTID" machine/.host cat /etc/machine-i modprobe vsock_loopback ||: if test -e /dev/vsock -a -d /sys/module/vsock_loopback ; then ssh -o StrictHostKeyChecking=no -v -i "$ROOTID" vsock/1 cat /etc/machine-id | cmp - /etc/machine-id + + if ! command -v scp &> /dev/null ; then + echo "scp not found, skipping subtest" >&2 + else + OUT_FILE=$(mktemp -u) + scp -o StrictHostKeyChecking=no -v -i "$ROOTID" vsock,1:/etc/machine-id "$OUT_FILE" + cmp "$OUT_FILE" /etc/machine-id + rm -f "$OUT_FILE" + fi fi