Anyone got an AppVM or Debian standalone solution for Mullvad VPN?

There is the problem.
There should be a file: /srv/salt/mullvad/mullvad-browser-linux-x86_64-13.0.10.tar.xz
It is included in the rpm file, and is extracted to /srv/salt/mullvad/
It seems that your download of the rpm file failed. I suggest that you
remove the package and reinstall.

I never presume to speak for the Qubes team. When I comment in the Forum I speak for myself.

I havent had reports of this - I could set the MTU by default, but it’s
better at high values. It’s only necessary to change it for some mobile
networks, and it is called out in the Mullvad docs.

5 it is.

I’ll look at the possibility of a logout script.

Different use cases. I understand yours. But the spec was for the VPN to
not start automatically, but require user login. (Many users have
sys-net not starting automatically, and require manual login.)

I never presume to speak for the Qubes team. When I comment in the Forum I speak for myself.

Thanks for your work on this.

Just to keep holding out the begging bowl:

Another neat feature I would like is to have the Mullvad browser always set to turn off DNS over HTTPS because of speed issues - of course this would work in my use case because the Mullvad tunnel would automatically be established.

I’ve thought about this a bit. I guess the use case I am really articulating is:

  1. a disposable Mullvad browser + disposable connection that operates pretty similarly to whonix-workstation-dvm: click and go. Modify connection if you need via widget, but it has your account number and auto-logs you off at close of qube (no clogging the account with disp devices).

  2. an installation of Mullvad browser available to all qubes (i.e installed on the usual fedora template), so connection is arbitrary via choice of netvm. Likely using:

  3. a disp-sys-mullvad gateway, which may already be applied here (but I need to sort my networking problems first, my bad), but remembers network settings.

Maybe other existing solutions are more suitable (e.g. Micah Leah’s instructions, @solene’s instructions), but they aren’t disposables. Could they be? Perhaps I just need to experiment more.

You can use firefox policies to set the desired configuration for your disposables:

But I guess the policy files for Mullvad browser should be in another location so you’ll need to find out where they are stored first.

making a qube disposable is just a few clicks away :+1:

Thankyou solene - when I clear my schedule I’ll get to experimenting/learning.

But I have two three questions for you regarding the approach you outline.

  1. Is this set of instructions going to work on Debian (perhaps Debian minimal)? Is it just a matter of substituting dnf with apt? I’m particularly unsure of the scripts you have there. (My aim is to have as few updates as possible if it is a standalone).
  2. If this can be set up as a disposable sys-mullvad, how will the Mullvad service treat it as a device? A new one every time, or as the original template device? There are a limit of 5.
  3. Following, any ideas on a script to log out with Mullvad automatically as part of the qube shutdown process?

I can remove 3isec-qubes-mullvad-vpn and reinstall. To be clear though, the file /srv/salt/mullvad/mullvad-browser-linux-x86_64-13.0.10.tar.xz does exist in /srv/salt/mullvad/.

This is my solution that works for me™:

On a Debian VM:

sudo dpkg -i MullvadVPN-*_amd64.deb
sudo apt install python3-pexpect

Then run this script as user:

#!/usr/bin/env -S python3 -u
# -*- coding: utf-8 -*-

import pexpect
import subprocess


def remove_devices():
    # Removed previous sessions
    devices = subprocess.check_output(["mullvad", "account", "list-devices"], text=True)
    # Split the output into lines
    device_list = devices.split("\n")
    # For each line, except for the last one
    print("Deleting %i devices" % (len(device_list) - 1))
    for device in device_list[1:-1]:
        subprocess.run(["mullvad", "account", "revoke-device", device])


subprocess.run(["mullvad", "tunnel", "ipv6", "set", "off"])
while True:
    print("Executing mullvad account login")
    child = pexpect.spawn("mullvad account login")
    try:
        child.expect(b"Enter account number: ", timeout=10)
    except pexpect.exceptions.TIMEOUT:
        print(child.before)
        print("Timed out waiting")
        continue
    except pexpect.exceptions.ExceptionPexpect as ep:
        print(ep)
        break

    print("Entering Mullvad account number")
    child.sendline('1234567890123456')  # <---- CHANGE THIS

    try:
        child.expect(' set', timeout=10)
    except pexpect.exceptions.EOF:
        print("End of file, retrying")
        child_msg = child.before.decode("ascii")
        print(child_msg)
    except pexpect.exceptions.TIMEOUT:
        print("Timed out waiting")
        print(child.before.decode('ascii'))
    else:
        print(child.before.decode('ascii'))
        break

subprocess.run(["mullvad", "connect"])
remove_devices()

Interesting.

So your ‘remove’ function looks like it takes out all devices. I want to keep a couple of other (physical) devices, like cell phone. Can I get it to skip them? They would have a stable name.

Why set a condition for IP6 off?

Strange.

I’d like to dig in to your configuration a bit, to understand why the
salting has not worked for you. If you would be happy to do this can you
PM me, so we keep the noise out of the forum, and we can report back to
Forum or GitHub with any issues we find. (Completely understand if you
do not want to do this.)

I never presume to speak for the Qubes team. When I comment in the Forum I speak for myself.

I haven’t tried, but this should work:

#!/usr/bin/env -S python3 -u
# -*- coding: utf-8 -*-

import pexpect
import subprocess


def remove_devices():
    # Removed previous sessions
    devices = subprocess.check_output(["mullvad", "account", "list-devices"], text=True)
    # Split the output into lines
    device_list = devices.split("\n")
    # For each line, except for the last one
    print("Deleting %i devices" % (len(device_list) - 1))
    for device in device_list[1:-1]:
        if device not in ("MYDEVICENAME1", "MYDEVICENAME2"):  # <-- CHANGE THIS
            subprocess.run(["mullvad", "account", "revoke-device", device])


subprocess.run(["mullvad", "tunnel", "ipv6", "set", "off"])
while True:
    print("Executing mullvad account login")
    child = pexpect.spawn("mullvad account login")
    try:
        child.expect(b"Enter account number: ", timeout=10)
    except pexpect.exceptions.TIMEOUT:
        print(child.before)
        print("Timed out waiting")
        continue
    except pexpect.exceptions.ExceptionPexpect as ep:
        print(ep)
        break

    print("Entering Mullvad account number")
    child.sendline('1234567890123456')  # <---- CHANGE THIS

    try:
        child.expect(' set', timeout=10)
    except pexpect.exceptions.EOF:
        print("End of file, retrying")
        child_msg = child.before.decode("ascii")
        print(child_msg)
    except pexpect.exceptions.TIMEOUT:
        print("Timed out waiting")
        print(child.before.decode('ascii'))
    else:
        print(child.before.decode('ascii'))
        break

subprocess.run(["mullvad", "connect"])
remove_devices()

As I understand it you need to set all of your Qubes system to work with IPv6, and I had problems in the past with this. I might give it another try.

For the record - adjusting the AppVM MTU value works for me:
sudo ip link set dev eth0 mtu 1380

You can add this firewall rule to your VPN qube to fix this:

Hey there, I did everything as instructed to install the mullvad vpn package. The VMs are up and running, but I have a problem with the DNS. Whenever the VPN is connected I cannot reach any sites. Any documentation you can point me to that would help with this?

Thanks