cmc/cleberg.net

My personal web garden & blog.

clone: git clone https://gitbay.org/cmc/cleberg.net.git

main: content/blog/2023-07-12-wireguard-lan.org · raw

  1#+date:        [2023-07-12 Wed 00:00:00]
  2#+title:       Mullvad WireGuard with LAN Access
  3#+description: Modifying Mullvad WireGuard configs to allow LAN access while connected.
  4#+slug:        wireguard-lan
  5#+filetags:    :security:self-hosting:
  6
  7* Download Configuration Files from Mullvad
  8
  9To begin, you'll need
 10[[https://mullvad.net/account/wireguard-config][Wireguard configuration
 11files from Mullvad]]. You can choose any of the options as you download
 12them. For example, I enabled the kill switch, selected all countries,
 13and selected a few content filters.
 14
 15Once downloaded, unzip the files and move them to the Wireguard folder
 16on your system.
 17
 18#+begin_src sh
 19cd ~/Downloads
 20unzip mullvad_wireguard_linux_all_all.zip
 21doas mv *.conf /etc/wireguard/
 22#+end_src
 23
 24** Configuration File Layout
 25
 26The default configuration files will look something like this:
 27
 28#+begin_src conf
 29[Interface]
 30# Device: <redacted>
 31PrivateKey = <redacted>
 32Address = <redacted>
 33DNS = <redacted>
 34PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT && ip6tables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
 35PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT && ip6tables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
 36
 37[Peer]
 38PublicKey = <redacted>
 39AllowedIPs = <redacted>
 40Endpoint = <redacted>
 41#+end_src
 42
 43#+begin_quote
 44Note: If you didn't select the kill switch option, you won't see the
 45=PostUp= and =PreDown= lines. In this case, you'll need to modify the
 46script below to simply append those lines to the =[Interface]= block.
 47#+end_quote
 48
 49* Editing the Configuration Files
 50
 51Once you have the files, you'll need to edit them and replace the
 52=PostUp= and =PreDown= lines to enable LAN access.
 53
 54I recommend that you do this process as root, since you'll need to be
 55able to access files in =/etc/wireguard=, which are generally owned by
 56root. You can also try using =sudo= or =doas=, but I didn't test that
 57scenario so you may need to adjust, as necessary.
 58
 59#+begin_src sh
 60su
 61#+end_src
 62
 63Create the Python file that we'll be using to update the Wireguard
 64configuration files.
 65
 66#+begin_src sh
 67nano replace.py
 68#+end_src
 69
 70Within the Python file, copy and paste the logic below. This script will
 71open a directory, loop through every configuration file within the
 72directory, and replace the =PostUp= and =PreDown= lines with the new
 73LAN-enabled iptables commands.
 74
 75#+begin_quote
 76Note: If your LAN is on a subnet other than =192.168.1.0/24=, you'll
 77need to update the Python script below appropriately.
 78#+end_quote
 79
 80#+begin_src python
 81import os
 82import fileinput
 83
 84print("--- starting ---")
 85
 86dir = "/etc/wireguard/"
 87
 88for file in os.listdir(dir):
 89    print(os.path.join(dir, file))
 90    for line in fileinput.input(os.path.join(dir, file), inplace=True):
 91        if "PostUp" in line:
 92            print("PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL ! -d 192.168.1.0/24 -j REJECT && ip6tables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT")
 93        elif "PreDown" in line:
 94            print("PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL ! -d 192.168.1.0/24 -j REJECT && ip6tables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT")
 95        else:
 96            print(line, end="")
 97
 98print("--- done ---")
 99#+end_src
100
101Once you're done, save and close the file. You can now run the Python
102script and watch as each file is updated.
103
104#+begin_src sh
105python3 replace.py
106#+end_src
107
108To confirm it worked, you can =cat= one of the configuration files to
109inspect the new logic and connect to one to test it out.
110
111#+begin_src sh
112cat /etc/wireguard/us-chi-wg-001.conf
113#+end_src
114
115The configuration files should now look like this:
116
117#+begin_src conf
118[Interface]
119# Device: <redacted>
120PrivateKey = <redacted>
121Address = <redacted>
122DNS = <redacted>
123PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL ! -d 192.168.1.0/24 -j REJECT && ip6tables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
124PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL ! -d 192.168.1.0/24 -j REJECT && ip6tables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
125
126[Peer]
127PublicKey = <redacted>
128AllowedIPs = <redacted>
129Endpoint = <redacted>
130#+end_src
131
132If you connect to a Wireguard interface, such as =us-chi-wg-001=, you
133can test your SSH functionality and see that it works even while on the
134VPN.
135
136#+begin_src sh
137wg-quick up us-chi-wg-001
138ssh user@lan-host
139#+end_src
140
141To confirm your VPN connection, you can curl Mullvad's connection API:
142
143#+begin_src sh
144curl https://am.i.mullvad.net/connected
145# You are connected to Mullvad (server us-chi-wg-001). Your IP address is <redacted>
146#+end_src