forked from faicker/wg-config
-
Notifications
You must be signed in to change notification settings - Fork 15
/
user.sh
executable file
·238 lines (205 loc) · 5.65 KB
/
user.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
#!/usr/bin/env bash
cd `dirname ${BASH_SOURCE[0]}`
. wg.def
CLIENT_TPL_FILE=client.conf.tpl
SERVER_TPL_FILE=server.conf.tpl
SAVED_FILE=.saved
AVAILABLE_IP_FILE=.available_ip
WG_TMP_CONF_FILE=.$_INTERFACE.conf
WG_CONF_FILE="/etc/wireguard/$_INTERFACE.conf"
dec2ip() {
local delim=''
local ip dec=$@
for e in {3..0}
do
((octet = dec / (256 ** e) ))
((dec -= octet * 256 ** e))
ip+=$delim$octet
delim=.
done
printf '%s\n' "$ip"
}
generate_cidr_ip_file_if() {
local cidr=${_VPN_NET}
local ip mask a b c d
IFS=$'/' read ip mask <<< "$cidr"
IFS=. read -r a b c d <<< "$ip"
local beg=$((a * 256 ** 3 + b * 256 ** 2 + c * 256 + d))
local end=$(( beg+(1<<(32-mask))-1 ))
ip=$(dec2ip $((beg+1)))
_SERVER_IP="$ip/$mask"
if [[ -f $AVAILABLE_IP_FILE ]]; then
return
fi
> $AVAILABLE_IP_FILE
local i=$((beg+2))
while [[ $i -lt $end ]]; do
ip=$(dec2ip $i)
echo "$ip/$mask" >> $AVAILABLE_IP_FILE
i=$((i+1))
done
}
get_vpn_ip() {
local ip=$(head -1 $AVAILABLE_IP_FILE)
if [[ $ip ]]; then
local mat="${ip/\//\\\/}"
sed -i "/^$mat$/d" $AVAILABLE_IP_FILE
fi
echo "$ip"
}
add_user() {
local user=$1
local template_file=${CLIENT_TPL_FILE}
local interface=${_INTERFACE}
local userdir="users/$user"
if [ ! -d "$userdir" ]
then
mkdir -p "$userdir"
wg genkey | tee $userdir/privatekey | wg pubkey > $userdir/publickey
# client config file
_PRIVATE_KEY=`cat $userdir/privatekey`
_VPN_IP=$(get_vpn_ip)
if [[ -z $_VPN_IP ]]; then
echo "no available ip"
exit 1
fi
eval "echo \"$(cat "${template_file}")\"" > $userdir/client.conf
eval "echo \"$(cat "${template_file}")\"" > $userdir/client.all.conf
sed -r "s/AllowedIPs.*/AllowedIPs = 0.0.0.0\/0/g" -i $userdir/client.all.conf
qrencode -t ansiutf8 < $userdir/client.conf
qrencode -o $userdir/$user.png < $userdir/client.conf
qrencode -o $userdir/$user.all.png < $userdir/client.all.conf
# change wg config
local ip=${_VPN_IP%/*}/32
local public_key=`cat $userdir/publickey`
wg set $interface peer $public_key allowed-ips $ip
if [[ $? -ne 0 ]]; then
echo "wg set failed"
rm -rf $user
exit 1
fi
echo "$user $_VPN_IP $public_key" >> ${SAVED_FILE}
else
echo "$user already exists." 1>&2
echo
read -r -p "Overwrite current user? [y/N]" response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]
then
del_user $user
add_user $user
else
echo "Exiting."
fi
fi
}
del_user() {
local user=$1
local userdir="users/$user"
local ip key
local interface=${_INTERFACE}
read ip key <<<"$(awk "/^$user /{print \$2, \$3}" ${SAVED_FILE})"
if [[ -n "$key" ]]; then
wg set $interface peer $key remove
if [[ $? -ne 0 ]]; then
echo "wg set failed"
exit 1
fi
fi
sed -i "/^$user /d" ${SAVED_FILE}
if [[ -n "$ip" ]]; then
echo "$ip" >> ${AVAILABLE_IP_FILE}
fi
rm -rf $userdir
sort ${AVAILABLE_IP_FILE} --version-sort -o ${AVAILABLE_IP_FILE}
}
generate_and_install_server_config_file() {
local template_file=${SERVER_TPL_FILE}
local ip
# server config file
eval "echo \"$(cat "${template_file}")\"" > $WG_TMP_CONF_FILE
while read user vpn_ip public_key; do
ip=${vpn_ip%/*}/32
cat >> $WG_TMP_CONF_FILE <<EOF
[Peer]
PublicKey = $public_key
AllowedIPs = $ip
EOF
done < ${SAVED_FILE}
\cp -f $WG_TMP_CONF_FILE $WG_CONF_FILE
}
do_clear() {
local interface=$_INTERFACE
wg-quick down $interface
> $WG_CONF_FILE
rm -f ${SAVED_FILE} ${AVAILABLE_IP_FILE}
}
do_user() {
generate_cidr_ip_file_if
if [[ $action == "-a" ]]; then
if [[ -d $user ]]; then
echo "$user exist"
exit 1
fi
add_user $user
elif [[ $action == "-d" ]]; then
del_user $user
fi
generate_and_install_server_config_file
}
view_user() {
local user=$1
local userdir="users/$user"
echo "Client configuration ($(cat $userdir/client.conf | grep AllowedIPs))"
echo "client.conf:"
echo
cat $userdir/client.conf
echo
qrencode -t ansiutf8 < $userdir/client.conf
echo
echo
echo "----------------------------------------------------------------"
echo "----------------------------------------------------------------"
echo "----------------------------------------------------------------"
echo
echo
echo "Client configuration (AllowedIPs: 0.0.0.0/0)"
echo "client.all.conf:"
echo
cat $userdir/client.all.conf
echo
qrencode -t ansiutf8 < $userdir/client.all.conf
}
usage() {
echo "usage: $0 [-a|-d|-c|-v] [username]"
echo
echo " -a [username] add user"
echo " -d [username] delete user"
echo " -c delete all users and configuration"
echo " -v [username] view generated QR codes for user"
echo
}
# main
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi
action=$1
user=$2
if [[ $action == "-c" ]]; then
read -r -p "Deleting all users and config. Are you sure? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]
then
do_clear
else
echo "Exiting."
fi
elif [[ $action == "-v" ]]; then
view_user $user
elif [[ $action == "-g" ]]; then
generate_cidr_ip_file_if
elif [[ ! -z "$user" && ( $action == "-a" || $action == "-d" ) ]]; then
do_user
else
usage
exit 1
fi