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