codespaces-contrib / codespaces-openvpn

MIT License
44 stars 49 forks source link

Does not work when server pushes multiple dhcp-options #10

Open allen-branch opened 1 year ago

allen-branch commented 1 year ago

Setup my codespace using

sudo apt-get -y update
sudo apt-get -y install --no-install-recommends openvpn resolvconf

Added to my client.ovpn

script-security 2 
up /etc/openvpn/update-resolv-conf 
down /etc/openvpn/update-resolv-conf

Confirmed that the script was being called correctly and passed the multiple dhcp-options.

Expected my /etc/resolv.conf to be updated with all of the pushed dhcp-options among other things.

However, my resolv.conf is not updated correctly with multiple

allen-branch commented 1 year ago

This is my workaround for now.

#!/usr/bin/env -S npx zx --experimental

// Switch to the .openvpn folder
await $`mkdir -p ~/.openvpn`;

cd(`${process.env.HOME}/.openvpn`);

// Touch file to make sure this user can read it
await $`touch openvpn.log`;

// If we are running as root, we do not need to use sudo
let sudo_cmd = "";
if (process.getuid() !== 0) {
  sudo_cmd = "sudo";
}

// Start openvpn
await $`${sudo_cmd} openvpn --config ~/.openvpn/client.ovpn --log ~/.openvpn/openvpn.log --daemon`;

const checkAuthSucceeded = () =>
  $`timeout 60s grep -q 'Initialization Sequence Completed' <(tail -f ~/.openvpn/openvpn.log)`;

// Wait for the VPN to come up
await spinner("Waiting for the VPN to come up...", checkAuthSucceeded);

// openvpn in codespaces does not update /etc/resolv.conf correctly with multiple DNS servers
const manuallyPatchDnsServers = async () => {
  const log =
    await $`timeout 60s grep 'PUSH: Received control message:' <(cat ~/.openvpn/openvpn.log)`;

  const dnsServers = log.stdout
    .toString()
    .match(/dhcp-option DNS ([0-9.]+).([0-9.]+).([0-9.]+).([0-9.]+)/g)
    .map((dnsServer) => dnsServer.replace("dhcp-option DNS ", ""))
    .filter((dnsServer) => dnsServer !== "")
    .map((dnsServer) => `nameserver ${dnsServer}`);

  if (!dnsServers) {
    throw new Error("No DNS servers found");
  }

  // Write the DNS servers to /etc/resolv.conf
  for (const dns of dnsServers) {
    await $`printf '%s\n%s\n' ${dns} "$(cat /etc/resolv.conf)" | sudo tee /etc/resolv.conf`;
  }

  return dnsServers;
}
await spinner("Patching resolv.conf manually...", manuallyPatchDnsServers);
lariskovski commented 3 months ago

Hello,

My team and I were having issues with openvpn not updating the resolv.conf. It connected just fine but could not resolve our internal names.

When trying to edit /etc/resolv.conf it'd throw "Device or resource busy".

We were able to solve it just by adding --dns to runArgs on devcontainer.json.

{
    "name": "OpenVPN Sample",
    "build": {
        "dockerfile": "Dockerfile",
    },

    // Allow the container to interact with host networking
       "runArgs": ["--dns=[your-internal-dns-server]", "--dns=[some-external-dns-server]",  "--cap-add=NET_ADMIN", "--cap-add=NET_RAW", "--device=/dev/net/tun"],

    // Save the contents of the OPENVPN_CONFIG secret to disk - it lands in .devcontainer/openvpn-tmp
    "initializeCommand": "bash .devcontainer/save-config.sh",

    // [Optional] Once the dev container is running, automatically start up the VPN client
    "postStartCommand": "bash .devcontainer/start-openvpn.sh",

    // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
    "remoteUser": "vscode"
}