Skip to content

Commit

Permalink
virtme: enable ssh support
Browse files Browse the repository at this point in the history
Add support for specifying `--server ssh`, to automatically start and
configure sshd in the virtme-ng guest, and `--client ssh` to connect to
a virtme-ng guest via SSH.

The server's port can be customized with the `--port NUM` option
(default is 2222).

Example usage (start a vng instance with sshd enabled):

 $ vng --server ssh --port 2222

In another shell session on the host, connect to the running instance as
a client:

 $ vng --client ssh --port 2222

Note that it's also possible to use ssh or scp directly, the --client
option is provided for convenience and to be consistent with the vsock
option.

Signed-off-by: Andrea Righi <[email protected]>
  • Loading branch information
arighi committed Dec 23, 2024
1 parent a721287 commit 8c1de59
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 5 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,15 @@ Examples
$ vng --client
```

- Enable ssh in the vng guest:
```
# Start the vng instance with ssh server support:
$ vng --server ssh
# Connect to the vng guest from the host via ssh:
$ vng --client ssh
```

- Run virtme-ng inside a docker container:
```
$ docker run -it --privileged ubuntu:23.10 /bin/bash
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def run(self):
package_files = [
"virtme-init",
"virtme-udhcpc-script",
"virtme-sshd-script",
"virtme-snapd-script",
"virtme-sound-script",
]
Expand Down
34 changes: 31 additions & 3 deletions virtme/commands/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ def make_parser() -> argparse.ArgumentParser:
)

g = parser.add_argument_group(title="Remote Console")
cli_srv_choices = ["console"]
cli_srv_choices = ["console", "ssh"]
g.add_argument(
"--server",
action="store",
Expand Down Expand Up @@ -968,6 +968,28 @@ def cleanup_console_script():
qemuargs.extend(["-device", "vhost-vsock-pci,guest-cid=%d" % args.port])


def ssh_client(args):
remote_cmd = args.remote_cmd if args.remote_cmd else ""
cmd = "ssh -p %d localhost %s" % (args.port, remote_cmd)
if args.dry_run:
print(cmd)
else:
os.system(cmd)


def ssh_server(args, arch, qemuargs, kernelargs):
# Implicitly enable dhcp to automatically get an IP on the network
# interface and prevent interface renaming.
kernelargs.extend(["virtme.dhcp", "net.ifnames=0", "biosdevname=0"])

# Tell virtme-ng-init / virtme-init to start sshd.
kernelargs.extend(["virtme.ssh"])

# Setup a port forward network interface for the guest.
qemuargs.extend(["-device", "%s,netdev=ssh" % (arch.virtio_dev_type("net"))])
qemuargs.extend(["-netdev", "user,id=ssh,hostfwd=tcp::%d-:22" % args.port])


# Allowed characters in mount paths. We can extend this over time if needed.
_SAFE_PATH_PATTERN = "[a-zA-Z0-9_+ /.-]+"
_RWDIR_RE = re.compile("^(%s)(?:=(%s))?$" % (_SAFE_PATH_PATTERN, _SAFE_PATH_PATTERN))
Expand All @@ -980,7 +1002,10 @@ def do_it() -> int:
if args.server is not None:
arg_fail('--client cannot be used with --server.')

console_client(args)
if args.client == 'vsock':
console_client(args)
elif args.client == 'ssh':
ssh_client(args)
sys.exit(0)

arch = architectures.get(args.arch)
Expand Down Expand Up @@ -1526,7 +1551,10 @@ def get_net_mac(index):
)

if args.server is not None:
console_server(args, qemu, arch, qemuargs, kernelargs)
if args.server == "vsock":
console_server(args, qemu, arch, qemuargs, kernelargs)
elif args.server == "ssh":
ssh_server(args, arch, qemuargs, kernelargs)

if args.pwd:
rel_pwd = os.path.relpath(os.getcwd(), args.root)
Expand Down
4 changes: 4 additions & 0 deletions virtme/guest/virtme-init
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,10 @@ if cat /proc/cmdline |grep -q -E '(^| )virtme.dhcp($| )'; then
wait
fi

if cat /proc/cmdline |grep -q -E '(^| )virtme.ssh($| )'; then
$(dirname $0)/virtme-sshd-script
fi

if cat /proc/cmdline |grep -q -E '(^| )virtme.snapd($| )'; then
# If snapd is present in the system try to start it, to properly support snaps.
snapd_bin="/usr/lib/snapd/snapd";
Expand Down
10 changes: 10 additions & 0 deletions virtme/guest/virtme-sshd-script
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
#
# Initialize ssh server for remote connections (option `--server ssh`)

HOME=$(getent passwd "${virtme_user}" | cut -d: -f6)
cat ${HOME}/.ssh/id_rsa.pub >> ${HOME}/.ssh/authorized_keys
chown ${virtme_user} ${HOME}/.ssh/authorized_keys
mkdir -p /run/sshd
rm -f /var/run/nologin
/usr/sbin/sshd -h ~/.ssh/id_rsa
2 changes: 1 addition & 1 deletion virtme_ng/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ def make_parser():
)

g_remote = parser.add_argument_group(title="Remote Console")
cli_srv_choices = ["console"]
cli_srv_choices = ["console", "ssh"]

g_remote.add_argument(
"--server",
Expand Down
2 changes: 1 addition & 1 deletion virtme_ng_init
Submodule virtme_ng_init updated 1 files
+11 −0 src/main.rs

0 comments on commit 8c1de59

Please sign in to comment.