mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-28 18:02:38 +02:00
Start porting VM to Windows
This commit is contained in:
parent
b82ffa2cac
commit
173f31ff41
6 changed files with 166 additions and 35 deletions
39
BUILD.md
39
BUILD.md
|
@ -31,7 +31,13 @@ Create a .deb:
|
||||||
Install dependencies:
|
Install dependencies:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo dnf install -y rpm-build podman python3 python3-setuptools python3-pyside2 python3-appdirs python3-click python3-pyxdg python3-requests python3-colorama
|
sudo dnf install -y rpm-build podman python3 python3-setuptools python3-pyside2 python3-appdirs python3-click python3-pyxdg python3-requests python3-colorama python3-psutil
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the latest container:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./install/linux/build-container.py
|
||||||
```
|
```
|
||||||
|
|
||||||
Run from source tree:
|
Run from source tree:
|
||||||
|
@ -62,7 +68,9 @@ If you don't have it already, install poetry (`pip3 install --user poetry`). The
|
||||||
poetry install
|
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:
|
Make sure [Docker Desktop](https://www.docker.com/products/docker-desktop) and vagrant (`brew install vagrant`) are installed.
|
||||||
|
|
||||||
|
Run this to build a custom Alpine Linux ISO for Dangerzone, and copy it into the `share` folder:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./install/macos/make-vm.sh
|
./install/macos/make-vm.sh
|
||||||
|
@ -97,8 +105,6 @@ The output is in the `dist` folder.
|
||||||
|
|
||||||
## Windows
|
## Windows
|
||||||
|
|
||||||
Install [Docker Desktop](https://www.docker.com/products/docker-desktop).
|
|
||||||
|
|
||||||
These instructions include adding folders to the path in Windows. To do this, go to Start and type "advanced system settings", and open "View advanced system settings" in the Control Panel. Click Environment Variables. Under "System variables" double-click on Path. From there you can add and remove folders that are available in the PATH.
|
These instructions include adding folders to the path in Windows. To do this, go to Start and type "advanced system settings", and open "View advanced system settings" in the Control Panel. Click Environment Variables. Under "System variables" double-click on Path. From there you can add and remove folders that are available in the PATH.
|
||||||
|
|
||||||
Download Python 3.9.0, 32-bit (x86) from https://www.python.org/downloads/release/python-390/. I downloaded python-3.9.0.exe. When installing it, make sure to check the "Add Python 3.9 to PATH" checkbox on the first page of the installer.
|
Download Python 3.9.0, 32-bit (x86) from https://www.python.org/downloads/release/python-390/. I downloaded python-3.9.0.exe. When installing it, make sure to check the "Add Python 3.9 to PATH" checkbox on the first page of the installer.
|
||||||
|
@ -115,6 +121,31 @@ Change to the `dangerzone` folder, and install the poetry dependencies:
|
||||||
poetry install
|
poetry install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Make sure these are installed:
|
||||||
|
|
||||||
|
- [Docker Desktop](https://www.docker.com/products/docker-desktop)
|
||||||
|
- [Vagrant](https://www.vagrantup.com/downloads)
|
||||||
|
- [VirtualBox](https://www.virtualbox.org/wiki/Downloads)
|
||||||
|
- [Chocolatey](https://chocolatey.org/install)
|
||||||
|
|
||||||
|
Open an administrator PowerShell and run:
|
||||||
|
|
||||||
|
```
|
||||||
|
choco install vcbuildtools
|
||||||
|
```
|
||||||
|
|
||||||
|
Build OpenSSH:
|
||||||
|
|
||||||
|
```
|
||||||
|
powershell.exe -executionpolicy remotesigned -File .\install\windows\make-openssh.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
Run this to build a custom Alpine Linux ISO for Dangerzone, and copy it (and some binaries from Docker) into the `share` folder:
|
||||||
|
|
||||||
|
```
|
||||||
|
.\install\windows\make-vm.bat
|
||||||
|
```
|
||||||
|
|
||||||
After that you can launch dangerzone during development with:
|
After that you can launch dangerzone during development with:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import uuid
|
import uuid
|
||||||
import pipes
|
import pipes
|
||||||
|
@ -10,6 +9,7 @@ import getpass
|
||||||
import json
|
import json
|
||||||
import psutil
|
import psutil
|
||||||
import time
|
import time
|
||||||
|
import platform
|
||||||
from PySide2 import QtCore
|
from PySide2 import QtCore
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,6 +32,22 @@ class Vm(QtCore.QObject):
|
||||||
self.sshd_port = None
|
self.sshd_port = None
|
||||||
self.sshd_tunnel_port = None
|
self.sshd_tunnel_port = None
|
||||||
|
|
||||||
|
# Folder to hold temporary files related to the VM
|
||||||
|
self.state_dir = tempfile.TemporaryDirectory()
|
||||||
|
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.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_info_path = os.path.join(self.state_dir.name, "info.json")
|
||||||
|
self.vm_disk_img_path = os.path.join(self.state_dir.name, "disk.img")
|
||||||
|
|
||||||
|
if platform.system() == "Darwin":
|
||||||
# Processes
|
# Processes
|
||||||
self.vpnkit_p = None
|
self.vpnkit_p = None
|
||||||
self.hyperkit_p = None
|
self.hyperkit_p = None
|
||||||
|
@ -46,22 +62,9 @@ class Vm(QtCore.QObject):
|
||||||
"vm/initramfs.img"
|
"vm/initramfs.img"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Folder to hold temporary files related to the VM
|
# 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.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.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.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_info_path = os.path.join(self.state_dir.name, "info.json")
|
|
||||||
self.vm_disk_img_path = os.path.join(self.state_dir.name, "disk.img")
|
|
||||||
|
|
||||||
# UDID for VM
|
# UDID for VM
|
||||||
self.vm_uuid = str(uuid.uuid4())
|
self.vm_uuid = str(uuid.uuid4())
|
||||||
|
@ -69,6 +72,9 @@ class Vm(QtCore.QObject):
|
||||||
"earlyprintk=serial console=ttyS0 modules=loop,squashfs,sd-mod"
|
"earlyprintk=serial console=ttyS0 modules=loop,squashfs,sd-mod"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if platform.system() == "Windows":
|
||||||
|
pass
|
||||||
|
|
||||||
# Threads
|
# Threads
|
||||||
self.wait_t = None
|
self.wait_t = None
|
||||||
|
|
||||||
|
@ -78,9 +84,6 @@ class Vm(QtCore.QObject):
|
||||||
def start(self):
|
def start(self):
|
||||||
print("Starting VM\n")
|
print("Starting VM\n")
|
||||||
|
|
||||||
self.state = self.STATE_STARTING
|
|
||||||
self.vm_state_change.emit(self.state)
|
|
||||||
|
|
||||||
# Delete keys if they already exist
|
# Delete keys if they already exist
|
||||||
for filename in [
|
for filename in [
|
||||||
self.ssh_host_key_path,
|
self.ssh_host_key_path,
|
||||||
|
@ -91,6 +94,10 @@ class Vm(QtCore.QObject):
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
|
|
||||||
|
# Find an open port
|
||||||
|
self.sshd_port = self.find_open_port()
|
||||||
|
self.sshd_tunnel_port = self.find_open_port()
|
||||||
|
|
||||||
# Generate new keys
|
# Generate new keys
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
[
|
[
|
||||||
|
@ -127,10 +134,6 @@ class Vm(QtCore.QObject):
|
||||||
with open(self.ssh_client_pubkey_path) as f:
|
with open(self.ssh_client_pubkey_path) as f:
|
||||||
ssh_client_pubkey = f.read()
|
ssh_client_pubkey = f.read()
|
||||||
|
|
||||||
# Find an open port
|
|
||||||
self.sshd_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
|
||||||
args = [
|
args = [
|
||||||
"/usr/sbin/sshd",
|
"/usr/sbin/sshd",
|
||||||
|
@ -162,6 +165,13 @@ class Vm(QtCore.QObject):
|
||||||
print("> " + args_str)
|
print("> " + args_str)
|
||||||
subprocess.run(args, stdout=self.devnull, stderr=self.devnull)
|
subprocess.run(args, stdout=self.devnull, stderr=self.devnull)
|
||||||
|
|
||||||
|
if platform.system() == "Darwin":
|
||||||
|
self.start_macos()
|
||||||
|
|
||||||
|
def start_macos(self):
|
||||||
|
self.state = self.STATE_STARTING
|
||||||
|
self.vm_state_change.emit(self.state)
|
||||||
|
|
||||||
# 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
|
||||||
guest_vm_info = {
|
guest_vm_info = {
|
||||||
|
@ -257,6 +267,10 @@ class Vm(QtCore.QObject):
|
||||||
self.vm_state_change.emit(self.state)
|
self.vm_state_change.emit(self.state)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
if platform.system() == "Darwin":
|
||||||
|
self.stop_macos()
|
||||||
|
|
||||||
|
def stop_macos(self):
|
||||||
# Kill existing processes
|
# Kill existing processes
|
||||||
self.kill_sshd()
|
self.kill_sshd()
|
||||||
if self.vpnkit_p is not None:
|
if self.vpnkit_p is not None:
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
set DANGERZONE_MODE=container
|
|
||||||
poetry run python .\dev_scripts\dangerzone %*
|
|
12
install/vm-builder/windows.sh
Normal file
12
install/vm-builder/windows.sh
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
VAGRANT_FILES=$(find /vagrant -type f | grep -v /vagrant/.vagrant | grep -v /vagrant/vm)
|
||||||
|
DANGERZONE_CONVERTER_FILES=$(find /opt/dangerzone-converter -type f)
|
||||||
|
|
||||||
|
for FILE in $VAGRANT_FILES; do dos2unix $FILE; done
|
||||||
|
for FILE in $DANGERZONE_CONVERTER_FILES; do dos2unix $FILE; done
|
||||||
|
|
||||||
|
/vagrant/build-iso.sh
|
||||||
|
|
||||||
|
for FILE in $VAGRANT_FILES; do unix2dos $FILE; done
|
||||||
|
for FILE in $DANGERZONE_CONVERTER_FILES; do unix2dos $FILE; done
|
65
install/windows/get-openssh.py
Normal file
65
install/windows/get-openssh.py
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import inspect
|
||||||
|
import requests
|
||||||
|
import hashlib
|
||||||
|
import zipfile
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
zip_url = "https://github.com/PowerShell/Win32-OpenSSH/releases/download/V8.6.0.0p1-Beta/OpenSSH-Win32.zip"
|
||||||
|
expected_zip_sha256 = (
|
||||||
|
"0221324212413a6caf260f95e308d22f8c141fc37727b622a6ad50998c46d226"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Figure out the paths
|
||||||
|
root_path = os.path.dirname(
|
||||||
|
os.path.dirname(
|
||||||
|
os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
zip_path = os.path.join(root_path, "build", "OpenSSH-Win32.zip")
|
||||||
|
extracted_path = os.path.join(root_path, "build", "OpenSSH-Win32")
|
||||||
|
bin_path = os.path.join(root_path, "share", "bin")
|
||||||
|
|
||||||
|
os.makedirs(os.path.join(root_path, "build"), exist_ok=True)
|
||||||
|
os.makedirs(os.path.join(bin_path), exist_ok=True)
|
||||||
|
|
||||||
|
# Make sure openssh is downloaded
|
||||||
|
if not os.path.exists(zip_path):
|
||||||
|
print(f"Downloading {zip_url}")
|
||||||
|
r = requests.get(zip_url)
|
||||||
|
open(zip_path, "wb").write(r.content)
|
||||||
|
zip_sha256 = hashlib.sha256(r.content).hexdigest()
|
||||||
|
else:
|
||||||
|
zip_data = open(zip_path, "rb").read()
|
||||||
|
zip_sha256 = hashlib.sha256(zip_data).hexdigest()
|
||||||
|
|
||||||
|
# Compare the hash
|
||||||
|
if zip_sha256 != expected_zip_sha256:
|
||||||
|
print("ERROR! The sha256 doesn't match:")
|
||||||
|
print("expected: {}".format(expected_zip_sha256))
|
||||||
|
print(" actual: {}".format(zip_sha256))
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
# Extract the zip
|
||||||
|
with zipfile.ZipFile(zip_path, "r") as z:
|
||||||
|
z.extractall(os.path.join(root_path, "build"))
|
||||||
|
|
||||||
|
# Copy binaries to share
|
||||||
|
shutil.copy(os.path.join(extracted_path, "libcrypto.dll"), bin_path)
|
||||||
|
shutil.copy(os.path.join(extracted_path, "moduli"), bin_path)
|
||||||
|
shutil.copy(os.path.join(extracted_path, "scp.exe"), bin_path)
|
||||||
|
shutil.copy(os.path.join(extracted_path, "ssh-agent.exe"), bin_path)
|
||||||
|
shutil.copy(os.path.join(extracted_path, "ssh-keygen.exe"), bin_path)
|
||||||
|
shutil.copy(os.path.join(extracted_path, "ssh.exe"), bin_path)
|
||||||
|
shutil.copy(os.path.join(extracted_path, "sshd.exe"), bin_path)
|
||||||
|
shutil.copyfile(
|
||||||
|
os.path.join(extracted_path, "LICENSE.txt"),
|
||||||
|
os.path.join(bin_path, "LICENSE-OpenSSH.txt"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
11
install/windows/make-vm.bat
Normal file
11
install/windows/make-vm.bat
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
REM Build ISO
|
||||||
|
cd install\vm-builder
|
||||||
|
vagrant up
|
||||||
|
vagrant ssh -- dos2unix /vagrant/windows.sh
|
||||||
|
vagrant ssh -- /vagrant/windows.sh
|
||||||
|
vagrant halt
|
||||||
|
cd ..\..
|
||||||
|
|
||||||
|
REM Copy the ISO to resources
|
||||||
|
if not exists share\vm mkdir share\vm
|
||||||
|
cp install\vm-builder\vm\* share\vm
|
Loading…
Reference in a new issue