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.65k stars 2.31k forks source link

WireGuard interface config in `laptop.conf` sets `Interface.DNS` to an internal IP when running inside Docker #14467

Open moltar opened 2 years ago

moltar commented 2 years ago

Describe the bug

I'm running algo from inside a Docker container.

docker run --cap-drop=all -it -e "ALGO_ARGS=$ALGO_ARGS" -v "$PWD/data:/data" trailofbits/algo:latest

When the setup finishes, I get the files created:

[Interface]
PrivateKey = ...
Address = 10.49.0.3 ,2001:db8:a160::3
DNS =  172.24.117.23, fd00::8:7517

[Peer]
PublicKey = ...
PresharedKey = ...
AllowedIPs = 0.0.0.0/0,::/0
Endpoint = $VPS_IP:$PORT

When I try to connect to this configuration, the connect works, but DNS resolution does not work.

Because 172.24.117.23, I think, is internal Docker DNS.

Why is this set to this IP?

To Reproduce

Steps to reproduce the behavior:

  1. Run config via Docker, like in the above command
  2. Check created config file

Expected behavior

I am not sure what the correct behaviour should be. I realize that the script has no way of knowing host's IP.

But setting I'm not sure if setting it to the host's IP is also the correct option? What if I want to use this config somewhere else?

Additional context

N/A

Full log

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"
}
[WARNING]: The value '' is not a valid IP address or network, passing this value to ipaddr filter might result in breaking change in future.

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

TASK [Set required ansible version as a fact] ********************************************************************************************************************************************************************************
ok: [localhost] => (item=ansible-core==2.12.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"
}
[WARNING]: Found variable using reserved name: no_log

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: Alpine Linux v3.15 (Virtualized: docker)
ZIP file created: 2022-03-26 08:43:42.000000000 +0000
Python 3.10.4
Runtime variables:
    algo_provider "digitalocean"
    algo_dns_adblocking "True"
    algo_ssh_tunneling "False"
    wireguard_enabled "True"
    dns_encryption "True"

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

TASK [Install the requirements] **********************************************************************************************************************************************************************************************
changed: [localhost]

TASK [Generate the SSH private key] ******************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Generate the SSH public key] *******************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Copy the private SSH key to /tmp] **************************************************************************************************************************************************************************************
changed: [localhost]

TASK [Include a provisioning role] *******************************************************************************************************************************************************************************************

TASK [cloud-digitalocean : Set the token as a fact] **************************************************************************************************************************************************************************
ok: [localhost]

TASK [cloud-digitalocean : Get regions] **************************************************************************************************************************************************************************************
ok: [localhost]

TASK [cloud-digitalocean : Set facts about the regions] **********************************************************************************************************************************************************************
ok: [localhost]

TASK [cloud-digitalocean : Set default region] *******************************************************************************************************************************************************************************
ok: [localhost]

TASK [cloud-digitalocean : Set additional facts] *****************************************************************************************************************************************************************************
ok: [localhost]

TASK [cloud-digitalocean : Upload the SSH key] *******************************************************************************************************************************************************************************
ok: [localhost]

TASK [cloud-digitalocean : Creating a droplet...] ****************************************************************************************************************************************************************************
changed: [localhost]

TASK [cloud-digitalocean : set_fact] *****************************************************************************************************************************************************************************************
ok: [localhost]

TASK [cloud-digitalocean : set_fact] *****************************************************************************************************************************************************************************************
ok: [localhost]

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

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

TASK [Additional variables for the server] ***********************************************************************************************************************************************************************************
changed: [localhost]

TASK [Wait until SSH becomes ready...] ***************************************************************************************************************************************************************************************
ok: [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": "IP"
}

TASK [Wait 600 seconds for target connection to become reachable/usable] *****************************************************************************************************************************************************
ok: [localhost -> IP] => (item=IP)

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

TASK [Wait until the cloud-init completed] ***********************************************************************************************************************************************************************************
ok: [IP]

TASK [Ensure the config directory exists] ************************************************************************************************************************************************************************************
changed: [IP -> localhost]

TASK [Dump the ssh config] ***************************************************************************************************************************************************************************************************
changed: [IP -> localhost]

TASK [common : Check the system] *********************************************************************************************************************************************************************************************
ok: [IP]

TASK [common : include_tasks] ************************************************************************************************************************************************************************************************
included: /algo/roles/common/tasks/ubuntu.yml for IP

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

TASK [common : Install software updates] *************************************************************************************************************************************************************************************
ok: [IP]

TASK [common : Check if reboot is required] **********************************************************************************************************************************************************************************
changed: [IP]

TASK [common : Reboot] *******************************************************************************************************************************************************************************************************
changed: [IP]

TASK [common : Wait until the server becomes ready...] ***********************************************************************************************************************************************************************
ok: [IP]

TASK [common : Install unattended-upgrades] **********************************************************************************************************************************************************************************
ok: [IP]

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

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

TASK [common : Disable MOTD on login and SSHD] *******************************************************************************************************************************************************************************
changed: [IP] => (item={'regexp': '^session.*optional.*pam_motd.so.*', 'line': '# MOTD DISABLED', 'file': '/etc/pam.d/login'})
changed: [IP] => (item={'regexp': '^session.*optional.*pam_motd.so.*', 'line': '# MOTD DISABLED', 'file': '/etc/pam.d/sshd'})
[WARNING]: Module remote_tmp /root/.ansible/tmp did not exist and was created with a mode of 0700, this may cause issues when running as another user. To avoid this, create the remote_tmp dir with the correct permissions
manually

TASK [common : Ensure fallback resolvers are set] ****************************************************************************************************************************************************************************
changed: [IP]

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

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

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

RUNNING HANDLER [common : restart systemd-resolved] **************************************************************************************************************************************************************************
changed: [IP]

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

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

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

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

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

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

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

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

TASK [common : include_tasks] ************************************************************************************************************************************************************************************************
included: /algo/roles/common/tasks/iptables.yml for IP

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

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

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

RUNNING HANDLER [common : restart iptables] **********************************************************************************************************************************************************************************
changed: [IP]

TASK [dns : Include tasks for Ubuntu] ****************************************************************************************************************************************************************************************
included: /algo/roles/dns/tasks/ubuntu.yml for IP

TASK [dns : Install dnscrypt-proxy] ******************************************************************************************************************************************************************************************
changed: [IP]

TASK [dns : Ubuntu | Configure AppArmor policy for dnscrypt-proxy] ***********************************************************************************************************************************************************
changed: [IP]

TASK [dns : Ubuntu | Enforce the dnscrypt-proxy AppArmor policy] *************************************************************************************************************************************************************
ok: [IP]

TASK [dns : Ubuntu | Ensure that the dnscrypt-proxy service directory exist] *************************************************************************************************************************************************
changed: [IP]

TASK [dns : Ubuntu | Add custom requirements to successfully start the unit] *************************************************************************************************************************************************
changed: [IP]

TASK [dns : dnscrypt-proxy ip-blacklist configured] **************************************************************************************************************************************************************************
changed: [IP]

TASK [dns : dnscrypt-proxy configured] ***************************************************************************************************************************************************************************************
changed: [IP]

TASK [dns : Adblock script created] ******************************************************************************************************************************************************************************************
changed: [IP]

TASK [dns : Adblock script added to cron] ************************************************************************************************************************************************************************************
changed: [IP]

TASK [dns : Update adblock hosts] ********************************************************************************************************************************************************************************************
ok: [IP]
[WARNING]: flush_handlers task does not support when conditional

RUNNING HANDLER [dns : restart dnscrypt-proxy] *******************************************************************************************************************************************************************************
changed: [IP]

TASK [dns : dnscrypt-proxy enabled and started] ******************************************************************************************************************************************************************************
changed: [IP]

TASK [wireguard : Ensure the required directories exist] *********************************************************************************************************************************************************************
changed: [IP -> localhost] => (item=configs/IP/wireguard//.pki//preshared)
changed: [IP -> localhost] => (item=configs/IP/wireguard//.pki//private)
changed: [IP -> localhost] => (item=configs/IP/wireguard//.pki//public)
changed: [IP -> localhost] => (item=configs/IP/wireguard//apple/ios)
changed: [IP -> localhost] => (item=configs/IP/wireguard//apple/macos)

TASK [wireguard : Include tasks for Ubuntu] **********************************************************************************************************************************************************************************
included: /algo/roles/wireguard/tasks/ubuntu.yml for IP

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

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

TASK [wireguard : Generate private keys] *************************************************************************************************************************************************************************************
changed: [IP] => (item=phone)
changed: [IP] => (item=laptop)
changed: [IP] => (item=IP)

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

TASK [wireguard : Touch the lock file] ***************************************************************************************************************************************************************************************
changed: [IP] => (item=phone)
changed: [IP] => (item=laptop)
changed: [IP] => (item=IP)

TASK [wireguard : Generate preshared keys] ***********************************************************************************************************************************************************************************
changed: [IP] => (item=phone)
changed: [IP] => (item=laptop)
changed: [IP] => (item=IP)

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

TASK [wireguard : Touch the preshared lock file] *****************************************************************************************************************************************************************************
changed: [IP] => (item=phone)
changed: [IP] => (item=laptop)
changed: [IP] => (item=IP)

TASK [wireguard : Generate public keys] **************************************************************************************************************************************************************************************
ok: [IP] => (item=phone)
ok: [IP] => (item=laptop)
ok: [IP] => (item=IP)

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

TASK [wireguard : WireGuard user list updated] *******************************************************************************************************************************************************************************
changed: [IP -> localhost] => (item=phone)
changed: [IP -> localhost] => (item=laptop)

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

TASK [wireguard : WireGuard users config generated] **************************************************************************************************************************************************************************
changed: [IP -> localhost] => (item=[0, 'phone'])
changed: [IP -> localhost] => (item=[1, 'laptop'])

TASK [wireguard : include_tasks] *********************************************************************************************************************************************************************************************
included: /algo/roles/wireguard/tasks/mobileconfig.yml for IP => (item=ios)
included: /algo/roles/wireguard/tasks/mobileconfig.yml for IP => (item=macos)

TASK [wireguard : WireGuard apple mobileconfig generated] ********************************************************************************************************************************************************************
changed: [IP -> localhost] => (item=[0, 'phone'])
changed: [IP -> localhost] => (item=[1, 'laptop'])

TASK [wireguard : WireGuard apple mobileconfig generated] ********************************************************************************************************************************************************************
changed: [IP -> localhost] => (item=[0, 'phone'])
changed: [IP -> localhost] => (item=[1, 'laptop'])

TASK [wireguard : Generate QR codes] *****************************************************************************************************************************************************************************************
ok: [IP -> localhost] => (item=[0, 'phone'])
ok: [IP -> localhost] => (item=[1, 'laptop'])

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

TASK [wireguard : WireGuard enabled and started] *****************************************************************************************************************************************************************************
changed: [IP]

RUNNING HANDLER [wireguard : restart wireguard] ******************************************************************************************************************************************************************************
changed: [IP]

TASK [Dump the configuration] ************************************************************************************************************************************************************************************************
changed: [IP -> localhost]

TASK [Linux | Delete the PKI directory] **************************************************************************************************************************************************************************************
ok: [IP -> localhost]

TASK [debug] *****************************************************************************************************************************************************************************************************************
ok: [IP] => {
    "msg": [
        [
            "\"#                          Congratulations!                            #\"",
            "\"#                     Your Algo server is running.                     #\"",
            "\"#    Config files and certificates are in the ./configs/ directory.    #\"",
            "\"#              Go to https://whoer.net/ after connecting               #\"",
            "\"#        and ensure that all your traffic passes through the VPN.      #\"",
            "\"#                     Local DNS resolver 172.24.117.23, fd00::8:7517                   #\"",
            ""
        ],
        "    ",
        "    ",
        "    \"#      Shell access: ssh -F configs/IP/ssh_config algo        #\"\n"
    ]
}

PLAY RECAP *******************************************************************************************************************************************************************************************************************
IP              : ok=71   changed=43   unreachable=0    failed=0    skipped=63   rescued=0    ignored=0
localhost                  : ok=34   changed=7    unreachable=0    failed=0    skipped=14   rescued=0    ignored=0
davidemyers commented 2 years ago

The address 172.24.117.23 was randomly generated by Algo to be used by dnscrypt-proxy on the VPN server to handle client DNS requests (see local_service_ip in config.cfg). SSH to the VPN server and run a command like host google.com 172.24.117.23 to see if DNS resolution is working. If not check:

systemctl status dnscrypt-proxy

Also make sure your client is really connected to the server:

sudo wg
moltar commented 2 years ago

Thanks, @davidemyers!

systemctl status dnscrypt-proxy

Ahh! Found the issue!

systemd exits with:

Apr 20 11:36:15 algo systemd[1]: Started DNSCrypt client proxy.
Apr 20 11:36:15 algo dnscrypt-proxy[3190]: [2022-04-20 11:36:15] [FATAL] Near line 549 (last key parsed 'static.NextDNS-xyz'): expected a top-level item to end with a newline, comment, or EOF, but got '[' instead
Apr 20 11:36:15 algo systemd[1]: dnscrypt-proxy.service: Main process exited, code=exited, status=255/EXCEPTION
Apr 20 11:36:15 algo systemd[1]: dnscrypt-proxy.service: Failed with result 'exit-code'.

Because the /etc/dnscrypt-proxy/dnscrypt-proxy.toml config file gets generated as:

## ... snip

[static]

  [static.'NextDNS-abc']
  stamp = 'sdns://xyz'  [static.'NextDNS-ipv6-abc']
  stamp = 'sdns://xyz'
  # [static.'myserver']
  # stamp = 'sdns:AQcAAAAAAAAAAAAQMi5kbnNjcnlwdC1jZXJ0Lg'

Note the missing line break before ipv6 config.

moltar commented 2 years ago

Probably need to remove the - here?

https://github.com/trailofbits/algo/blob/d06869e1ebf501734edfc228c20f3ba2c8f6dea0/roles/dns/templates/dnscrypt-proxy.toml.j2#L557

davidemyers commented 2 years ago

Probably need to remove the - here?

I think you might be right about that.