trailofbits / algo

Set up a personal VPN in the cloud
https://blog.trailofbits.com/2016/12/12/meet-algo-the-vpn-that-works/
GNU Affero General Public License v3.0
28.98k stars 2.32k forks source link

"Unable to start service wg-quick@wg0" on Hyper-V VM #1669

Closed fdcastel closed 4 years ago

fdcastel commented 4 years ago

Describe the bug

Installation fails with:

TASK [wireguard : WireGuard enabled and started] **********************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Unable to start service wg-quick@wg0: Job for wg-quick@wg0.service failed because the control process exited with error code.\nSee \"systemctl status wg-quick@wg0.service\" and \"journalctl -xe\" for details.\n"}
included: /opt/algo/playbooks/rescue.yml for localhost

TASK [debug] **********************************************************************************************************************************************************************************************
ok: [localhost] => {
    "fail_hint": [
        "Sorry, but something went wrong!",
        "Please check the troubleshooting guide.",
        "https://trailofbits.github.io/algo/troubleshooting.html"
    ]
}

TASK [Fail the installation] ******************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Failed as requested from task"}

PLAY RECAP ************************************************************************************************************************************************************************************************
localhost                  : ok=68   changed=28   unreachable=0    failed=1    skipped=35   rescued=1    ignored=0

To Reproduce

Steps to reproduce the behavior:

  1. Create a new VM on Hyper-V using latest cloud image from Ubuntu (18.04.3)

  2. Download Algo

    cd /opt
    git clone https://github.com/trailofbits/algo.git
  3. Install requirements

    cd /opt/algo
    sudo apt install -y python3-virtualenv
    python3 -m virtualenv --python="$(command -v python3)" .env &&
      source .env/bin/activate &&
      python3 -m pip install -U pip virtualenv &&
      python3 -m pip install -r requirements.txt
  4. Edit config.cfg. Change:

    ipsec_enabled: false
    dns_encryption: false
    BetweenClients_DROP: false
    block_smb: false
    block_netbios: false
  5. Install it with unattended parameters:

    ansible-playbook ./main.yml -e "provider=local
                                    server_name=localhost
                                    ondemand_cellular=false
                                    ondemand_wifi=false
                                    dns_adblocking=false
                                    store_pki=true
                                    ssh_tunneling=false
                                    endpoint=MYVPN.EXAMPLE.ORG"

Expected behavior

Rainbows and fireworks.

Additional context

Algo running on: Ubuntu 18.04.3 LTS (Virtualized: microsoft)
Created from git clone. Last commit: b66c9f5 Update CHANGELOG.md
Python 3.6.9
Runtime variables:
    algo_provider "local"
    algo_dns_adblocking "False"
    algo_ssh_tunneling "False"
    wireguard_enabled "True"
    dns_encryption "False"

Full log

(Real usernames and hostnames anonymized)

 [WARNING]: Could not match supplied host pattern, ignoring: vpn-host

PLAY [localhost] ******************************************************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Playbook dir stat] **********************************************************************************************************************************************************************************
ok: [localhost]

TASK [Ensure Ansible is not being run in a world writable directory] **************************************************************************************************************************************
ok: [localhost] => {
    "changed": false,
    "msg": "All assertions passed"
}

TASK [Ensure the requirements installed] ******************************************************************************************************************************************************************
ok: [localhost]

TASK [Set required ansible version as a fact] *************************************************************************************************************************************************************
ok: [localhost] => (item=ansible==2.8.3)

TASK [Verify Python meets Algo VPN requirements] **********************************************************************************************************************************************************
ok: [localhost] => {
    "changed": false,
    "msg": "All assertions passed"
}

TASK [Verify Ansible meets Algo VPN requirements] *********************************************************************************************************************************************************
ok: [localhost] => {
    "changed": false,
    "msg": "All assertions passed"
}

PLAY [Ask user for the input] *****************************************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Set facts based on the input] ***********************************************************************************************************************************************************************
ok: [localhost]

TASK [Set facts based on the input] ***********************************************************************************************************************************************************************
ok: [localhost]

PLAY [Provision the server] *******************************************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************************************************************
ok: [localhost]

--> Please include the following block of text when reporting issues:

Algo running on: Ubuntu 18.04.3 LTS (Virtualized: microsoft)
Created from git clone. Last commit: b66c9f5 Update CHANGELOG.md
Python 3.6.9
Runtime variables:
    algo_provider "local"
    algo_dns_adblocking "False"
    algo_ssh_tunneling "False"
    wireguard_enabled "True"
    dns_encryption "False"

TASK [Display the invocation environment] *****************************************************************************************************************************************************************
changed: [localhost -> localhost]

TASK [Install the requirements] ***************************************************************************************************************************************************************************
changed: [localhost -> localhost]
[local : pause]
Enter the IP address of your server: (or use localhost for local installation):
[localhost]
:
^M
TASK [local : pause] **************************************************************************************************************************************************************************************
ok: [localhost]

TASK [local : Set the facts] ******************************************************************************************************************************************************************************
ok: [localhost]

TASK [local : Set the facts] ******************************************************************************************************************************************************************************
ok: [localhost]

TASK [Set subjectAltName as a fact] ***********************************************************************************************************************************************************************
ok: [localhost]

TASK [Add the server to an inventory group] ***************************************************************************************************************************************************************
changed: [localhost]

TASK [Linux | set OS specific facts] **********************************************************************************************************************************************************************
ok: [localhost]

TASK [Set config paths as facts] **************************************************************************************************************************************************************************
ok: [localhost]

TASK [Update config paths] ********************************************************************************************************************************************************************************
changed: [localhost]

TASK [debug] **********************************************************************************************************************************************************************************************
ok: [localhost] => {
    "IP_subject_alt_name": "MYVPN.EXAMPLE.ORG"
}
Pausing for 20 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)

TASK [A short pause, in order to be sure the instance is ready] *******************************************************************************************************************************************
ok: [localhost]

PLAY [Configure the server and install required software] *************************************************************************************************************************************************

TASK [common : Check the system] **************************************************************************************************************************************************************************
ok: [localhost]
included: /opt/algo/roles/common/tasks/ubuntu.yml for localhost

TASK [common : Gather facts] ******************************************************************************************************************************************************************************
ok: [localhost]

TASK [common : Install unattended-upgrades] ***************************************************************************************************************************************************************
 [WARNING]: Could not find aptitude. Using apt-get instead

ok: [localhost]

TASK [common : Configure unattended-upgrades] *************************************************************************************************************************************************************
changed: [localhost]

TASK [common : Periodic upgrades configured] **************************************************************************************************************************************************************
changed: [localhost]

TASK [common : Disable MOTD on login and SSHD] ************************************************************************************************************************************************************
changed: [localhost] => (item={'regexp': '^session.*optional.*pam_motd.so.*', 'line': '# MOTD DISABLED', 'file': '/etc/pam.d/login'})
changed: [localhost] => (item={'regexp': '^session.*optional.*pam_motd.so.*', 'line': '# MOTD DISABLED', 'file': '/etc/pam.d/sshd'})

TASK [common : Loopback for services configured] **********************************************************************************************************************************************************
changed: [localhost]

TASK [common : systemd services enabled and started] ******************************************************************************************************************************************************
ok: [localhost] => (item=systemd-networkd)
ok: [localhost] => (item=systemd-resolved)

RUNNING HANDLER [common : restart systemd-networkd] *******************************************************************************************************************************************************
changed: [localhost]

TASK [common : Check apparmor support] ********************************************************************************************************************************************************************
ok: [localhost]

TASK [common : Set fact if apparmor enabled] **************************************************************************************************************************************************************
ok: [localhost]

TASK [common : Define facts] ******************************************************************************************************************************************************************************
ok: [localhost]

TASK [common : Set facts] *********************************************************************************************************************************************************************************
ok: [localhost]

TASK [common : Set IPv6 support as a fact] ****************************************************************************************************************************************************************
ok: [localhost]

TASK [common : Check size of MTU] *************************************************************************************************************************************************************************
ok: [localhost]

TASK [common : Set OS specific facts] *********************************************************************************************************************************************************************
ok: [localhost]

TASK [common : Install tools] *****************************************************************************************************************************************************************************
changed: [localhost]

TASK [common : Install headers] ***************************************************************************************************************************************************************************
ok: [localhost]
included: /opt/algo/roles/common/tasks/iptables.yml for localhost

TASK [common : Iptables configured] ***********************************************************************************************************************************************************************
changed: [localhost] => (item={'src': 'rules.v4.j2', 'dest': '/etc/iptables/rules.v4'})

TASK [common : Sysctl tuning] *****************************************************************************************************************************************************************************
changed: [localhost] => (item={'item': 'net.ipv4.ip_forward', 'value': 1})
changed: [localhost] => (item={'item': 'net.ipv4.conf.all.forwarding', 'value': 1})

RUNNING HANDLER [common : restart iptables] ***************************************************************************************************************************************************************
changed: [localhost]
 [WARNING]: flush_handlers task does not support when conditional

TASK [wireguard : Ensure the required directories exist] **************************************************************************************************************************************************
changed: [localhost -> localhost] => (item=configs/MYVPN.EXAMPLE.ORG/wireguard//.pki//preshared)
changed: [localhost -> localhost] => (item=configs/MYVPN.EXAMPLE.ORG/wireguard//.pki//private)
changed: [localhost -> localhost] => (item=configs/MYVPN.EXAMPLE.ORG/wireguard//.pki//public)
ok: [localhost -> localhost] => (item=configs/MYVPN.EXAMPLE.ORG/wireguard/)
included: /opt/algo/roles/wireguard/tasks/ubuntu.yml for localhost

TASK [wireguard : WireGuard repository configured] ********************************************************************************************************************************************************
changed: [localhost]

TASK [wireguard : WireGuard installed] ********************************************************************************************************************************************************************
changed: [localhost]

TASK [wireguard : WireGuard reload-module-on-update] ******************************************************************************************************************************************************
changed: [localhost]

TASK [wireguard : Configure unattended-upgrades] **********************************************************************************************************************************************************
changed: [localhost]

TASK [wireguard : Set OS specific facts] ******************************************************************************************************************************************************************
ok: [localhost]

TASK [wireguard : Generate private keys] ******************************************************************************************************************************************************************
changed: [localhost] => (item=fdcastel)
changed: [localhost] => (item=SOME_USER)
changed: [localhost] => (item=ANOTHER_USER)
changed: [localhost] => (item=MYVPN.EXAMPLE.ORG)

TASK [wireguard : Save private keys] **********************************************************************************************************************************************************************
changed: [localhost -> localhost] => (item=None)
changed: [localhost -> localhost] => (item=None)
changed: [localhost -> localhost] => (item=None)
changed: [localhost -> localhost] => (item=None)
changed: [localhost]

TASK [wireguard : Touch the lock file] ********************************************************************************************************************************************************************
changed: [localhost] => (item=fdcastel)
changed: [localhost] => (item=SOME_USER)
changed: [localhost] => (item=ANOTHER_USER)
changed: [localhost] => (item=MYVPN.EXAMPLE.ORG)

TASK [wireguard : Generate preshared keys] ****************************************************************************************************************************************************************
changed: [localhost] => (item=fdcastel)
changed: [localhost] => (item=SOME_USER)
changed: [localhost] => (item=ANOTHER_USER)
changed: [localhost] => (item=MYVPN.EXAMPLE.ORG)

TASK [wireguard : Save preshared keys] ********************************************************************************************************************************************************************
changed: [localhost -> localhost] => (item=None)
changed: [localhost -> localhost] => (item=None)
changed: [localhost -> localhost] => (item=None)
changed: [localhost -> localhost] => (item=None)
changed: [localhost]

TASK [wireguard : Touch the preshared lock file] **********************************************************************************************************************************************************
changed: [localhost] => (item=fdcastel)
changed: [localhost] => (item=SOME_USER)
changed: [localhost] => (item=ANOTHER_USER)
changed: [localhost] => (item=MYVPN.EXAMPLE.ORG)

TASK [wireguard : Generate public keys] *******************************************************************************************************************************************************************
ok: [localhost] => (item=fdcastel)
ok: [localhost] => (item=SOME_USER)
ok: [localhost] => (item=ANOTHER_USER)
ok: [localhost] => (item=MYVPN.EXAMPLE.ORG)

TASK [wireguard : Save public keys] ***********************************************************************************************************************************************************************
changed: [localhost -> localhost] => (item=None)
changed: [localhost -> localhost] => (item=None)
changed: [localhost -> localhost] => (item=None)
changed: [localhost -> localhost] => (item=None)
changed: [localhost]

TASK [wireguard : WireGuard user list updated] ************************************************************************************************************************************************************
changed: [localhost -> localhost] => (item=fdcastel)
changed: [localhost -> localhost] => (item=SOME_USER)
changed: [localhost -> localhost] => (item=ANOTHER_USER)

TASK [wireguard : set_fact] *******************************************************************************************************************************************************************************
ok: [localhost -> localhost]

TASK [wireguard : WireGuard users config generated] *******************************************************************************************************************************************************
changed: [localhost -> localhost] => (item=[0, 'fdcastel'])
changed: [localhost -> localhost] => (item=[1, 'SOME_USER'])
changed: [localhost -> localhost] => (item=[2, 'ANOTHER_USER'])

TASK [wireguard : Generate QR codes] **********************************************************************************************************************************************************************
ok: [localhost -> localhost] => (item=[0, 'fdcastel'])
ok: [localhost -> localhost] => (item=[1, 'SOME_USER'])
ok: [localhost -> localhost] => (item=[2, 'ANOTHER_USER'])

TASK [wireguard : WireGuard configured] *******************************************************************************************************************************************************************
changed: [localhost]

TASK [wireguard : WireGuard enabled and started] **********************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Unable to start service wg-quick@wg0: Job for wg-quick@wg0.service failed because the control process exited with error code.\nSee \"systemctl status wg-quick@wg0.service\" and \"journalctl -xe\" for details.\n"}
included: /opt/algo/playbooks/rescue.yml for localhost

TASK [debug] **********************************************************************************************************************************************************************************************
ok: [localhost] => {
    "fail_hint": [
        "Sorry, but something went wrong!",
        "Please check the troubleshooting guide.",
        "https://trailofbits.github.io/algo/troubleshooting.html"
    ]
}

TASK [Fail the installation] ******************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Failed as requested from task"}

PLAY RECAP ************************************************************************************************************************************************************************************************
localhost                  : ok=68   changed=28   unreachable=0    failed=1    skipped=35   rescued=1    ignored=0
TC1977 commented 4 years ago

So, what do systemctl status wg-quick@wg0.service and journalctl -xe show you?

And just making sure, but you've got it set so that myvpn.example.org points to your Ubuntu VM?

fdcastel commented 4 years ago

I'm very sorry @TC1977. I completely forgot (late hours...):

systemctl status wg-quick@wg0.service:

ubuntu@ALGO:~$ systemctl status wg-quick@wg0.service
● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
   Loaded: loaded (/lib/systemd/system/wg-quick@.service; indirect; vendor preset: enabled)
   Active: failed (Result: exit-code) since Thu 2019-12-26 23:43:14 UTC; 15h ago
     Docs: man:wg-quick(8)
           man:wg(8)
           https://www.wireguard.com/
           https://www.wireguard.com/quickstart/
           https://git.zx2c4.com/WireGuard/about/src/tools/man/wg-quick.8
           https://git.zx2c4.com/WireGuard/about/src/tools/man/wg.8
 Main PID: 24663 (code=exited, status=1/FAILURE)

Dec 26 23:43:14 ALGO systemd[1]: Starting WireGuard via wg-quick(8) for wg0...
Dec 26 23:43:14 ALGO wg-quick[24663]: [#] ip link add wg0 type wireguard
Dec 26 23:43:14 ALGO wg-quick[24663]: RTNETLINK answers: Operation not supported
Dec 26 23:43:14 ALGO wg-quick[24663]: Unable to access interface: Protocol not supported
Dec 26 23:43:14 ALGO wg-quick[24663]: [#] ip link delete dev wg0
Dec 26 23:43:14 ALGO wg-quick[24663]: Cannot find device "wg0"
Dec 26 23:43:14 ALGO systemd[1]: wg-quick@wg0.service: Main process exited, code=exited, status=1/FAILURE
Dec 26 23:43:14 ALGO systemd[1]: wg-quick@wg0.service: Failed with result 'exit-code'.
Dec 26 23:43:14 ALGO systemd[1]: Failed to start WireGuard via wg-quick(8) for wg0.

Now... journalctl -xe has a very large output. But I believe the interesting part is this:

Dec 26 23:43:12 ALGO ansible-command[24543]: Invoked with chdir=configs/MYVPN.EXAMPLE.ORG/wireguard/ executable=bash _raw_params=umask 077; which segno && segno --scale=5 --output=SOME_USER.png  "[Interface]
                                             PrivateKey = mAT8W0TEF87p5fElefCRsW9antdGO9i4RjKRnf894VU=
                                             Address = 10.30.1.3/24
                                             DNS =  10.10.1.211,10.10.1.212

                                             [Peer]
                                             PublicKey = mCrHmIK3dERG3Fnw/Fwz+Ds2Z5is4GCCB0XtVq/nrUE=
                                             PresharedKey = JvC9/loZccJFFIN/fk5Bq3s/fwaSd0WOKKVH6I08V9E=
                                             AllowedIPs = 0.0.0.0/0,::/0
                                             Endpoint = MYVPN.EXAMPLE.ORG:51820
                                             " || true
                                              _uses_shell=True warn=True stdin_add_newline=True strip_empty_ends=True argv=None creates=None removes=None stdin=None
Dec 26 23:43:13 ALGO ansible-command[24568]: Invoked with chdir=configs/MYVPN.EXAMPLE.ORG/wireguard/ executable=bash _raw_params=umask 077; which segno && segno --scale=5 --output=ANOTHER_USER.png  "[Interface]
                                             PrivateKey = gIHll/N92YT/ixSckqlIqa/fLGzoR7hKbgv9OFM61Xo=
                                             Address = 10.30.1.4/24
                                             DNS =  10.10.1.211,10.10.1.212

                                             [Peer]
                                             PublicKey = mCrHmIK3dERG3Fnw/Fwz+Ds2Z5is4GCCB0XtVq/nrUE=
                                             PresharedKey = Y4Ve6hszCRkvZunQTbL85IeNnzjEBEQelafy4QmgXkA=
                                             AllowedIPs = 0.0.0.0/0,::/0
                                             Endpoint = MYVPN.EXAMPLE.ORG:51820
                                             " || true
                                              _uses_shell=True warn=True stdin_add_newline=True strip_empty_ends=True argv=None creates=None removes=None stdin=None
Dec 26 23:43:13 ALGO python3[24594]: ansible-stat Invoked with path=/etc/wireguard/wg0.conf follow=False get_checksum=True checksum_algorithm=sha1 get_mime=True get_attributes=True get_md5=None
Dec 26 23:43:13 ALGO python3[24607]: ansible-copy Invoked with src=/root/.ansible/tmp/ansible-tmp-1577403793.2755225-22353364926425/source dest=/etc/wireguard/wg0.conf mode=0600 follow=False _original_basename=server.conf.j2 checksum=2a594e567730eea485beb7a20a0737562e432
Dec 26 23:43:13 ALGO python3[24634]: ansible-systemd Invoked with name= state=started enabled=True daemon_reload=False daemon_reexec=False no_block=False force=None masked=None user=None scope=None
Dec 26 23:43:13 ALGO systemd[1]: Reloading.
Dec 26 23:43:14 ALGO systemd[1]: Created slice system-wg\x2dquick.slice.
-- Subject: Unit system-wg\x2dquick.slice has finished start-up
-- Defined-By: systemd
-- Support: http://www.ubuntu.com/support
--
-- Unit system-wg\x2dquick.slice has finished starting up.
--
-- The start-up result is RESULT.
Dec 26 23:43:14 ALGO systemd[1]: Starting WireGuard via wg-quick(8) for wg0...
-- Subject: Unit wg-quick@wg0.service has begun start-up
-- Defined-By: systemd
-- Support: http://www.ubuntu.com/support
--
-- Unit wg-quick@wg0.service has begun starting up.
Dec 26 23:43:14 ALGO wg-quick[24663]: [#] ip link add wg0 type wireguard
Dec 26 23:43:14 ALGO kernel: PKCS#7 signature not signed with a trusted key
Dec 26 23:43:14 ALGO kernel: Lockdown: Loading of unsigned modules is restricted; see man kernel_lockdown.7
Dec 26 23:43:14 ALGO wg-quick[24663]: RTNETLINK answers: Operation not supported
Dec 26 23:43:14 ALGO wg-quick[24663]: Unable to access interface: Protocol not supported
Dec 26 23:43:14 ALGO wg-quick[24663]: [#] ip link delete dev wg0
Dec 26 23:43:14 ALGO kernel: PKCS#7 signature not signed with a trusted key
Dec 26 23:43:14 ALGO wg-quick[24663]: Cannot find device "wg0"
Dec 26 23:43:14 ALGO systemd[1]: wg-quick@wg0.service: Main process exited, code=exited, status=1/FAILURE
Dec 26 23:43:14 ALGO systemd[1]: wg-quick@wg0.service: Failed with result 'exit-code'.
Dec 26 23:43:14 ALGO systemd[1]: Failed to start WireGuard via wg-quick(8) for wg0.
-- Subject: Unit wg-quick@wg0.service has failed
-- Defined-By: systemd
-- Support: http://www.ubuntu.com/support
--
-- Unit wg-quick@wg0.service has failed.
--
-- The result is RESULT.

Please ask me any other information which could be helpful.

fdcastel commented 4 years ago

And just making sure, but you've got it set so that myvpn.example.org points to your Ubuntu VM?

Hmm. Nope. I was first testing it into a local lab. I was going to update it AFTER the installation.

The public dns host (endpoint) is required to be correct (pointing to algo server) DURING the install process? (Sorry, a very first noob algo user here 😉)

davidemyers commented 4 years ago

Try disabling EFI Secure Boot in the Hyper-V settings for this VM.

fdcastel commented 4 years ago

Thanks @davidemyers! That solved the problem.

My VM was indeed with Secure Boot enabled:

Get-VMFirmware ALGO

VMName SecureBoot SecureBootTemplate                PreferredNetworkBootProtocol BootOrder
------ ---------- ------------------                ---------------------------- ---------
ALGO   On         MicrosoftUEFICertificateAuthority IPv4                         {Drive, Network}

Running

Set-VMFirmware ALGO -EnableSecureBoot Off

and running ALGO installer again worked this time.

Just out of curiosity: Why is this needed? I always run my Ubuntu VMs with Secure Boot and MicrosoftUEFICertificateAuthority template with no problems.

davidemyers commented 4 years ago

I believe the issue is that the Linux kernel won't install third-party kernel modules like WireGuard when Secure Booted.

fdcastel commented 4 years ago

I see. Thanks @davidemyers !