mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-28 18:02:38 +02:00
Successfully set up reverse ssh forward system, allowing the host to run commands on the guest over ssh
This commit is contained in:
parent
1c39895206
commit
29a148d211
14 changed files with 306 additions and 189 deletions
|
@ -10,72 +10,72 @@ RUN apk -U upgrade && \
|
||||||
poppler-utils \
|
poppler-utils \
|
||||||
py3-magic \
|
py3-magic \
|
||||||
py3-pillow \
|
py3-pillow \
|
||||||
sudo
|
sudo \
|
||||||
# tesseract-ocr \
|
tesseract-ocr \
|
||||||
# tesseract-ocr-data-afr \
|
tesseract-ocr-data-afr \
|
||||||
# tesseract-ocr-data-ara \
|
tesseract-ocr-data-ara \
|
||||||
# tesseract-ocr-data-aze \
|
tesseract-ocr-data-aze \
|
||||||
# tesseract-ocr-data-bel \
|
tesseract-ocr-data-bel \
|
||||||
# tesseract-ocr-data-ben \
|
tesseract-ocr-data-ben \
|
||||||
# tesseract-ocr-data-bul \
|
tesseract-ocr-data-bul \
|
||||||
# tesseract-ocr-data-cat \
|
tesseract-ocr-data-cat \
|
||||||
# tesseract-ocr-data-ces \
|
tesseract-ocr-data-ces \
|
||||||
# tesseract-ocr-data-chi_sim \
|
tesseract-ocr-data-chi_sim \
|
||||||
# tesseract-ocr-data-chi_tra \
|
tesseract-ocr-data-chi_tra \
|
||||||
# tesseract-ocr-data-chr \
|
tesseract-ocr-data-chr \
|
||||||
# tesseract-ocr-data-dan \
|
tesseract-ocr-data-dan \
|
||||||
# tesseract-ocr-data-deu \
|
tesseract-ocr-data-deu \
|
||||||
# tesseract-ocr-data-ell \
|
tesseract-ocr-data-ell \
|
||||||
# tesseract-ocr-data-enm \
|
tesseract-ocr-data-enm \
|
||||||
# tesseract-ocr-data-epo \
|
tesseract-ocr-data-epo \
|
||||||
# tesseract-ocr-data-equ \
|
tesseract-ocr-data-equ \
|
||||||
# tesseract-ocr-data-est \
|
tesseract-ocr-data-est \
|
||||||
# tesseract-ocr-data-eus \
|
tesseract-ocr-data-eus \
|
||||||
# tesseract-ocr-data-fin \
|
tesseract-ocr-data-fin \
|
||||||
# tesseract-ocr-data-fra \
|
tesseract-ocr-data-fra \
|
||||||
# tesseract-ocr-data-frk \
|
tesseract-ocr-data-frk \
|
||||||
# tesseract-ocr-data-frm \
|
tesseract-ocr-data-frm \
|
||||||
# tesseract-ocr-data-glg \
|
tesseract-ocr-data-glg \
|
||||||
# tesseract-ocr-data-grc \
|
tesseract-ocr-data-grc \
|
||||||
# tesseract-ocr-data-heb \
|
tesseract-ocr-data-heb \
|
||||||
# tesseract-ocr-data-hin \
|
tesseract-ocr-data-hin \
|
||||||
# tesseract-ocr-data-hrv \
|
tesseract-ocr-data-hrv \
|
||||||
# tesseract-ocr-data-hun \
|
tesseract-ocr-data-hun \
|
||||||
# tesseract-ocr-data-ind \
|
tesseract-ocr-data-ind \
|
||||||
# tesseract-ocr-data-isl \
|
tesseract-ocr-data-isl \
|
||||||
# tesseract-ocr-data-ita \
|
tesseract-ocr-data-ita \
|
||||||
# tesseract-ocr-data-ita_old \
|
tesseract-ocr-data-ita_old \
|
||||||
# tesseract-ocr-data-jpn \
|
tesseract-ocr-data-jpn \
|
||||||
# tesseract-ocr-data-kan \
|
tesseract-ocr-data-kan \
|
||||||
# tesseract-ocr-data-kat \
|
tesseract-ocr-data-kat \
|
||||||
# tesseract-ocr-data-kor \
|
tesseract-ocr-data-kor \
|
||||||
# tesseract-ocr-data-lav \
|
tesseract-ocr-data-lav \
|
||||||
# tesseract-ocr-data-lit \
|
tesseract-ocr-data-lit \
|
||||||
# tesseract-ocr-data-mal \
|
tesseract-ocr-data-mal \
|
||||||
# tesseract-ocr-data-mkd \
|
tesseract-ocr-data-mkd \
|
||||||
# tesseract-ocr-data-mlt \
|
tesseract-ocr-data-mlt \
|
||||||
# tesseract-ocr-data-msa \
|
tesseract-ocr-data-msa \
|
||||||
# tesseract-ocr-data-nld \
|
tesseract-ocr-data-nld \
|
||||||
# tesseract-ocr-data-nor \
|
tesseract-ocr-data-nor \
|
||||||
# tesseract-ocr-data-pol \
|
tesseract-ocr-data-pol \
|
||||||
# tesseract-ocr-data-por \
|
tesseract-ocr-data-por \
|
||||||
# tesseract-ocr-data-ron \
|
tesseract-ocr-data-ron \
|
||||||
# tesseract-ocr-data-rus \
|
tesseract-ocr-data-rus \
|
||||||
# tesseract-ocr-data-slk \
|
tesseract-ocr-data-slk \
|
||||||
# tesseract-ocr-data-slv \
|
tesseract-ocr-data-slv \
|
||||||
# tesseract-ocr-data-spa \
|
tesseract-ocr-data-spa \
|
||||||
# tesseract-ocr-data-spa_old \
|
tesseract-ocr-data-spa_old \
|
||||||
# tesseract-ocr-data-sqi \
|
tesseract-ocr-data-sqi \
|
||||||
# tesseract-ocr-data-srp \
|
tesseract-ocr-data-srp \
|
||||||
# tesseract-ocr-data-swa \
|
tesseract-ocr-data-swa \
|
||||||
# tesseract-ocr-data-swe \
|
tesseract-ocr-data-swe \
|
||||||
# tesseract-ocr-data-tam \
|
tesseract-ocr-data-tam \
|
||||||
# tesseract-ocr-data-tel \
|
tesseract-ocr-data-tel \
|
||||||
# tesseract-ocr-data-tgl \
|
tesseract-ocr-data-tgl \
|
||||||
# tesseract-ocr-data-tha \
|
tesseract-ocr-data-tha \
|
||||||
# tesseract-ocr-data-tur \
|
tesseract-ocr-data-tur \
|
||||||
# tesseract-ocr-data-ukr \
|
tesseract-ocr-data-ukr \
|
||||||
# tesseract-ocr-data-vie
|
tesseract-ocr-data-vie
|
||||||
|
|
||||||
# Install pdftk
|
# Install pdftk
|
||||||
RUN \
|
RUN \
|
||||||
|
|
|
@ -170,4 +170,10 @@ def gui_main(custom_container, filename):
|
||||||
# If the application is activated and all windows are closed, open a new one
|
# If the application is activated and all windows are closed, open a new one
|
||||||
app_wrapper.application_activated.connect(application_activated)
|
app_wrapper.application_activated.connect(application_activated)
|
||||||
|
|
||||||
sys.exit(app.exec_())
|
# Launch the GUI
|
||||||
|
ret = app.exec_()
|
||||||
|
|
||||||
|
if vm:
|
||||||
|
vm.stop()
|
||||||
|
|
||||||
|
sys.exit(ret)
|
||||||
|
|
|
@ -8,6 +8,8 @@ import socket
|
||||||
import random
|
import random
|
||||||
import getpass
|
import getpass
|
||||||
import json
|
import json
|
||||||
|
import psutil
|
||||||
|
import time
|
||||||
from PySide2 import QtCore
|
from PySide2 import QtCore
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,6 +17,7 @@ class Vm(QtCore.QObject):
|
||||||
STATE_OFF = 0
|
STATE_OFF = 0
|
||||||
STATE_STARTING = 1
|
STATE_STARTING = 1
|
||||||
STATE_ON = 2
|
STATE_ON = 2
|
||||||
|
STATE_FAIL = 3
|
||||||
|
|
||||||
vm_state_change = QtCore.Signal(int)
|
vm_state_change = QtCore.Signal(int)
|
||||||
|
|
||||||
|
@ -25,9 +28,14 @@ class Vm(QtCore.QObject):
|
||||||
# VM starts off
|
# VM starts off
|
||||||
self.state = self.STATE_OFF
|
self.state = self.STATE_OFF
|
||||||
|
|
||||||
|
# Ports for ssh services
|
||||||
|
self.sshd_port = None
|
||||||
|
self.sshd_tunnel_port = None
|
||||||
|
|
||||||
# Processes
|
# Processes
|
||||||
self.vpnkit_p = None
|
self.vpnkit_p = None
|
||||||
self.hyperkit_p = None
|
self.hyperkit_p = None
|
||||||
|
self.sshd_pid = None
|
||||||
|
|
||||||
# Relevant paths
|
# Relevant paths
|
||||||
self.vpnkit_path = self.global_common.get_resource_path("bin/vpnkit")
|
self.vpnkit_path = self.global_common.get_resource_path("bin/vpnkit")
|
||||||
|
@ -50,6 +58,8 @@ class Vm(QtCore.QObject):
|
||||||
self.ssh_client_pubkey_path = os.path.join(
|
self.ssh_client_pubkey_path = os.path.join(
|
||||||
self.state_dir.name, "client_ed25519.pub"
|
self.state_dir.name, "client_ed25519.pub"
|
||||||
)
|
)
|
||||||
|
self.sshd_pid_path = os.path.join(self.state_dir.name, "sshd.pid")
|
||||||
|
self.sshd_log_path = os.path.join(self.state_dir.name, "sshd.log")
|
||||||
self.vm_disk_img_path = os.path.join(self.state_dir.name, "disk.img")
|
self.vm_disk_img_path = os.path.join(self.state_dir.name, "disk.img")
|
||||||
|
|
||||||
# UDID for VM
|
# UDID for VM
|
||||||
|
@ -58,6 +68,12 @@ class Vm(QtCore.QObject):
|
||||||
"earlyprintk=serial console=ttyS0 modules=loop,squashfs,sd-mod"
|
"earlyprintk=serial console=ttyS0 modules=loop,squashfs,sd-mod"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Threads
|
||||||
|
self.wait_t = None
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.stop()
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.state = self.STATE_STARTING
|
self.state = self.STATE_STARTING
|
||||||
self.vm_state_change.emit(self.state)
|
self.vm_state_change.emit(self.state)
|
||||||
|
@ -105,35 +121,39 @@ class Vm(QtCore.QObject):
|
||||||
ssh_client_pubkey = f.read()
|
ssh_client_pubkey = f.read()
|
||||||
|
|
||||||
# Find an open port
|
# Find an open port
|
||||||
sshd_port = self.find_open_port()
|
self.sshd_port = self.find_open_port()
|
||||||
sshd_tunnel_port = self.find_open_port()
|
self.sshd_tunnel_port = self.find_open_port()
|
||||||
|
|
||||||
# Start an sshd service on this port
|
# Start an sshd service on this port
|
||||||
subprocess.run(
|
args = [
|
||||||
[
|
"/usr/sbin/sshd",
|
||||||
"/usr/sbin/sshd",
|
"-4",
|
||||||
"-4",
|
"-E",
|
||||||
"-o",
|
self.sshd_log_path,
|
||||||
f"HostKey={self.ssh_host_key_path}",
|
"-o",
|
||||||
"-o",
|
f"PidFile={self.sshd_pid_path}",
|
||||||
f"ListenAddress=127.0.0.1:{sshd_port}",
|
"-o",
|
||||||
"-o",
|
f"HostKey={self.ssh_host_key_path}",
|
||||||
f"AllowUsers={getpass.getuser()}",
|
"-o",
|
||||||
"-o",
|
f"ListenAddress=127.0.0.1:{self.sshd_port}",
|
||||||
"PasswordAuthentication=no",
|
"-o",
|
||||||
"-o",
|
f"AllowUsers={getpass.getuser()}",
|
||||||
"PubkeyAuthentication=yes",
|
"-o",
|
||||||
"-o",
|
"PasswordAuthentication=no",
|
||||||
"Compression=yes",
|
"-o",
|
||||||
"-o",
|
"PubkeyAuthentication=yes",
|
||||||
"ForceCommand=/usr/bin/whoami",
|
"-o",
|
||||||
"-o",
|
"Compression=yes",
|
||||||
"UseDNS=no",
|
"-o",
|
||||||
"-o",
|
"ForceCommand=/usr/bin/whoami",
|
||||||
f"AuthorizedKeysFile={self.ssh_client_pubkey_path}",
|
"-o",
|
||||||
]
|
"UseDNS=no",
|
||||||
)
|
"-o",
|
||||||
# TODO: keep track of the sshd process so we can kill it on close
|
f"AuthorizedKeysFile={self.ssh_client_pubkey_path}",
|
||||||
|
]
|
||||||
|
args_str = " ".join(pipes.quote(s) for s in args)
|
||||||
|
print("> " + args_str)
|
||||||
|
subprocess.run(args)
|
||||||
|
|
||||||
# Create a JSON object to pass into the VM
|
# Create a JSON object to pass into the VM
|
||||||
# This is a 512kb file that starts with a JSON object, followed by null bytes
|
# This is a 512kb file that starts with a JSON object, followed by null bytes
|
||||||
|
@ -142,8 +162,8 @@ class Vm(QtCore.QObject):
|
||||||
"id_ed25519.pub": ssh_client_pubkey,
|
"id_ed25519.pub": ssh_client_pubkey,
|
||||||
"user": getpass.getuser(),
|
"user": getpass.getuser(),
|
||||||
"ip": "192.168.65.2",
|
"ip": "192.168.65.2",
|
||||||
"port": sshd_port,
|
"port": self.sshd_port,
|
||||||
"tunnel_port": sshd_tunnel_port,
|
"tunnel_port": self.sshd_tunnel_port,
|
||||||
}
|
}
|
||||||
with open(self.vm_disk_img_path, "wb") as f:
|
with open(self.vm_disk_img_path, "wb") as f:
|
||||||
vm_info_bytes = json.dumps(vm_info).encode()
|
vm_info_bytes = json.dumps(vm_info).encode()
|
||||||
|
@ -200,16 +220,39 @@ class Vm(QtCore.QObject):
|
||||||
print("> " + args_str)
|
print("> " + args_str)
|
||||||
self.hyperkit_p = subprocess.Popen(
|
self.hyperkit_p = subprocess.Popen(
|
||||||
args,
|
args,
|
||||||
stdout=sys.stdout,
|
# stdout=sys.stdout,
|
||||||
stderr=subprocess.STDOUT,
|
# stderr=subprocess.STDOUT,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Get the sshd PID
|
||||||
|
with open(self.sshd_pid_path) as f:
|
||||||
|
self.sshd_pid = int(f.read())
|
||||||
|
|
||||||
|
print(f"sshd PID: {self.sshd_pid}")
|
||||||
|
print(f"vpnkit PID: {self.vpnkit_p.pid}")
|
||||||
|
print(f"hyperkit PID: {self.hyperkit_p.pid}")
|
||||||
|
|
||||||
|
# Wait for SSH thread
|
||||||
|
self.wait_t = WaitForSsh(self.sshd_tunnel_port)
|
||||||
|
self.wait_t.connected.connect(self.vm_connected)
|
||||||
|
self.wait_t.timeout.connect(self.vm_timeout)
|
||||||
|
self.wait_t.start()
|
||||||
|
|
||||||
|
def vm_connected(self):
|
||||||
|
self.state = self.STATE_ON
|
||||||
|
self.vm_state_change.emit()
|
||||||
|
|
||||||
|
def vm_timeout(self):
|
||||||
|
self.state = self.STATE_FAIL
|
||||||
|
self.vm_state_change.emit()
|
||||||
|
|
||||||
def restart(self):
|
def restart(self):
|
||||||
self.stop()
|
self.stop()
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
# Kill existing processes
|
# Kill existing processes
|
||||||
|
self.kill_sshd()
|
||||||
if self.vpnkit_p is not None:
|
if self.vpnkit_p is not None:
|
||||||
self.vpnkit_p.terminate()
|
self.vpnkit_p.terminate()
|
||||||
self.vpnkit_p = None
|
self.vpnkit_p = None
|
||||||
|
@ -228,3 +271,34 @@ class Vm(QtCore.QObject):
|
||||||
_, port = tmpsock.getsockname()
|
_, port = tmpsock.getsockname()
|
||||||
|
|
||||||
return port
|
return port
|
||||||
|
|
||||||
|
def kill_sshd(self):
|
||||||
|
if self.sshd_pid and psutil.pid_exists(self.sshd_pid):
|
||||||
|
try:
|
||||||
|
proc = psutil.Process(self.sshd_pid)
|
||||||
|
proc.kill()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.sshd_pid = None
|
||||||
|
|
||||||
|
|
||||||
|
class WaitForSsh(QtCore.QThread):
|
||||||
|
connected = QtCore.Signal()
|
||||||
|
timeout = QtCore.Signal()
|
||||||
|
|
||||||
|
def __init__(self, ssh_port):
|
||||||
|
super(WaitForSsh, self).__init__()
|
||||||
|
self.ssh_port = ssh_port
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# Wait for the SSH port to be open
|
||||||
|
timeout_seconds = 45
|
||||||
|
sock = socket.socket()
|
||||||
|
sock.settimeout(timeout_seconds)
|
||||||
|
try:
|
||||||
|
sock.connect(("127.0.0.1", int(self.ssh_port)))
|
||||||
|
self.connected.emit()
|
||||||
|
sock.close()
|
||||||
|
except socket.timeout:
|
||||||
|
self.timeout.emit()
|
||||||
|
|
|
@ -17,32 +17,15 @@ class WaitingWidget(QtWidgets.QWidget):
|
||||||
self.label.setAlignment(QtCore.Qt.AlignCenter)
|
self.label.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
self.label.setStyleSheet("QLabel { font-size: 20px; }")
|
self.label.setStyleSheet("QLabel { font-size: 20px; }")
|
||||||
|
|
||||||
self.details = QtWidgets.QLabel()
|
|
||||||
self.details.setStyleSheet(
|
|
||||||
"QLabel { background-color: #ffffff; font-size: 12px; padding: 10px; }"
|
|
||||||
)
|
|
||||||
self.details.setFont(self.gui_common.fixed_font)
|
|
||||||
self.details.setAlignment(QtCore.Qt.AlignTop)
|
|
||||||
|
|
||||||
self.details_scrollarea = QtWidgets.QScrollArea()
|
|
||||||
self.details_scrollarea.setMinimumHeight(200)
|
|
||||||
self.details_scrollarea.setWidgetResizable(True)
|
|
||||||
self.details_scrollarea.setWidget(self.details)
|
|
||||||
self.details_scrollarea.verticalScrollBar().rangeChanged.connect(
|
|
||||||
self.scroll_to_bottom
|
|
||||||
)
|
|
||||||
|
|
||||||
# Layout
|
# Layout
|
||||||
layout = QtWidgets.QVBoxLayout()
|
layout = QtWidgets.QVBoxLayout()
|
||||||
layout.addStretch()
|
layout.addStretch()
|
||||||
layout.addWidget(self.label)
|
layout.addWidget(self.label)
|
||||||
layout.addWidget(self.details_scrollarea)
|
|
||||||
layout.addStretch()
|
layout.addStretch()
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
def vm_state_change(self, state):
|
def vm_state_change(self, state):
|
||||||
if state == self.vm.STATE_ON:
|
if state == self.vm.STATE_ON:
|
||||||
self.vm_started.emit()
|
self.vm_started.emit()
|
||||||
|
elif state == self.vm.STATE_FAIL:
|
||||||
def scroll_to_bottom(self, minimum, maximum):
|
self.label.setText("Dangerzone virtual machine failed to start :(")
|
||||||
self.scrollarea.verticalScrollBar().setValue(maximum)
|
|
||||||
|
|
|
@ -14,54 +14,10 @@ This takes awhile to run. It:
|
||||||
|
|
||||||
- Builds a new `dangerzone-converter` docker image
|
- Builds a new `dangerzone-converter` docker image
|
||||||
- Builds an ISO, which includes a copy of this image
|
- Builds an ISO, which includes a copy of this image
|
||||||
- Outputs the ISO, as well as vmlinuz and initramfs files, in the `vm` folder
|
- Outputs files in the `vm` folder
|
||||||
|
|
||||||
## Run the VM
|
## Run the VM
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./run-vm.sh
|
./run-vm.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
You can ssh in as the unprivileged user like this (you need to `brew install socat`):
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ssh -i ./ssh-key/id_ed25519 \
|
|
||||||
-o LogLevel=FATAL \
|
|
||||||
-o Compression=yes \
|
|
||||||
-o IdentitiesOnly=yes \
|
|
||||||
-o StrictHostKeyChecking=no \
|
|
||||||
-o UserKnownHostsFile=/dev/null \
|
|
||||||
-o "ProxyCommand nc -U /Users/user/code/dangerzone/rip_docker/vm/connect" \
|
|
||||||
-v \
|
|
||||||
user@localhost
|
|
||||||
```
|
|
||||||
|
|
||||||
(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
|
|
||||||
|
|
||||||
```
|
|
|
@ -1,3 +1,6 @@
|
||||||
alpine-base
|
alpine-base
|
||||||
openssh
|
podman
|
||||||
podman
|
dropbear
|
||||||
|
sshfs
|
||||||
|
python3
|
||||||
|
sudo
|
|
@ -1,6 +1,6 @@
|
||||||
#!/sbin/openrc-run
|
#!/sbin/openrc-run
|
||||||
name="Dangerzone init script"
|
name="Dangerzone init script"
|
||||||
start_pre() {
|
start() {
|
||||||
# Setup Alpine
|
# Setup Alpine
|
||||||
/sbin/setup-alpine -f /etc/answers.txt -e -q
|
/sbin/setup-alpine -f /etc/answers.txt -e -q
|
||||||
rm /etc/answers.txt
|
rm /etc/answers.txt
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import stat
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -17,25 +17,36 @@ def main():
|
||||||
info = json.loads(s[0 : s.find(b"\0")])
|
info = json.loads(s[0 : s.find(b"\0")])
|
||||||
|
|
||||||
# Create SSH files
|
# Create SSH files
|
||||||
os.makedirs("/home/user/.ssh", mode=0o700, exist_ok=True)
|
os.makedirs("/home/user/.ssh", exist_ok=True)
|
||||||
perms = stat.S_IRUSR | stat.S_IWUSR
|
|
||||||
|
|
||||||
with open("/home/user/.ssh/id_ed25519", "w") as f:
|
with open("/home/user/.ssh/id_ed25519", "w") as f:
|
||||||
f.write(info["id_ed25519"])
|
f.write(info["id_ed25519"])
|
||||||
|
f.write("\n")
|
||||||
|
|
||||||
with open("/home/user/.ssh/id_ed25519.pub", "w") as f:
|
with open("/home/user/.ssh/id_ed25519.pub", "w") as f:
|
||||||
f.write(info["id_ed25519.pub"])
|
f.write(info["id_ed25519.pub"])
|
||||||
|
f.write("\n")
|
||||||
|
|
||||||
with open("/home/user/.ssh/authorized_keys", "w") as f:
|
with open("/home/user/.ssh/authorized_keys", "w") as f:
|
||||||
f.write(info["id_ed25519.pub"])
|
f.write(info["id_ed25519.pub"])
|
||||||
|
f.write("\n")
|
||||||
|
|
||||||
os.chmod("/home/user/.ssh/id_ed25519", perms)
|
os.chmod("/home/user/.ssh", 0o700)
|
||||||
os.chmod("/home/user/.ssh/id_ed25519.pub", perms)
|
os.chmod("/home/user/.ssh/id_ed25519", 0o600)
|
||||||
os.chmod("/home/user/.ssh/authorized_keys", perms)
|
os.chmod("/home/user/.ssh/id_ed25519.pub", 0o644)
|
||||||
|
os.chmod("/home/user/.ssh/authorized_keys", 0o600)
|
||||||
|
|
||||||
|
shutil.chown("/home/user/.ssh", "user", "user")
|
||||||
|
shutil.chown("/home/user/.ssh/id_ed25519", "user", "user")
|
||||||
|
shutil.chown("/home/user/.ssh/id_ed25519.pub", "user", "user")
|
||||||
|
shutil.chown("/home/user/.ssh/authorized_keys", "user", "user")
|
||||||
|
|
||||||
# Start SSH reverse port forward
|
# Start SSH reverse port forward
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
[
|
[
|
||||||
|
"/usr/bin/sudo",
|
||||||
|
"-u",
|
||||||
|
"user",
|
||||||
"/usr/bin/ssh",
|
"/usr/bin/ssh",
|
||||||
"-o",
|
"-o",
|
||||||
"StrictHostKeyChecking=no",
|
"StrictHostKeyChecking=no",
|
||||||
|
@ -45,7 +56,7 @@ def main():
|
||||||
"-R",
|
"-R",
|
||||||
f"{info['tunnel_port']}:127.0.0.1:22",
|
f"{info['tunnel_port']}:127.0.0.1:22",
|
||||||
"-p",
|
"-p",
|
||||||
info["port"],
|
str(info["port"]),
|
||||||
f"{info['user']}@{info['ip']}",
|
f"{info['user']}@{info['ip']}",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
AuthorizedKeysFile .ssh/authorized_keys
|
|
||||||
AllowTcpForwarding no
|
|
||||||
GatewayPorts no
|
|
||||||
X11Forwarding no
|
|
||||||
Subsystem sftp /usr/lib/ssh/sftp-server
|
|
||||||
UseDNS no
|
|
||||||
PasswordAuthentication no
|
|
|
@ -31,8 +31,8 @@ cp -r /home/user/.local/share/containers "$tmp"/etc/container-data
|
||||||
# Start cgroups, required by podman
|
# Start cgroups, required by podman
|
||||||
rc_add cgroups boot
|
rc_add cgroups boot
|
||||||
|
|
||||||
# Start sshd
|
# Start dropbear (ssh server)
|
||||||
rc_add sshd boot
|
rc_add dropbear boot
|
||||||
|
|
||||||
# Run setup-alpine
|
# Run setup-alpine
|
||||||
rc_add dangerzone boot
|
rc_add dangerzone boot
|
||||||
|
|
|
@ -9,5 +9,5 @@ profile_dangerzone() {
|
||||||
kernel_cmdline="console=tty0 console=ttyS0,115200"
|
kernel_cmdline="console=tty0 console=ttyS0,115200"
|
||||||
syslinux_serial="0 115200"
|
syslinux_serial="0 115200"
|
||||||
apkovl="genapkovl-dangerzone.sh"
|
apkovl="genapkovl-dangerzone.sh"
|
||||||
apks="$apks podman openssh sshfs python3"
|
apks="$apks podman dropbear sshfs python3 sudo"
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,20 +4,69 @@ ROOT=$(pwd)/vm
|
||||||
HYPERKIT=/Applications/Docker.app/Contents/Resources/bin/com.docker.hyperkit
|
HYPERKIT=/Applications/Docker.app/Contents/Resources/bin/com.docker.hyperkit
|
||||||
VPNKIT=/Applications/Docker.app/Contents/Resources/bin/com.docker.vpnkit
|
VPNKIT=/Applications/Docker.app/Contents/Resources/bin/com.docker.vpnkit
|
||||||
|
|
||||||
|
SSHD_PORT=4445
|
||||||
|
SSHD_TUNNEL_PORT=4446
|
||||||
|
|
||||||
|
tmp="$(mktemp -d)"
|
||||||
|
trap rm -rf "$tmp" EXIT
|
||||||
|
|
||||||
|
# make ssh keys
|
||||||
|
/usr/bin/ssh-keygen \
|
||||||
|
-t ed25519 \
|
||||||
|
-C dangerzone-host \
|
||||||
|
-N "" \
|
||||||
|
-f "$tmp/host_ed25519"
|
||||||
|
/usr/bin/ssh-keygen \
|
||||||
|
-t ed25519 \
|
||||||
|
-C dangerzone-client \
|
||||||
|
-N "" \
|
||||||
|
-f "$tmp/client_ed25519"
|
||||||
|
|
||||||
|
# run sshd
|
||||||
|
SSHD_PIDFILE=$ROOT/sshd.pid
|
||||||
|
/usr/sbin/sshd \
|
||||||
|
-4 \
|
||||||
|
-E $ROOT/sshd.log \
|
||||||
|
-o PidFile=$ROOT/sshd.pid \
|
||||||
|
-o HostKey=$tmp/host_ed25519 \
|
||||||
|
-o ListenAddress=127.0.0.1:$SSHD_PORT \
|
||||||
|
-o AllowUsers=$(whoami) \
|
||||||
|
-o PasswordAuthentication=no \
|
||||||
|
-o PubkeyAuthentication=yes \
|
||||||
|
-o Compression=yes \
|
||||||
|
-o ForceCommand=/usr/bin/whoami \
|
||||||
|
-o UseDNS=no \
|
||||||
|
-o AuthorizedKeysFile=$tmp/client_ed25519.pub &
|
||||||
|
echo $! > $SSHD_PIDFILE
|
||||||
|
trap 'test -f $SSHD_PIDFILE && kill `cat $SSHD_PIDFILE` && rm $SSHD_PIDFILE' EXIT
|
||||||
|
|
||||||
|
# create disk image
|
||||||
|
cd $ROOT
|
||||||
|
cat > info.json << EOF
|
||||||
|
{
|
||||||
|
"id_ed25519": "$(cat $tmp/client_ed25519 | awk '{printf "%s\\n", $0}')",
|
||||||
|
"id_ed25519.pub": "$(cat $tmp/client_ed25519.pub)",
|
||||||
|
"user": "$(whoami)",
|
||||||
|
"ip": "192.168.65.2",
|
||||||
|
"port": $SSHD_PORT,
|
||||||
|
"tunnel_port": $SSHD_TUNNEL_PORT
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
python3 -c 's=open("info.json").read(); open("disk.img", "wb").write(s.encode()+b"\x00"*(512*1024-len(s)))'
|
||||||
|
|
||||||
|
# run vpnkit
|
||||||
VPNKIT_SOCK=$ROOT/vpnkit.eth.sock
|
VPNKIT_SOCK=$ROOT/vpnkit.eth.sock
|
||||||
PIDFILE=$ROOT/vpnkit.pid
|
VPNKIT_PIDFILE=$ROOT/vpnkit.pid
|
||||||
$VPNKIT \
|
$VPNKIT \
|
||||||
--ethernet=$VPNKIT_SOCK \
|
--ethernet=$VPNKIT_SOCK \
|
||||||
--gateway-ip 192.168.65.1 \
|
--gateway-ip 192.168.65.1 \
|
||||||
--host-ip 192.168.65.2 \
|
--host-ip 192.168.65.2 \
|
||||||
--lowest-ip 192.168.65.3 \
|
--lowest-ip 192.168.65.3 \
|
||||||
--highest-ip 192.168.65.254 &
|
--highest-ip 192.168.65.254 &
|
||||||
echo $! > $PIDFILE
|
echo $! > $VPNKIT_PIDFILE
|
||||||
trap 'test -f $PIDFILE && kill `cat $PIDFILE` && rm $PIDFILE' EXIT
|
trap 'test -f $VPNKIT_PIDFILE && kill `cat $VPNKIT_PIDFILE` && rm $VPNKIT_PIDFILE' EXIT
|
||||||
|
|
||||||
cd $ROOT
|
|
||||||
python3 -c 's="this is a test"; open("disk.img", "wb").write(s.encode()+b"\x00"*(512*1024-len(s)))'
|
|
||||||
|
|
||||||
|
# run hyperkit
|
||||||
$HYPERKIT \
|
$HYPERKIT \
|
||||||
-F $ROOT/hyperkit.pid \
|
-F $ROOT/hyperkit.pid \
|
||||||
-A -u \
|
-A -u \
|
||||||
|
|
43
poetry.lock
generated
43
poetry.lock
generated
|
@ -144,6 +144,17 @@ python-versions = ">=3.6.0"
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
future = "*"
|
future = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "psutil"
|
||||||
|
version = "5.8.0"
|
||||||
|
description = "Cross-platform lib for process and system monitoring in Python."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
test = ["ipaddress", "mock", "unittest2", "enum34", "pywin32", "wmi"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyinstaller"
|
name = "pyinstaller"
|
||||||
version = "4.3"
|
version = "4.3"
|
||||||
|
@ -382,7 +393,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pyt
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = ">=3.7,<3.10"
|
python-versions = ">=3.7,<3.10"
|
||||||
content-hash = "6db74c36125b2d3ad4d04c864c24ecbcf376d5ac75ee7402d950010cade5de96"
|
content-hash = "234d09a8607647ed536d6737a98bdacc9d6296d6f71e1382b9d97342de1911e5"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
altgraph = [
|
altgraph = [
|
||||||
|
@ -439,6 +450,36 @@ pathspec = [
|
||||||
pefile = [
|
pefile = [
|
||||||
{file = "pefile-2021.5.24.tar.gz", hash = "sha256:ed79b2353daa58421459abf4d685953bde0adf9f6e188944f97ba9795f100246"},
|
{file = "pefile-2021.5.24.tar.gz", hash = "sha256:ed79b2353daa58421459abf4d685953bde0adf9f6e188944f97ba9795f100246"},
|
||||||
]
|
]
|
||||||
|
psutil = [
|
||||||
|
{file = "psutil-5.8.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64"},
|
||||||
|
{file = "psutil-5.8.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c"},
|
||||||
|
{file = "psutil-5.8.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df"},
|
||||||
|
{file = "psutil-5.8.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131"},
|
||||||
|
{file = "psutil-5.8.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60"},
|
||||||
|
{file = "psutil-5.8.0-cp27-none-win32.whl", hash = "sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876"},
|
||||||
|
{file = "psutil-5.8.0-cp27-none-win_amd64.whl", hash = "sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65"},
|
||||||
|
{file = "psutil-5.8.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8"},
|
||||||
|
{file = "psutil-5.8.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6"},
|
||||||
|
{file = "psutil-5.8.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac"},
|
||||||
|
{file = "psutil-5.8.0-cp36-cp36m-win32.whl", hash = "sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2"},
|
||||||
|
{file = "psutil-5.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d"},
|
||||||
|
{file = "psutil-5.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935"},
|
||||||
|
{file = "psutil-5.8.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d"},
|
||||||
|
{file = "psutil-5.8.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023"},
|
||||||
|
{file = "psutil-5.8.0-cp37-cp37m-win32.whl", hash = "sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394"},
|
||||||
|
{file = "psutil-5.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563"},
|
||||||
|
{file = "psutil-5.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef"},
|
||||||
|
{file = "psutil-5.8.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28"},
|
||||||
|
{file = "psutil-5.8.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b"},
|
||||||
|
{file = "psutil-5.8.0-cp38-cp38-win32.whl", hash = "sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d"},
|
||||||
|
{file = "psutil-5.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d"},
|
||||||
|
{file = "psutil-5.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7"},
|
||||||
|
{file = "psutil-5.8.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4"},
|
||||||
|
{file = "psutil-5.8.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b"},
|
||||||
|
{file = "psutil-5.8.0-cp39-cp39-win32.whl", hash = "sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0"},
|
||||||
|
{file = "psutil-5.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3"},
|
||||||
|
{file = "psutil-5.8.0.tar.gz", hash = "sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6"},
|
||||||
|
]
|
||||||
pyinstaller = [
|
pyinstaller = [
|
||||||
{file = "pyinstaller-4.3.tar.gz", hash = "sha256:5ecf8bbc230d7298a796e52bb745b95eee12878d141f1645612c99246ecd23f2"},
|
{file = "pyinstaller-4.3.tar.gz", hash = "sha256:5ecf8bbc230d7298a796e52bb745b95eee12878d141f1645612c99246ecd23f2"},
|
||||||
]
|
]
|
||||||
|
|
|
@ -20,6 +20,7 @@ pyobjc-core = {version = "*", platform = "darwin"}
|
||||||
pyobjc-framework-launchservices = {version = "*", platform = "darwin"}
|
pyobjc-framework-launchservices = {version = "*", platform = "darwin"}
|
||||||
strip-ansi = {version = "*", platform = "darwin"}
|
strip-ansi = {version = "*", platform = "darwin"}
|
||||||
colorama = "^0.4.4"
|
colorama = "^0.4.4"
|
||||||
|
psutil = "^5.8.0"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
pyinstaller = {version = "*", platform = "darwin"}
|
pyinstaller = {version = "*", platform = "darwin"}
|
||||||
|
|
Loading…
Reference in a new issue