-
Notifications
You must be signed in to change notification settings - Fork 0
/
wireguard-setup.sh
285 lines (247 loc) · 10.3 KB
/
wireguard-setup.sh
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#!/usr/bin/env bash
# github.com/OlJohnny | 2021
set -e # exit immediately if a command exits with a non-zero status
set -u # treat unset variables as an error when substituting
set -o pipefail # return value of pipeline is status of last command to exit with a non-zero status
# set -o xtrace # uncomment the previous statement for debugging
# environment
SCRIPT_FULL=$(realpath -s $0) # stackoverflow.com/a/11114547
SCRIPT_PATH=$(dirname $(realpath -s $0))
SCRIPT_NAME=$(basename $(realpath -s $0))
# text colors
text_info="\e[96m"
text_yes="\e[92m"
text_no="\e[91m"
text_reset="\e[0m"
read_question=$'\e[93m'
read_reset=$'\e[0m'
# check for root privileges
if [[ "${EUID}" -ne 0 ]]
then
echo -e ""${text_no}"Please run as root."${text_reset}""
echo -e "Exiting..."
exit 1
fi
# check if instance of script is already running, stackoverflow.com/a/45429634
if ps ax | grep ${SCRIPT_NAME} | grep --invert-match $$ | grep bash | grep --invert-match grep > /dev/null
then
echo -e ""${text_no}"Another instance of this script is already running."${text_reset}""
echo -e "Exiting..."
exit 1
fi
## global variables
peer_name="<PEER NAME DEFAULT>"
peer_ip="<PEER IP DEFAULT>"
server_subnet="<SERVER SUBNET DEFAULT>"
server_ip="<SERVER IP DEFAULT>"
server_port="<SERVER PORT DEFAULT>"
server_interface="<SERVER INTERFACE DEFAULT>"
allowed_ips="<ALLOWED IPS DEFAULT>"
# loop question: restart wireguard
_var1func(){
read -ep ""${read_question}"Do you want to restart wireguard? This will temporarily disconnect all wireguard connections (y|n): "${read_reset}"" var1
if [[ "${var1}" == "y" ]]
then
echo -e ""${text_yes}"Restarting wireguard..."${text_reset}""
$(wg-quick down "${server_interface}" || :)
wg-quick up "${server_interface}"
elif [[ "${var1}" == "n" ]]
then
echo -e ""${text_no}"Not restarting wireguard"${text_reset}""
else
_var1func
fi
}
# loop question: generate server keys
_var2func(){
read -ep ""${read_question}"Couldn't find any server keys. Do you want to generate new ones? (They will NOT get updated in any pre existing config files) (y|n): "${read_reset}"" var2
if [[ "${var2}" == "y" ]]
then
echo -e ""${text_yes}"Generating server keys..."${text_reset}""
touch server_"${server_interface}"_private.key
touch server_"${server_interface}"_public.key
touch server_"${server_interface}"_preshared.key
chown root:root -f *.key
chmod 770 -f *.key
# generate peer keys
wg genkey | tee server_"${server_interface}"_private.key | wg pubkey > server_"${server_interface}"_public.key
wg genpsk > server_"${server_interface}"_preshared.key
elif [[ "${var2}" == "n" ]]
then
echo -e ""${text_no}"Not generating server keys.\nAs we can't find any server keys, exiting ..."${text_reset}""
else
_var2func
fi
}
# loop question: delete local copies of peer keys
_var3func(){
read -ep ""${read_question}"Do you want to delete local copies of peer key files? They are no longer needed if you have copied the peer config from above. (y|n): "${read_reset}"" var3
if [[ "${var3}" == "y" ]]
then
echo -e ""${text_yes}"Deleting local copies of peer key files..."${text_reset}""
rm peer_"${server_interface}"_"${peer_name}"_private.key
rm peer_"${server_interface}"_"${peer_name}"_public.key
rm peer_"${server_interface}"_"${peer_name}"_preshared.key
elif [[ "${var3}" == "n" ]]
then
echo -e ""${text_no}"Not deleting local copies of peer key files."${text_reset}""
else
_var3func
fi
}
# loop question: AllowedIPs
_var4func(){
echo -e ""${read_question}"Which (peer) IP range should be routed through the wireguard tunnel:\n 0: 0.0.0.0/0 (Route all traffic through wireguard)\n 1: "${server_subnet}" (Route local traffic through wireguard)\n c: Enter a custom subnet"${read_reset}""
read -ep "" var4
if [[ "${var4}" == "0" ]]
then
echo -e ""${text_yes}"Setting 0.0.0.0/0 as AllowedIPs..."${text_reset}""
allowed_ips="0.0.0.0/0"
elif [[ "${var4}" == "1" ]]
then
echo -e ""${text_yes}"Setting "${server_subnet}" as AllowedIPs..."${text_reset}""
allowed_ips="${server_subnet}"
elif [[ "${var4}" == "c" ]]
then
read -p ""${read_question}"Enter IP range for wireguard routing (e.g. 192.168.50.0/24): "${read_reset}"" allowed_ips
else
_var4func
fi
}
# loop question: build initial server config
_var5func(){
read -ep ""${read_question}"Couldn't find a server config for interface "${server_interface}". Do you want to generate a new config at '/etc/wireguard/"${server_interface}".conf'? (y|n): "${read_reset}"" var5
if [[ "${var5}" == "y" ]]
then
ip -br a
echo ""
read -p ""${read_question}"Enter the network interface over which the wireguard server should connect to the internet (e.g. eth0): "${read_reset}"" server5_interface
read -p ""${read_question}"Enter the network address & range the server should be reachable at in the wireguard network (e.g. 192.168.11.1/24): "${read_reset}"" server5_address
echo -e ""${text_info}"Generating new server config..."${text_reset}""
echo "[Interface]
Address = "${server5_address}"
SaveConfig = false
PostUp = iptables -A FORWARD -i "${server_interface}" -j ACCEPT; iptables -A FORWARD -o "${server_interface}" -j ACCEPT; iptables -t nat -A POSTROUTING -o "${server5_interface}" -j MASQUERADE
PostDown = iptables -D FORWARD -i "${server_interface}" -j ACCEPT; iptables -D FORWARD -o "${server_interface}" -j ACCEPT; iptables -t nat -D POSTROUTING -o "${server5_interface}" -j MASQUERADE
ListenPort = "${server_port}"
PrivateKey = "$(cat server_"${server_interface}"_private.key)"" > /etc/wireguard/"${server_interface}".conf
elif [[ "${var5}" == "n" ]]
then
echo -e ""${text_no}"Not generating a new server config."${text_reset}""
else
_var5func
fi
}
# loop question: enable wireguard tunnel at startup
_var6func(){
read -ep ""${read_question}"Do you want to enable the wireguard tunnel "${server_interface}" at startup? (y|n): "${read_reset}"" var6
if [[ "${var6}" == "y" ]]
then
echo -e ""${text_yes}"Enabling "${server_interface}" at startup..."${text_reset}""
systemctl enable wg-quick@"${server_interface}"
elif [[ "${var6}" == "n" ]]
then
echo -e ""${text_no}"Not enabling "${server_interface}" at startup."${text_reset}""
else
_var6func
fi
}
# TODO: check if system is running on some kind of debian
# check if wireguard-tools is installed
if [[ $(dpkg-query --show --showformat='${Status}' wireguard-tools 2>/dev/null | grep --count "ok installed") == 0 ]];
then
echo -e ""${text_no}"Package 'wireguard-tools' needs to be installed"${text_reset}""
exit
fi
# get server information
# ask which wireguard config to use
path_to_use="/etc/wireguard"
no_of_files=$(ls -1 "${path_to_use}" | grep -E \.conf$ | wc -l)
echo -en "${text_info}"
ls -1 "${path_to_use}" | grep -E \.conf$ | awk '{print NR ": " $s}'
echo -en "${text_reset}"
# loop question
_var112func(){
read -i "1" -ep ""${read_question}"Which config to use. Enter the line number: "${read_reset}"" var112
if [[ -n "${var112}" ]]; then
server_interface=$(ls -1 "${path_to_use}" | grep -E \.conf$ | sed "${var112}q;d" | sed 's|\.conf||g' )
else
_var112func
fi
}
_var112func
server_port_d=$(grep "ListenPort" /etc/wireguard/"${server_interface}".conf | awk '{print $3}')
read -ep ""${read_question}"Enter Server IP/Domain: "${read_reset}"" server_ip
read -i "${server_port_d}" -ep ""${read_question}"Enter Server Wireguard Port: "${read_reset}"" server_port
read -ep ""${read_question}"Enter Server Wireguard Subnet (as CIDR, eg. 192.168.11.0/24): "${read_reset}"" server_subnet
# get peer information
echo ""
read -ep ""${read_question}"Enter Peer Name (for key naming, no spaces & '/'): "${read_reset}"" peer_name
echo ""
echo -en "${text_info}"
grep "AllowedIPs" /etc/wireguard/"${server_interface}".conf | grep -oE "[0-9]{,3}\.[0-9]{,3}\.[0-9]{,3}\.[0-9]{,3}" | sort -t. -n +3.0
echo -en "${text_reset}"
read -ep ""${read_question}"Enter Peer IP (local Wireguard network, eg 192.168.11.5): "${read_reset}"" peer_ip
# if wireguard folder doesnt exist, create it
if [[ ! -d ""${SCRIPT_PATH}"/wireguard-keys" ]]
then
mkdir "${SCRIPT_PATH}"/wireguard-keys
fi
cd "${SCRIPT_PATH}"/wireguard-keys
# check for existing server keys
if [[ ! -f ""${SCRIPT_PATH}"/wireguard-keys/server_"${server_interface}"_public.key" ]]; then
echo ""
_var2func
fi
# check for existing wireguard config, if not ask to generate one and ask to enable wireguard tunnel at startup
if [[ ! -f "/etc/wireguard/"${server_interface}".conf" ]]
then
echo ""
_var5func
echo ""
_var6func
fi
# generate peer keys
echo -e "\n"${text_info}"Generating Peer keys in '"${SCRIPT_PATH}"/wireguard-keys'..."${text_reset}""
# touch key files and update permissions to prevent a warning message by wireguard
touch peer_"${server_interface}"_"${peer_name}"_private.key
touch peer_"${server_interface}"_"${peer_name}"_public.key
touch peer_"${server_interface}"_"${peer_name}"_preshared.key
chown root:root -f *.key
chmod 770 -f *.key
# generate peer keys
wg genkey | tee peer_"${server_interface}"_"${peer_name}"_private.key | wg pubkey > peer_"${server_interface}"_"${peer_name}"_public.key
wg genpsk > peer_"${server_interface}"_"${peer_name}"_preshared.key
# append server config
echo -e "\n"${text_info}"Adding new peer to server config..."${text_reset}""
echo "
# peer_"${peer_name}":
[Peer]
PublicKey = "$(cat peer_"${server_interface}"_"${peer_name}"_public.key)"
PresharedKey = "$(cat peer_"${server_interface}"_"${peer_name}"_preshared.key)"
AllowedIPs = "${peer_ip}"/32" >> /etc/wireguard/"${server_interface}".conf
chmod 770 /etc/wireguard/"${server_interface}".conf
# ask which 'AllowedIPs' to use
echo ""
_var4func
# ask to restart wireguard
echo ""
_var1func
# print peer config
echo -e "\n"${text_info}"Use the following configuration for your new peer:"${text_reset}""
echo "[Interface]
Address = "${peer_ip}"/24
Privatekey = "$(cat peer_"${server_interface}"_"${peer_name}"_private.key)"
MTU = 1384
[Peer]
PublicKey = "$(cat server_"${server_interface}"_public.key)"
PresharedKey = "$(cat peer_"${server_interface}"_"${peer_name}"_preshared.key)"
AllowedIPs = "${allowed_ips}"
PersistentKeepalive = 30
Endpoint = "${server_ip}":"${server_port}""
echo -e "\n"${text_info}"Tip: You can provide this config as a file to clients by pasting it into '"${peer_name}".conf'"${text_reset}""
# ask to delete local copies of peer keys
echo ""
_var3func
# exiting
echo -e "\n"${text_info}"Finished\nExiting..."${text_reset}""