mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-28 18:02:38 +02:00
Refactor how VM image is created to split it into different files, and write ssh-to-host.py script
This commit is contained in:
parent
da75559e3a
commit
1c39895206
11 changed files with 176 additions and 181 deletions
2
BUILD.md
2
BUILD.md
|
@ -59,7 +59,7 @@ poetry install
|
|||
Make sure [Docker Desktop](https://www.docker.com/products/docker-desktop) and vagrant (`brew install vagrant`) are installed and run this to collect the binaries from Docker Desktop and then build a custom Alpine Linux ISO for Dangerzone, and copy them into the `share` folder:
|
||||
|
||||
```
|
||||
./install/macos/get-vm.sh
|
||||
./install/macos/make-vm.sh
|
||||
```
|
||||
|
||||
Run from source tree:
|
||||
|
|
|
@ -10,72 +10,72 @@ RUN apk -U upgrade && \
|
|||
poppler-utils \
|
||||
py3-magic \
|
||||
py3-pillow \
|
||||
sudo \
|
||||
tesseract-ocr \
|
||||
tesseract-ocr-data-afr \
|
||||
tesseract-ocr-data-ara \
|
||||
tesseract-ocr-data-aze \
|
||||
tesseract-ocr-data-bel \
|
||||
tesseract-ocr-data-ben \
|
||||
tesseract-ocr-data-bul \
|
||||
tesseract-ocr-data-cat \
|
||||
tesseract-ocr-data-ces \
|
||||
tesseract-ocr-data-chi_sim \
|
||||
tesseract-ocr-data-chi_tra \
|
||||
tesseract-ocr-data-chr \
|
||||
tesseract-ocr-data-dan \
|
||||
tesseract-ocr-data-deu \
|
||||
tesseract-ocr-data-ell \
|
||||
tesseract-ocr-data-enm \
|
||||
tesseract-ocr-data-epo \
|
||||
tesseract-ocr-data-equ \
|
||||
tesseract-ocr-data-est \
|
||||
tesseract-ocr-data-eus \
|
||||
tesseract-ocr-data-fin \
|
||||
tesseract-ocr-data-fra \
|
||||
tesseract-ocr-data-frk \
|
||||
tesseract-ocr-data-frm \
|
||||
tesseract-ocr-data-glg \
|
||||
tesseract-ocr-data-grc \
|
||||
tesseract-ocr-data-heb \
|
||||
tesseract-ocr-data-hin \
|
||||
tesseract-ocr-data-hrv \
|
||||
tesseract-ocr-data-hun \
|
||||
tesseract-ocr-data-ind \
|
||||
tesseract-ocr-data-isl \
|
||||
tesseract-ocr-data-ita \
|
||||
tesseract-ocr-data-ita_old \
|
||||
tesseract-ocr-data-jpn \
|
||||
tesseract-ocr-data-kan \
|
||||
tesseract-ocr-data-kat \
|
||||
tesseract-ocr-data-kor \
|
||||
tesseract-ocr-data-lav \
|
||||
tesseract-ocr-data-lit \
|
||||
tesseract-ocr-data-mal \
|
||||
tesseract-ocr-data-mkd \
|
||||
tesseract-ocr-data-mlt \
|
||||
tesseract-ocr-data-msa \
|
||||
tesseract-ocr-data-nld \
|
||||
tesseract-ocr-data-nor \
|
||||
tesseract-ocr-data-pol \
|
||||
tesseract-ocr-data-por \
|
||||
tesseract-ocr-data-ron \
|
||||
tesseract-ocr-data-rus \
|
||||
tesseract-ocr-data-slk \
|
||||
tesseract-ocr-data-slv \
|
||||
tesseract-ocr-data-spa \
|
||||
tesseract-ocr-data-spa_old \
|
||||
tesseract-ocr-data-sqi \
|
||||
tesseract-ocr-data-srp \
|
||||
tesseract-ocr-data-swa \
|
||||
tesseract-ocr-data-swe \
|
||||
tesseract-ocr-data-tam \
|
||||
tesseract-ocr-data-tel \
|
||||
tesseract-ocr-data-tgl \
|
||||
tesseract-ocr-data-tha \
|
||||
tesseract-ocr-data-tur \
|
||||
tesseract-ocr-data-ukr \
|
||||
tesseract-ocr-data-vie
|
||||
sudo
|
||||
# tesseract-ocr \
|
||||
# tesseract-ocr-data-afr \
|
||||
# tesseract-ocr-data-ara \
|
||||
# tesseract-ocr-data-aze \
|
||||
# tesseract-ocr-data-bel \
|
||||
# tesseract-ocr-data-ben \
|
||||
# tesseract-ocr-data-bul \
|
||||
# tesseract-ocr-data-cat \
|
||||
# tesseract-ocr-data-ces \
|
||||
# tesseract-ocr-data-chi_sim \
|
||||
# tesseract-ocr-data-chi_tra \
|
||||
# tesseract-ocr-data-chr \
|
||||
# tesseract-ocr-data-dan \
|
||||
# tesseract-ocr-data-deu \
|
||||
# tesseract-ocr-data-ell \
|
||||
# tesseract-ocr-data-enm \
|
||||
# tesseract-ocr-data-epo \
|
||||
# tesseract-ocr-data-equ \
|
||||
# tesseract-ocr-data-est \
|
||||
# tesseract-ocr-data-eus \
|
||||
# tesseract-ocr-data-fin \
|
||||
# tesseract-ocr-data-fra \
|
||||
# tesseract-ocr-data-frk \
|
||||
# tesseract-ocr-data-frm \
|
||||
# tesseract-ocr-data-glg \
|
||||
# tesseract-ocr-data-grc \
|
||||
# tesseract-ocr-data-heb \
|
||||
# tesseract-ocr-data-hin \
|
||||
# tesseract-ocr-data-hrv \
|
||||
# tesseract-ocr-data-hun \
|
||||
# tesseract-ocr-data-ind \
|
||||
# tesseract-ocr-data-isl \
|
||||
# tesseract-ocr-data-ita \
|
||||
# tesseract-ocr-data-ita_old \
|
||||
# tesseract-ocr-data-jpn \
|
||||
# tesseract-ocr-data-kan \
|
||||
# tesseract-ocr-data-kat \
|
||||
# tesseract-ocr-data-kor \
|
||||
# tesseract-ocr-data-lav \
|
||||
# tesseract-ocr-data-lit \
|
||||
# tesseract-ocr-data-mal \
|
||||
# tesseract-ocr-data-mkd \
|
||||
# tesseract-ocr-data-mlt \
|
||||
# tesseract-ocr-data-msa \
|
||||
# tesseract-ocr-data-nld \
|
||||
# tesseract-ocr-data-nor \
|
||||
# tesseract-ocr-data-pol \
|
||||
# tesseract-ocr-data-por \
|
||||
# tesseract-ocr-data-ron \
|
||||
# tesseract-ocr-data-rus \
|
||||
# tesseract-ocr-data-slk \
|
||||
# tesseract-ocr-data-slv \
|
||||
# tesseract-ocr-data-spa \
|
||||
# tesseract-ocr-data-spa_old \
|
||||
# tesseract-ocr-data-sqi \
|
||||
# tesseract-ocr-data-srp \
|
||||
# tesseract-ocr-data-swa \
|
||||
# tesseract-ocr-data-swe \
|
||||
# tesseract-ocr-data-tam \
|
||||
# tesseract-ocr-data-tel \
|
||||
# tesseract-ocr-data-tgl \
|
||||
# tesseract-ocr-data-tha \
|
||||
# tesseract-ocr-data-tur \
|
||||
# tesseract-ocr-data-ukr \
|
||||
# tesseract-ocr-data-vie
|
||||
|
||||
# Install pdftk
|
||||
RUN \
|
||||
|
|
|
@ -133,15 +133,17 @@ class Vm(QtCore.QObject):
|
|||
f"AuthorizedKeysFile={self.ssh_client_pubkey_path}",
|
||||
]
|
||||
)
|
||||
# TODO: keep track of the sshd process so we can kill it on close
|
||||
|
||||
# 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,
|
||||
"user": getpass.getuser(),
|
||||
"ip": "192.168.65.2",
|
||||
"port": sshd_port,
|
||||
"tunnel_port": sshd_tunnel_port,
|
||||
}
|
||||
with open(self.vm_disk_img_path, "wb") as f:
|
||||
vm_info_bytes = json.dumps(vm_info).encode()
|
||||
|
|
|
@ -38,7 +38,7 @@ sudo -u user sh mkimage.sh --tag v3.14 \
|
|||
--repository http://dl-cdn.alpinelinux.org/alpine/v3.14/main \
|
||||
--repository http://dl-cdn.alpinelinux.org/alpine/v3.14/community \
|
||||
--profile dangerzone
|
||||
mv alpine-dangerzone-v3.14-x86_64.iso dangerzone.iso
|
||||
mv /vagrant/vm/alpine-dangerzone-v3.14-x86_64.iso /vagrant/vm/dangerzone.iso
|
||||
|
||||
# Fix permissions
|
||||
chmod 755 /vagrant/vm
|
||||
|
|
12
install/vm-builder/etc/answers.txt
Normal file
12
install/vm-builder/etc/answers.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
KEYMAPOPTS="us us"
|
||||
HOSTNAMEOPTS="-n dangerzone"
|
||||
INTERFACESOPTS="auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet dhcp
|
||||
hostname dangerzone
|
||||
"
|
||||
DNSOPTS="-d example.com 4.4.4.4"
|
||||
TIMEZONEOPTS="-z UTC"
|
||||
SSHDOPTS="-c openssh"
|
3
install/vm-builder/etc/apk/world
Normal file
3
install/vm-builder/etc/apk/world
Normal file
|
@ -0,0 +1,3 @@
|
|||
alpine-base
|
||||
openssh
|
||||
podman
|
22
install/vm-builder/etc/init.d/dangerzone
Executable file
22
install/vm-builder/etc/init.d/dangerzone
Executable file
|
@ -0,0 +1,22 @@
|
|||
#!/sbin/openrc-run
|
||||
name="Dangerzone init script"
|
||||
start_pre() {
|
||||
# Setup Alpine
|
||||
/sbin/setup-alpine -f /etc/answers.txt -e -q
|
||||
rm /etc/answers.txt
|
||||
|
||||
# Create user
|
||||
/usr/sbin/adduser -D -u 1001 user
|
||||
|
||||
# Move containers into home dir
|
||||
mkdir -p /home/user/.local/share
|
||||
mv /etc/container-data /home/user/.local/share/containers
|
||||
chown -R user:user /home/user/.local
|
||||
|
||||
# Allow podman containers to run
|
||||
echo "user:100000:65536" >> /etc/subuid
|
||||
echo "user:100000:65536" >> /etc/subgid
|
||||
|
||||
# SSH reverse tunnel to host
|
||||
/etc/ssh-to-host.py &
|
||||
}
|
55
install/vm-builder/etc/ssh-to-host.py
Executable file
55
install/vm-builder/etc/ssh-to-host.py
Executable file
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import json
|
||||
import stat
|
||||
import subprocess
|
||||
|
||||
|
||||
def main():
|
||||
if not os.path.exists("/dev/vda"):
|
||||
print("Disk is not mounted, skipping")
|
||||
return
|
||||
|
||||
# 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", mode=0o700, exist_ok=True)
|
||||
perms = stat.S_IRUSR | stat.S_IWUSR
|
||||
|
||||
with open("/home/user/.ssh/id_ed25519", "w") as f:
|
||||
f.write(info["id_ed25519"])
|
||||
|
||||
with open("/home/user/.ssh/id_ed25519.pub", "w") as f:
|
||||
f.write(info["id_ed25519.pub"])
|
||||
|
||||
with open("/home/user/.ssh/authorized_keys", "w") as f:
|
||||
f.write(info["id_ed25519.pub"])
|
||||
|
||||
os.chmod("/home/user/.ssh/id_ed25519", perms)
|
||||
os.chmod("/home/user/.ssh/id_ed25519.pub", perms)
|
||||
os.chmod("/home/user/.ssh/authorized_keys", perms)
|
||||
|
||||
# Start SSH reverse port forward
|
||||
subprocess.run(
|
||||
[
|
||||
"/usr/bin/ssh",
|
||||
"-o",
|
||||
"StrictHostKeyChecking=no",
|
||||
"-i",
|
||||
"/home/user/.ssh/id_ed25519",
|
||||
"-N",
|
||||
"-R",
|
||||
f"{info['tunnel_port']}:127.0.0.1:22",
|
||||
"-p",
|
||||
info["port"],
|
||||
f"{info['user']}@{info['ip']}",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
7
install/vm-builder/etc/ssh/sshd_config
Normal file
7
install/vm-builder/etc/ssh/sshd_config
Normal file
|
@ -0,0 +1,7 @@
|
|||
AuthorizedKeysFile .ssh/authorized_keys
|
||||
AllowTcpForwarding no
|
||||
GatewayPorts no
|
||||
X11Forwarding no
|
||||
Subsystem sftp /usr/lib/ssh/sftp-server
|
||||
UseDNS no
|
||||
PasswordAuthentication no
|
|
@ -10,15 +10,6 @@ cleanup() {
|
|||
rm -rf "$tmp"
|
||||
}
|
||||
|
||||
makefile() {
|
||||
OWNER="$1"
|
||||
PERMS="$2"
|
||||
FILENAME="$3"
|
||||
cat > "$FILENAME"
|
||||
chown "$OWNER" "$FILENAME"
|
||||
chmod "$PERMS" "$FILENAME"
|
||||
}
|
||||
|
||||
rc_add() {
|
||||
mkdir -p "$tmp"/etc/runlevels/"$2"
|
||||
ln -sf /etc/init.d/"$1" "$tmp"/etc/runlevels/"$2"/"$1"
|
||||
|
@ -27,107 +18,9 @@ rc_add() {
|
|||
tmp="$(mktemp -d)"
|
||||
trap cleanup EXIT
|
||||
|
||||
mkdir -p "$tmp"/etc/apk
|
||||
makefile root:root 0644 "$tmp"/etc/apk/world <<EOF
|
||||
alpine-base
|
||||
openssh
|
||||
podman
|
||||
EOF
|
||||
|
||||
# Custom sshd config
|
||||
mkdir -p "$tmp"/etc/ssh
|
||||
makefile root:root 0644 "$tmp"/etc/ssh/sshd_config <<EOF
|
||||
AuthorizedKeysFile .ssh/authorized_keys
|
||||
AllowTcpForwarding no
|
||||
GatewayPorts no
|
||||
X11Forwarding no
|
||||
Subsystem sftp /usr/lib/ssh/sftp-server
|
||||
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"
|
||||
HOSTNAMEOPTS="-n dangerzone"
|
||||
INTERFACESOPTS="auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet dhcp
|
||||
hostname dangerzone
|
||||
"
|
||||
DNSOPTS="-d example.com 4.4.4.4"
|
||||
TIMEZONEOPTS="-z UTC"
|
||||
SSHDOPTS="-c openssh"
|
||||
EOF
|
||||
|
||||
mkdir -p "$tmp"/etc/init.d
|
||||
makefile root:root 0755 "$tmp"/etc/init.d/dangerzone <<EOF
|
||||
#!/sbin/openrc-run
|
||||
name="Dangerzone init script"
|
||||
start_pre() {
|
||||
# Setup Alpine
|
||||
/sbin/setup-alpine -f /etc/answers.txt -e -q
|
||||
rm /etc/answers.txt
|
||||
|
||||
# Create user
|
||||
/usr/sbin/adduser -D -u 1001 user
|
||||
|
||||
# Move containers into home dir
|
||||
mkdir -p /home/user/.local/share
|
||||
mv /etc/container-data /home/user/.local/share/containers
|
||||
chown -R user:user /home/user/.local
|
||||
|
||||
# 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
|
||||
# Copy /etc
|
||||
cp -r /vagrant/etc "$tmp"
|
||||
chown -R root:root "$tmp"/etc
|
||||
|
||||
# Fix permissions and add containers to /etc/container-data, temporarily
|
||||
for WEIRD_FILE in $(find /home/user/.local/share/containers -perm 000); do
|
||||
|
@ -144,6 +37,7 @@ rc_add sshd boot
|
|||
# Run setup-alpine
|
||||
rc_add dangerzone boot
|
||||
|
||||
# Other init scripts
|
||||
rc_add devfs sysinit
|
||||
rc_add dmesg sysinit
|
||||
rc_add mdev sysinit
|
||||
|
|
Loading…
Reference in a new issue