{"id":1957,"date":"2021-12-21T12:35:02","date_gmt":"2021-12-21T16:35:02","guid":{"rendered":"https:\/\/lowtek.ca\/roo\/?p=1957"},"modified":"2022-01-06T13:51:21","modified_gmt":"2022-01-06T17:51:21","slug":"wireguard-self-hosted-vpn","status":"publish","type":"post","link":"https:\/\/lowtek.ca\/roo\/2021\/wireguard-self-hosted-vpn\/","title":{"rendered":"Wireguard &#8211; self hosted VPN"},"content":{"rendered":"<p><a href=\"https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2021\/12\/wireguard.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-1959\" src=\"https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2021\/12\/wireguard-500x115.png\" alt=\"\" width=\"500\" height=\"115\" srcset=\"https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2021\/12\/wireguard-500x115.png 500w, https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2021\/12\/wireguard-1024x236.png 1024w, https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2021\/12\/wireguard-768x177.png 768w, https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2021\/12\/wireguard-1536x354.png 1536w, https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2021\/12\/wireguard-1200x277.png 1200w, https:\/\/lowtek.ca\/roo\/wp-content\/uploads\/2021\/12\/wireguard.png 1934w\" sizes=\"auto, (max-width: 500px) 85vw, 500px\" \/><\/a><\/p>\n<p>After my recent adventures setting up <a href=\"https:\/\/lowtek.ca\/roo\/category\/iot\/\">IoT<\/a> devices with local only access, I now needed to sometimes be able to talk to those devices when I&#8217;m not home. There are plenty of solutions, including setting up SSH tunnels which I&#8217;ve done in the past. <a href=\"https:\/\/www.wireguard.com\/\">Wireguard<\/a> seems like a nice solution and it was high time I had <a href=\"https:\/\/en.wikipedia.org\/wiki\/Virtual_private_network\">VPN<\/a> access to my home network.<\/p>\n<p>The <a href=\"https:\/\/www.linuxserver.io\/\">linuxserver.io<\/a> folks have a nicely curated wireguard container with <a href=\"https:\/\/docs.linuxserver.io\/images\/docker-wireguard\">documentation<\/a>. There are also plenty of good <a href=\"https:\/\/www.the-digital-life.com\/wireguard-docker\/\">tutorials<\/a> on installing wireguard. You can even go deeper and <a href=\"https:\/\/blog.jessfraz.com\/post\/installing-and-using-wireguard\/\">build your own<\/a>, or explore alternatives.<\/p>\n<p>Here is a makefile &#8211; based on my <a href=\"https:\/\/lowtek.ca\/roo\/2021\/managing-docker-containers-with-makefiles\/\">template<\/a> for docker makefiles.<\/p>\n<pre class=\"lang:default decode:true \">#\r\n# wireguard - VPN\r\n# https:\/\/hub.docker.com\/r\/linuxserver\/wireguard\/\r\n#\r\n# Needs port forward in gateway\/router for 51820\/UDP\r\n#\r\nNAME = wireguard\r\nREPO = linuxserver\/wireguard\r\n#\r\nROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))\r\n\r\n# Create the container\r\nbuild:\r\n        docker create \\\r\n                --name=$(NAME) \\\r\n                --cap-add=NET_ADMIN \\\r\n                --cap-add=SYS_MODULE \\\r\n                -e PUID=1000 \\\r\n                -e PGID=1000 \\\r\n                -e TZ=America\/Toronto \\\r\n                -e SERVERURL=yourDomain.ca \\\r\n                -e PEERS=myPhone,myLaptop \\\r\n                -e PEERDNS=9.9.9.9 \\\r\n                -p 51820:51820\/udp \\\r\n                -v $(ROOT_DIR)\/config:\/config \\\r\n                -v \/lib\/modules:\/lib\/modules \\\r\n                --sysctl=\"net.ipv4.conf.all.src_valid_mark=1\" \\\r\n                --restart=unless-stopped \\\r\n                $(REPO)\r\n\r\n# Start the container\r\nstart:\r\n        docker start $(NAME)\r\n\r\n# Update the container\r\nupdate:\r\n        docker pull $(REPO)\r\n        - docker rm $(NAME)-old\r\n        docker rename $(NAME) $(NAME)-old\r\n        make build\r\n        docker stop $(NAME)-old\r\n        make start\r\n<\/pre>\n<p>Once you create this &#8211; go pull the .png files for the QR codes from the config directory. This will make it trivial to setup your phone.<\/p>\n<p>On mobile data &#8211; this just works. The local only <a href=\"https:\/\/tasmota.github.io\/docs\/\">Tasmota<\/a> devices I can now control when away from home and it&#8217;s super easy. What doesn&#8217;t work with this setup is accessing other docker containers on the same host as the wireguard container.<\/p>\n<p>I explored a few options to solve this, but it boils down to the problem of containers not easily being able to see each other. This bugs me, because while I can appreciate the security of containers being isolated from each other &#8211; if I expose a port on the host to a container &#8211; then other containers should be able to see that same port &#8211; but they can&#8217;t. This means that containers actually have less visibility into the host than an external machine &#8211; that seems wrong.<\/p>\n<p>You can solve the network visibility problem by giving the container a unique IP address. Here is a brief recap of creating a <a href=\"https:\/\/docs.docker.com\/network\/macvlan\/\">macvlan docker network<\/a> &#8211; details can be found in my <a href=\"https:\/\/lowtek.ca\/roo\/2020\/docker-and-macvlan-networking-ipv4\/\">previous post<\/a> on this topic<\/p>\n<pre class=\"lang:default decode:true \">$ docker network create -d macvlan -o parent=enp3s0 \\\r\n --subnet 192.168.1.0\/24 \\\r\n --gateway 192.168.1.1 \\\r\n --ip-range 192.168.1.64\/30 \\\r\n --aux-address 'host=192.168.1.67' \\\r\n myNewNet<\/pre>\n<p>Now from the makefile above, all we need to do is add <code>--network myNewNet<\/code> to the docker flags and update the container and we&#8217;re good to go.<\/p>\n<p>It&#8217;s interesting that the <code>docker ps<\/code> command seems to not show as much about the container when it is run in this mode (No port information &#8211; but yes, ports are exposed).<\/p>\n<pre class=\"lang:default decode:true \">CONTAINER ID   IMAGE                                       COMMAND                  CREATED          STATUS                 PORTS                                                                                                                                                                                                                                                                            NAMES\r\n434d19122529   linuxserver\/wireguard                       \"\/init\"                  36 seconds ago   Up 35 seconds                                                                                                                                                                                                                                                                                           wireguard<\/pre>\n<p>One thing to keep in mind, if you first setup the container just on the docker host without macvlan you may need to adjust your port mapping to account for the new IP.<\/p>\n<p>If I want the docker host machine to be able to see this container on the new IP we will need to use that <code>--aux-address<\/code> to build a network path. This is optional, but useful so it&#8217;s worth doing.<\/p>\n<p>The version of Ubuntu I&#8217;m using doesn&#8217;t ship with rc.local enabled. I started down the path of <a href=\"https:\/\/www.lukmanlab.com\/how-to-activing-rc-local-on-ubuntu-server-18-04\/\">enabling rc.local<\/a>, but the further I got the more it seemed this was the wrong answer. This <a href=\"https:\/\/www.linuxbabe.com\/linux-server\/how-to-enable-etcrc-local-with-systemd\">post talking about rc.local<\/a>, pointed me at cron&#8217;s ability to execute on commands on reboot. The <a href=\"https:\/\/www.configserverfirewall.com\/linux-tutorials\/linux-run-cron-job-reboot\/\">cron @reboot<\/a> capability seems like the easy path here, the other choice being to create a systemd service which is effectively what the rc.local solution is.<\/p>\n<p>Let&#8217;s create a script in <code>\/usr\/local\/bin\/macvlansetup<\/code>, making sure it&#8217;s executable.<\/p>\n<pre class=\"lang:default decode:true \">$ cat \/usr\/local\/bin\/macvlansetup \r\n#!\/bin\/bash\r\n# Enable macvlan visibility for docker host\r\n#\r\nip link add myNewNet-shim link enp3s0 type macvlan mode bridge\r\nip addr add 192.168.1.67\/32 dev myNewNet-shim\r\nip link set myNewNet-shim up\r\nip route add 192.168.1.64\/30 dev myNewNet-shim\r\n \r\n<\/pre>\n<p>Then we&#8217;ll edit root&#8217;s crontab to call this on reboot<\/p>\n<pre class=\"lang:default decode:true \">$ sudo crontab -e<\/pre>\n<p>Adding the new job<\/p>\n<pre class=\"lang:default decode:true \"># One shot on reboots\r\n@reboot     \/usr\/local\/bin\/macvlansetup\r\n<\/pre>\n<p>Now we&#8217;re set. The wireguard container has a unique IP address and no visibility problems to any of my other containers on the same host. The IoT devices can also be seen just fine when I am remote and enable the VPN. The one trade-off is a slightly more complicated networking setup.<\/p>\n<p>With the default wireguard settings, this acts like a full tunnel VPN &#8211; meaning all of the network traffic runs over the tunnel. This is useful as a security measure if I&#8217;m on an untrusted wifi network &#8211; all the traffic will flow securely from my device to my home network then back out again to the internet. In my case with my pi-hole configured as the DNS server, I get ad-blocking over the VPN.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After my recent adventures setting up IoT devices with local only access, I now needed to sometimes be able to talk to those devices when I&#8217;m not home. There are plenty of solutions, including setting up SSH tunnels which I&#8217;ve done in the past. Wireguard seems like a nice solution and it was high time &hellip; <a href=\"https:\/\/lowtek.ca\/roo\/2021\/wireguard-self-hosted-vpn\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Wireguard &#8211; self hosted VPN&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,12,21],"tags":[],"class_list":["post-1957","post","type-post","status-publish","format-standard","hentry","category-computing","category-how-to","category-network"],"_links":{"self":[{"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/posts\/1957","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/comments?post=1957"}],"version-history":[{"count":6,"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/posts\/1957\/revisions"}],"predecessor-version":[{"id":1987,"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/posts\/1957\/revisions\/1987"}],"wp:attachment":[{"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/media?parent=1957"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/categories?post=1957"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lowtek.ca\/roo\/wp-json\/wp\/v2\/tags?post=1957"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}