]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ssh-proxy: add scp and rsync support
authorMatthieu Baerts (NGI0) <matttbe@kernel.org>
Mon, 7 Apr 2025 15:10:29 +0000 (17:10 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 18 Apr 2025 10:58:28 +0000 (12:58 +0200)
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/<CID>' 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.

man/systemd-ssh-proxy.xml
src/ssh-generator/20-systemd-ssh-proxy.conf.in
src/ssh-generator/ssh-proxy.c
test/units/TEST-74-AUX-UTILS.ssh.sh

index 786d16b3ee0550ee553c1e5c00efe2aa01dfc305..79e28e201c942a6f2fb6844659e37886d655d7e8 100644 (file)
@@ -24,7 +24,7 @@
 
   <refsynopsisdiv>
     <programlisting>
-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
 </programlisting>
@@ -46,7 +46,7 @@ Host unix/* vsock/* vsock-mux/*
     configuration fragment like the following:</para>
 
     <programlisting>
-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 <constant>AF_VSOCK</constant> communication between the host and guests, and provide their own
     multiplexer over <constant>AF_UNIX</constant> sockets. See
     <ulink url="https://github.com/cloud-hypervisor/cloud-hypervisor/blob/main/docs/vsock.md">cloud-hypervisor VSOCK support</ulink>
-    and <ulink url="https://github.com/firecracker-microvm/firecracker/blob/main/docs/vsock.md">Using the Firecracker Virtio-vsock Device</ulink>.</para>
+    and <ulink url="https://github.com/firecracker-microvm/firecracker/blob/main/docs/vsock.md">Using the Firecracker Virtio-vsock Device</ulink>.
+    Note that <literal>,</literal> can be used as a separator instead of <literal>/</literal> to be
+    compatible with tools like <literal>scp</literal> and <literal>rsync</literal>.</para>
 
     <para>Moreover, connecting to <literal>.host</literal> will connect to the local host via SSH, without
     involving networking.</para>
@@ -113,6 +115,12 @@ Host .host
 
       <programlisting>ssh unix/run/ssh-unix-local/socket</programlisting>
     </example>
+
+    <example>
+      <title>Copy local 'foo' file to a local VM with CID 1348</title>
+
+      <programlisting>scp foo vsock,1348:</programlisting>
+    </example>
   </refsect1>
 
   <refsect1>
index bcd0d456208a7da082a626d533c070c4ae00e7a9..bafd9634d34ad8cc9d3a50d201f32354032bf883 100644 (file)
@@ -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
index 94ba3d95ac003187ecf26984af0e71682b0345a9..c5c10adc6ebd8e97ecc4982dfbc011b1d4f2737e 100644 (file)
@@ -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);
 
index 18848e1220d3f8ee0924f21f8b68f35d981c676b..6a4f766b6a28849b571110a81ab3b5fd3164c1f2 100755 (executable)
@@ -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