freedomofpress / dangerzone

Take potentially dangerous PDFs, office documents, or images and convert them to safe PDFs
https://dangerzone.rocks/
GNU Affero General Public License v3.0
3.48k stars 162 forks source link

Investigate removing Docker Desktop dependency for Windows and Mac #118

Open micahflee opened 3 years ago

micahflee commented 3 years ago

It would amazing if Dangerzone could be a standalone program without requiring the user to separately install Docker Desktop. Dangerzone relies on Linux containers though, and so Docker Desktop runs a Linux VM in order to run the containers in.

If we wanted to remove the Docker Desktop dependency we would have to figure out how to launch our own Linux VM in each OS. I think this would be a considerable amount of work and we would have to come up with a solution for each separate platform, but it would be a great improvement.

If we did this it would also make sense to switch from Docker to bubblewrap for Linux: #95

Further evidence / notes (added by @deeplow)

From user interviews, we learned that this was a painpoint for an ex-dangerzone user.

micahflee commented 3 years ago

We'll want to use this: https://www.mobyproject.org/

micahflee commented 3 years ago

I'm testing on macOS to start with. Specifically, we should use HyperKit to run the actual VM: https://github.com/moby/hyperkit and LinuxKit to create the VM image that runs: https://github.com/linuxkit/linuxkit

Installing LinuxKit:

brew tap linuxkit/linuxkit
brew install --HEAD linuxkit

Grab the linuxkit.yml file and build the image:

wget https://raw.githubusercontent.com/linuxkit/linuxkit/master/linuxkit.yml
linuxkit build linuxkit.yml

Now installing hyperkit (it's also easy to build from source):

brew install hyperkit

Then to run the VM:

hyperkit -f kexec,linuxkit-kernel,linuxkit-initrd.img,linuxkit-cmdline

And it works!

$ hyperkit -f kexec,linuxkit-kernel,linuxkit-initrd.img,linuxkit-cmdline                                         
Using fd 5 for I/O notifications
vmx_set_ctlreg: cap_field: 4 bit: 12 unspecified don't care: bit is 0
vmx_set_ctlreg: cap_field: 4 bit: 20 unspecified don't care: bit is 0
vmx_set_ctlreg: cap_field: 3 bit: 13 unspecified don't care: bit is 0
rdmsr to register 0x3a on vcpu 0
rdmsr to register 0x140 on vcpu 0
rdmsr to register 0x64d on vcpu 0
rdmsr to register 0x64e on vcpu 0
rdmsr to register 0x34 on vcpu 0
micahflee commented 3 years ago

I copy linuxkit.yml to dangerzone.yml and remove the nginx service, so here's my dangerzone.yml:

kernel:
  image: linuxkit/kernel:5.10.39
  cmdline: "console=tty0 console=ttyS0 console=ttyAMA0"
init:
  - linuxkit/init:78fb57c7da07c4e43c3a37b27755581da087a3b6
  - linuxkit/runc:bf1e0c61fb4678d6428d0aabbd80db5ea24e4d4d
  - linuxkit/containerd:cc02c2af9c928c2faeccbe4edc78bd297ad91866
  - linuxkit/ca-certificates:4df823737c9bf6a9564b736f1a19fd25d60e909a
onboot:
  - name: sysctl
    image: linuxkit/sysctl:02d2bd74509fd063857ceb4c4f502f09ee4f2e0a
  - name: dhcpcd
    image: linuxkit/dhcpcd:1033f340e2d42f86a60aab70752346f0045ea388
    command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
onshutdown:
  - name: shutdown
    image: busybox:latest
    command: ["/bin/echo", "so long and thanks for all the fish"]
services:
  - name: getty
    image: linuxkit/getty:ed32c71531f5998aa510847bb07bd847492d4101
    env:
     - INSECURE=true
  - name: rngd
    image: linuxkit/rngd:bdabfe138f05f7d48396d2f435af16f5a6ccaa45
files:
  - path: etc/linuxkit-config
    metadata: yaml
trust:
  org:
    - linuxkit
    - library

Then build it:

linuxkit build -format kernel+initrd dangerzone.yml

Then run it:

linuxkit run hyperkit dangerzone

Now I get a shell inside the VM, but there doesn't seem to be a /etc/containerd. I can install it with:

apk add containerd

Now containerd is running, and looks like it's using /run/containerd/containerd.sock as a unix socket.

Also back on my host, the VM's state folder is called dangerzone-state and looks like there's a connect files in there that's also a unix socket.

micahflee commented 3 years ago

Inside the VM you can run runc list to list all the running containers, and also use other runc commands to run stuff in containers, start new containers, etc.

One way to make this work would be to:

I think this would be a great start, but I'd like to be able to actually create brand new containers for each step, and a single service container won't do this. With new containers we can be sure that if malware compromises a container it can't compromise any "safe" output PDFs.

micahflee commented 3 years ago

I've started working in this branch: https://github.com/firstlookmedia/dangerzone/tree/118_rip_docker_desktop

And I hit a problem and opened an upstream issue: https://github.com/linuxkit/linuxkit/issues/3693

micahflee commented 3 years ago

While I'm waiting to see if the upstream bug can get resolved, here is a totally separate way of removing the Docker Desktop dependency. Dangerzone for Mac could switch to use podman (like Linux), and instead of using linuxkit to launch a VM it can use Mulitpass: https://github.com/hutger/podman-on-mac

micahflee commented 3 years ago

Another useful blog post: https://cakemanny.com/2021/05/02/running-linux-in-hyperkit.html

micahflee commented 3 years ago

Another useful resource: https://github.com/ottomatica/slim/blob/master/lib/providers/hyperkit.js

micahflee commented 3 years ago

https://user-images.githubusercontent.com/156128/124326707-bddf1800-db3b-11eb-8ce2-7ab52a7e029c.mov

deeplow commented 2 years ago

. Dangerzone for Mac could switch to use podman (like Linux), and instead of using linuxkit to launch a VM it can use Mulitpass: https://github.com/hutger/podman-on-mac

Podman is now officially supported on mac including apple silicon and can be installed via homebrew. This is potentially interesting to replace the bloated Docker Desktop dependency.

deeplow commented 2 years ago

Notes on installing Docker on Windows

Installing Podman

  1. download unsigned binary from github's podman releases
  2. install binary
    • opens windows "smart screen" saying that's an unstrusted application. Do you really want to run it? (say yes)
    • start installation wizard
    • after install it opens a local webpage in the browser: file:///C:/Program Files/RedHat/podman/podman-for-windows.html
    • [there might be more steps here in a machine where WSL is not installed and will require a restart]
  3. On powershell: podman machine init
    • terminal starts downloading the vm fedora-podman-v36.0.34.tar.xz
    • a Windows Defender pop-up shows asking if we want to allow access to podman (maybe we can deny since we don't need internet access???)
  4. On powershell: podman machine start

Running Dangerzone:

Requirements:

References:

Notes on installing Podman on Apple Silicon Mac

Installing Podman

  1. download installer (there are .pkg installers and a .dmg) I went with the .pkg since the .dmg is not very clear what we're supposed to do with the files it shows.
  2. run installer, following the wizard
  3. open terminal and add podman to $PATH with export PATH=$PATH:/opt/podman/bin (not by defauly due to https://github.com/containers/podman/issues/15542)
  4. on the same terminal: podman machine init It will install a VM like fedora-coreos-36.20220820.2.0-qemu.aarch64.qcow2.xz
  5. on the same terminal: podman machine start

Running Dangerzone

(I haven't tested yet running the dev environment on apple silicon macs)

Note: unlike windows, there were no "allow from unstrusted developer". There was only an admin prompt in the middle of the installation. I've checked the settings and the mac seems to have gatekeeper enabled and the .pkg is reported as code object is not signed at all by codesign -v [.pkg].

marsmensch commented 1 year ago

Podman is probably the preferred option since it's now available for all supported platforms and a lot of information can be consolidated that way. It works on apple silicon macs, too.

One alternative (also using moby) is rancher desktop ( https://rancherdesktop.io). It's also compatible because it provides symlinks for all docker commands for backward compatibility.

e.g. /Users/$USER/.rd/bin/docker -> /Applications/Rancher Desktop.app/Contents/Resources/resources/darwin/bin/docker

This blogpost has a more detailed look at the alternatives: https://dnsmichi.at/2022/03/15/docker-desktop-alternatives-macos-podman-nerdctl-rancher-desktop/

deeplow commented 1 year ago

Interesting proposal. Thanks for the pointers. I'll have to read up on ranger desktop. Ideally the user would install this dependency and not have to deal with its UI. This is achievable with podman, but unlike its desktop counterpart, the cli version doesn't seem to be signed by trusted apple / windows keys -- meaning the user would get prompted about an untrusted application. If we're already going through the trouble of getting windows / mac certificates, this would be understandable.

deeplow commented 11 months ago

More feedback on how to approach this is available in #125.

deeplow commented 6 months ago

@apyrgio said on another thread:

As for Docker Desktop, I just stumbled on this: https://download.docker.com/win/static/stable/x86_64/. It's a list of static builds of Docker, but I'm not sure how they are used in a Windows system? Can we potentially include them in our .exe as binaries, run the Docker daemon as a subprocess, and issue commands? That would be a very interesting avenue to explore.

That would be a pretty nice solution and would help us drop the docker desktop altogether. Although if we do bundle software like this, I'd rather have us build the static file to ensure that it all comes from the source.

However, we'd need to match our release cadence with theirs in order to keep up with the CVEs that will eventually appear. We can also explore if podman has this.