pirate / wireguard-docs

📖 Unofficial WireGuard Documentation: Setup, Usage, Configuration, and full example setups for VPNs supporting both servers & roaming clients.
https://docs.sweeting.me/s/wireguard
MIT License
4.45k stars 309 forks source link

Selective Application Tunneling #30

Open jonpolak opened 4 years ago

jonpolak commented 4 years ago

Can you cover the usecase where wireguard is ran out of a separate network namespace wherein certain applications are launched -- and only the traffic of those launched from that network namespace is tunneled? I've been doing this on OpenVpn for a years but as Ubuntu's adoption of systemd-resolved I've had DNS leaks.

Would love if there was a wireguard native way to tunnel certain applications rather than tunnel traffic based on range of destination IP addresses.

Ps. thanks for the HN post.

pirate commented 4 years ago

By certain applications do you mean certain ports, or unix sockets, or something else?

I believe the wireguard userspace implementations let you do anyting you want with the wireguard connection, so you could conceivably bind an application to a wg connection with a small userspace program without needing to use a tun/tap interface + assign it a real port. It could work something like a CloudFlare's Argo tunnels https://www.cloudflare.com/en-ca/products/argo-tunnel/

https://github.com/WireGuard/wireguard-go/blob/master/device/receive.go#L93

jonpolak commented 4 years ago

The use case would be - I have say firefox going through the tunnel while chrome is not tunneled. shell utilities like ping , dig and (very importantly) systemd-resolved need to point them either to the tunnel or to the untunneled interface. This is poorly documented. For openvpn I've used this script to create a new network namespace and launch applications that I want tunneled from a shell that is set to that network namespace. The challenge becomes the dns leaks when using systemd-resolved

alextrekov3307 commented 4 years ago

There is: https://www.wireguard.com/netns/ The second use case where the physical interfaces get ejected from the default namespace is most suitable for those who don't practice more paranoid isolation or use multiple tunnels for multiple applications.

And for resolv: http://man7.org/linux/man-pages/man8/ip-netns.8.html

There is also firejail where you can specify both netns and dns.

jonpolak commented 4 years ago

@pirate Was trying to get to is @alextrekov3307 suggestion of using the netns. Creating created the wg0 device in the init namespace and then move it to a new namespace temp1. Then setup that interface within temp1. One caveat is that you need to modify the conf files shipped by VPN providers that expect you to be using wg-quick. Among the incompatible commands are Address = 192.168.x.x/32 and DNS = xxx.xxx.xxx.xxx. So you need to comment them out. You add the IP addr manually with ip -n temp1 addr add 192.168.x.x dev wg0 where the 192 address is whatever was in the conf file meant for wg-quick. Haven't figured out is how to route the dns over the tunnel. Both on 19.10 and 20.04 machines dns leaking

Edit Setting up /etc/temp1/resolv.conf with the desired DNS does capture the dns requests from shell apps like dig, ping, curl etc but does not capture the dns requests of browsers started from that network namespace. www.dnsleaktest reports IP address as the tunnel exit location, but the DNS server is still that of the un-tunneled traffic, which is the closest 1.1.1.1 server to the real physical location.

EDIT 2 There's been a lot of discussion about this in nixOS -- here's a blog post describing it

pirate commented 4 years ago

Figured out how to do this with docker: https://github.com/pirate/wireguard-docs#containerization

If you can get your application running inside a docker container, then you can route all of its traffic through wireguard like this:

docker-compose.yml:

version: '3'

services:
  wireguard:
    image: linuxserver/wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    volumes:
      - /lib/modules:/lib/modules
      - ./wg0.conf:/config/wg0.conf:ro

  vpn_test:
    image: curlimages/curl
    entrypoint: curl -s http://whatismyip.akamai.com/
    network_mode: 'service:wireguard'

wg0.conf:

[Interface]
# Name = client1.wg.example.com
Address = 10.17.17.2/32
PrivateKey = abc...

[Peer]
# Name = relay1.wg.example.com
Endpoint = relay1.wg.example.com:51820
PublicKey = abc...
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 21
docker-compose up
docker-compose run vpn_test
# should output public IP of VPN relay server (instead of container host)
ghost commented 4 years ago

www.dnsleaktest reports IP address as the tunnel exit location, but the DNS server is still that of the un-tunneled traffic, which is the closest 1.1.1.1 server to the real physical location.

That should not happen if set up properly. Try to delete all cache and browser configuration or sandbox it in its own rootfs.

Network namespaces produce isolated virtualized networking stacks, not even rules carry over (have to execute iptaables/etc in each namespace).