Start working on ssh reverse tunnel stuff

This commit is contained in:
Micah Lee 2021-06-30 16:21:40 -07:00
parent 9158d02669
commit da75559e3a
No known key found for this signature in database
GPG key ID: 403C2657CD994F73
8 changed files with 193 additions and 28 deletions

View file

@ -4,6 +4,10 @@ import subprocess
import uuid
import pipes
import tempfile
import socket
import random
import getpass
import json
from PySide2 import QtCore
@ -34,10 +38,19 @@ class Vm(QtCore.QObject):
"vm/initramfs.img"
)
# Folder to hold files related to the VM
# Folder to hold temporary files related to the VM
self.state_dir = tempfile.TemporaryDirectory()
self.vpnkit_sock_path = os.path.join(self.state_dir.name, "vpnkit.eth.sock")
self.hyperkit_pid_path = os.path.join(self.state_dir.name, "hyperkit.pid")
self.ssh_host_key_path = os.path.join(self.state_dir.name, "host_ed25519")
self.ssh_host_pubkey_path = os.path.join(
self.state_dir.name, "host_ed25519.pub"
)
self.ssh_client_key_path = os.path.join(self.state_dir.name, "client_ed25519")
self.ssh_client_pubkey_path = os.path.join(
self.state_dir.name, "client_ed25519.pub"
)
self.vm_disk_img_path = os.path.join(self.state_dir.name, "disk.img")
# UDID for VM
self.vm_uuid = str(uuid.uuid4())
@ -49,6 +62,92 @@ class Vm(QtCore.QObject):
self.state = self.STATE_STARTING
self.vm_state_change.emit(self.state)
# Delete keys if they already exist
for filename in [
self.ssh_host_key_path,
self.ssh_host_pubkey_path,
self.ssh_client_key_path,
self.ssh_client_pubkey_path,
]:
if os.path.exists(filename):
os.remove(filename)
# Generate new keys
subprocess.run(
[
"/usr/bin/ssh-keygen",
"-t",
"ed25519",
"-C",
"dangerzone-host",
"-N",
"",
"-f",
self.ssh_host_key_path,
]
)
subprocess.run(
[
"/usr/bin/ssh-keygen",
"-t",
"ed25519",
"-C",
"dangerzone-client",
"-N",
"",
"-f",
self.ssh_client_key_path,
]
)
with open(self.ssh_client_key_path) as f:
ssh_client_key = f.read()
with open(self.ssh_client_pubkey_path) as f:
ssh_client_pubkey = f.read()
# Find an open port
sshd_port = self.find_open_port()
sshd_tunnel_port = self.find_open_port()
# Start an sshd service on this port
subprocess.run(
[
"/usr/sbin/sshd",
"-4",
"-o",
f"HostKey={self.ssh_host_key_path}",
"-o",
f"ListenAddress=127.0.0.1:{sshd_port}",
"-o",
f"AllowUsers={getpass.getuser()}",
"-o",
"PasswordAuthentication=no",
"-o",
"PubkeyAuthentication=yes",
"-o",
"Compression=yes",
"-o",
"ForceCommand=/usr/bin/whoami",
"-o",
"UseDNS=no",
"-o",
f"AuthorizedKeysFile={self.ssh_client_pubkey_path}",
]
)
# Create a JSON object to pass into the VM
# This is a 512kb file that starts with a JSON object, followed by null bytes
vm_info = {
"id_ed25519": ssh_client_key,
"id_ed25519.pub": ssh_client_pubkey,
"ssh_target": f"{getpass.getuser()}@192.168.65.2",
"sshd_port": sshd_port,
"sshd_tunnel_port": sshd_tunnel_port,
}
with open(self.vm_disk_img_path, "wb") as f:
vm_info_bytes = json.dumps(vm_info).encode()
f.write(vm_info_bytes)
f.write(b"\x00" * (512 * 1024 - len(vm_info_bytes)))
# Run VPNKit
args = [
self.vpnkit_path,
@ -65,11 +164,7 @@ class Vm(QtCore.QObject):
]
args_str = " ".join(pipes.quote(s) for s in args)
print("> " + args_str)
self.vpnkit_p = subprocess.Popen(
args,
stdout=sys.stdout,
stderr=subprocess.STDOUT,
)
self.vpnkit_p = subprocess.Popen(args)
# Run Hyperkit
args = [
@ -92,6 +187,8 @@ class Vm(QtCore.QObject):
f"1:0,ahci-cd,{self.vm_iso_path}",
"-s",
f"2:0,virtio-vpnkit,path={self.vpnkit_sock_path}",
"-s",
f"3:0,virtio-blk,{self.vm_disk_img_path}",
"-U",
self.vm_uuid,
"-f",
@ -117,3 +214,15 @@ class Vm(QtCore.QObject):
if self.hyperkit_p is not None:
self.hyperkit_p.terminate()
self.hyperkit_p = None
def find_open_port(self):
with socket.socket() as tmpsock:
while True:
try:
tmpsock.bind(("127.0.0.1", random.randint(1024, 65535)))
break
except OSError:
pass
_, port = tmpsock.getsockname()
return port

View file

@ -37,3 +37,31 @@ ssh -i ./ssh-key/id_ed25519 \
```
(doesn't work yet)
Notes on sshd:
```
# Generate keys
rm -r state
mkdir state
ssh-keygen -t ed25519 -C dangerzone-vm-key -N "" -f state/host_ed25519
ssh-keygen -t ed25519 -C dangerzone-vm-key -N "" -f state/client_ed25519
# start sshd service
/usr/sbin/sshd -4 \
-o HostKey=$(pwd)/state/host_ed25519 \
-o ListenAddress=127.0.0.1:4444 \
-o AllowUsers=$(whoami) \
-o PasswordAuthentication=no \
-o PubkeyAuthentication=yes \
-o Compression=yes \
-o ForceCommand=/usr/bin/whoami \
-o UseDNS=no \
-o AuthorizedKeysFile=$(pwd)/state/client_ed25519.pub
# in the vm, making an ssh tunnel
ssh -o StrictHostKeyChecking=no -N -R 52038:127.0.0.1:22 -p 52039 user@192.168.65.2
```

View file

@ -46,6 +46,39 @@ UseDNS no
PasswordAuthentication no
EOF
# Script to read info from host
makefile root:root 0755 "$tmp"/etc/read-info-from-host <<EOF
#!/usr/bin/env python3
import json
# Read data
with open("/dev/vda", "rb") as f:
s = f.read()
info = json.loads(s[0:s.find(b"\0")])
# Create SSH files
os.makedirs("/home/user/.ssh", exist_ok=True)
with open("/home/user/.ssh/id_ed25519") as f:
f.write(info["id_ed25519"])
with open("/home/user/.ssh/id_ed25519.pub") as f:
f.write(info["id_ed25519.pub"])
with open("/home/user/.ssh/authorized_keys") as f:
f.write(info["id_ed25519.pub"])
with open("/home/user/.ssh/env_ssh_target") as f:
f.write(info['ssh_target'])
with open("/home/user/.ssh/env_sshd_port") as f:
f.write(info['sshd_port'])
with open("/home/user/.ssh/env_sshd_tunnel_port") as f:
f.write(info['sshd_tunnel_port'])
EOF
# Dangerzone alpine setup
makefile root:root 0644 "$tmp"/etc/answers.txt <<EOF
KEYMAPOPTS="us us"
@ -71,13 +104,8 @@ start_pre() {
/sbin/setup-alpine -f /etc/answers.txt -e -q
rm /etc/answers.txt
# Create user, give the dangerzone-vm-key ssh access
# Create user
/usr/sbin/adduser -D -u 1001 user
mkdir -p /home/user/.ssh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILmxIw2etg2IxY77GOFe/6tuMH/K5c1gsz3qPY/s7rZF dangerzone-vm-key" > /home/user/.ssh/authorized_keys
chown -R user:user /home/user/.ssh
chmod 700 /home/user/.ssh
chmod 600 /home/user/.ssh/authorized_keys
# Move containers into home dir
mkdir -p /home/user/.local/share
@ -87,6 +115,17 @@ start_pre() {
# Allow podman containers to run
echo "user:100000:65536" >> /etc/subuid
echo "user:100000:65536" >> /etc/subgid
# Get info from the host
/etc/read-info-from-host
chmod 700 /home/user/.ssh
chmod 600 /home/user/.ssh/*
# Start the ssh reverse tunnel
SSH_TARGET=$(cat /home/user/.ssh/env_ssh_target)
SSHD_PORT=$(cat /home/user/.ssh/env_sshd_port)
SSHD_TUNNEL_PORT=$(cat /home/user/.ssh/sshd_tunnel_port)
/usr/bin/ssh -o StrictHostKeyChecking=no -N -R $SSHD_TUNNEL_PORT:127.0.0.1:22 -p $SSHD_PORT $SSH_TARGET &
}
EOF

View file

@ -9,5 +9,5 @@ profile_dangerzone() {
kernel_cmdline="console=tty0 console=ttyS0,115200"
syslinux_serial="0 115200"
apkovl="genapkovl-dangerzone.sh"
apks="$apks podman openssh"
apks="$apks podman openssh sshfs python3"
}

View file

@ -15,6 +15,9 @@ $VPNKIT \
echo $! > $PIDFILE
trap 'test -f $PIDFILE && kill `cat $PIDFILE` && rm $PIDFILE' EXIT
cd $ROOT
python3 -c 's="this is a test"; open("disk.img", "wb").write(s.encode()+b"\x00"*(512*1024-len(s)))'
$HYPERKIT \
-F $ROOT/hyperkit.pid \
-A -u \
@ -24,5 +27,6 @@ $HYPERKIT \
-l com1,stdio \
-s 1:0,ahci-cd,$ROOT/dangerzone.iso \
-s 2:0,virtio-vpnkit,path=$VPNKIT_SOCK \
-s 3:0,virtio-blk,$ROOT/disk.img \
-U 9efa82d7-ebd5-4287-b1cc-ac4160a39fa7 \
-f kexec,$ROOT/kernel,$ROOT/initramfs.img,"earlyprintk=serial console=ttyS0 modules=loop,squashfs,sd-mod"

View file

@ -1,7 +0,0 @@
# Dangerzone VM key
This is an insecure hard-coded SSH key that's built-in to allow ssh access to the VM's `user` account. It was generated like this:
```sh
ssh-keygen -t ed25519 -C dangerzone-vm-key -N "" -f id_ed25519
```

View file

@ -1,7 +0,0 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACC5sSMNnrYNiMWO+xjhXv+rbjB/yuXNYLM96j2P7O62RQAAAJhcTPZgXEz2
YAAAAAtzc2gtZWQyNTUxOQAAACC5sSMNnrYNiMWO+xjhXv+rbjB/yuXNYLM96j2P7O62RQ
AAAEBCvhorS+9SPDNqhyxAPvFMnzkbUoc6HcM6Ll2W8F5krrmxIw2etg2IxY77GOFe/6tu
MH/K5c1gsz3qPY/s7rZFAAAAEWRhbmdlcnpvbmUtdm0ta2V5AQIDBA==
-----END OPENSSH PRIVATE KEY-----

View file

@ -1 +0,0 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILmxIw2etg2IxY77GOFe/6tuMH/K5c1gsz3qPY/s7rZF dangerzone-vm-key