@@ -89,13 +89,59 @@ check_container() {
8989 fi
9090}
9191
92+ set_client_name () {
93+ # Allow a limited set of characters to avoid conflicts
94+ # Limit to 15 characters for compatibility with Linux clients
95+ client=$( sed ' s/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< " $unsanitized_client" | cut -c-15)
96+ }
97+
9298parse_args () {
9399 while [ " $# " -gt 0 ]; do
94100 case $1 in
95101 --auto)
96102 auto=1
97103 shift
98104 ;;
105+ --addclient)
106+ add_client=1
107+ unsanitized_client=" $2 "
108+ shift
109+ shift
110+ ;;
111+ --listclients)
112+ list_clients=1
113+ shift
114+ ;;
115+ --removeclient)
116+ remove_client=1
117+ unsanitized_client=" $2 "
118+ shift
119+ shift
120+ ;;
121+ --showclientqr)
122+ show_client_qr=1
123+ unsanitized_client=" $2 "
124+ shift
125+ shift
126+ ;;
127+ --uninstall)
128+ remove_wg=1
129+ shift
130+ ;;
131+ --dns1)
132+ dns1=" $2 "
133+ shift
134+ shift
135+ ;;
136+ --dns2)
137+ dns2=" $2 "
138+ shift
139+ shift
140+ ;;
141+ -y|--yes)
142+ assume_yes=1
143+ shift
144+ ;;
99145 -h|--help)
100146 show_usage
101147 ;;
@@ -106,6 +152,57 @@ parse_args() {
106152 done
107153}
108154
155+ check_args () {
156+ if [ " $auto " = 1 ] && [ -e " $WG_CONF " ]; then
157+ echo " Error: Invalid parameter '--auto'. WireGuard is already set up on this server." >&2
158+ echo " To manage WireGuard clients, re-run this script without '--auto'." >&2
159+ exit 1
160+ fi
161+ if [ " $(( add_client + list_clients + remove_client + show_client_qr)) " -gt 1 ]; then
162+ show_usage " Invalid parameters. Specify only one of '--addclient', '--listclients', '--removeclient' or '--showclientqr'."
163+ fi
164+ if [ " $remove_wg " = 1 ]; then
165+ if [ " $(( add_client + list_clients + remove_client + show_client_qr + auto)) " -gt 0 ]; then
166+ show_usage " Invalid parameters. '--uninstall' cannot be specified with other parameters."
167+ fi
168+ fi
169+ if [ ! -e " $WG_CONF " ]; then
170+ [ " $add_client " = 1 ] && exiterr " You must first set up WireGuard before adding a client."
171+ [ " $list_clients " = 1 ] && exiterr " You must first set up WireGuard before listing clients."
172+ [ " $remove_client " = 1 ] && exiterr " You must first set up WireGuard before removing a client."
173+ [ " $show_client_qr " = 1 ] && exiterr " You must first set up WireGuard before showing QR code for a client."
174+ [ " $remove_wg " = 1 ] && exiterr " Cannot remove WireGuard because it has not been set up on this server."
175+ fi
176+ if [ " $add_client " = 1 ]; then
177+ set_client_name
178+ if [ -z " $client " ]; then
179+ exiterr " Invalid client name. Use one word only, no special characters except '-' and '_'."
180+ elif grep -q " ^# BEGIN_PEER $client $" " $WG_CONF " ; then
181+ exiterr " $client : invalid name. Client already exists."
182+ fi
183+ if { [ -n " $dns1 " ] && ! check_ip " $dns1 " ; } \
184+ || { [ -n " $dns2 " ] && ! check_ip " $dns2 " ; }; then
185+ exiterr " Invalid DNS server(s)."
186+ fi
187+ if [ -z " $dns1 " ] && [ -n " $dns2 " ]; then
188+ exiterr " Invalid DNS server. --dns2 cannot be specified without --dns1."
189+ fi
190+ if [ -n " $dns1 " ] && [ -n " $dns2 " ]; then
191+ dns=" $dns1 , $dns2 "
192+ elif [ -n " $dns1 " ]; then
193+ dns=" $dns1 "
194+ else
195+ dns=" 8.8.8.8, 8.8.4.4"
196+ fi
197+ fi
198+ if [ " $remove_client " = 1 ] || [ " $show_client_qr " = 1 ]; then
199+ set_client_name
200+ if [ -z " $client " ] || ! grep -q " ^# BEGIN_PEER $client $" " $WG_CONF " ; then
201+ exiterr " Invalid client name, or client does not exist."
202+ fi
203+ fi
204+ }
205+
109206check_nftables () {
110207 if [ " $os " = " centos" ]; then
111208 if grep -qs " hwdsl2 VPN script" /etc/sysconfig/nftables.conf \
@@ -171,6 +268,7 @@ cat <<'EOF'
171268
172269Welcome to this WireGuard server installer!
173270GitHub: https://github.com/hwdsl2/wireguard-install
271+
174272EOF
175273}
176274
@@ -193,8 +291,16 @@ cat 1>&2 <<EOF
193291Usage: bash $0 [options]
194292
195293Options:
196- --auto auto install WireGuard using default options
197- -h, --help show this help message and exit
294+ --auto auto install WireGuard using default options
295+ --addclient [client name] add a new client
296+ --dns1 [DNS server IP] primary DNS server for new client (optional, defaults to Google Public DNS)
297+ --dns2 [DNS server IP] secondary DNS server for new client (optional)
298+ --listclients list the names of existing clients
299+ --removeclient [client name] remove an existing client
300+ --showclientqr [client name] show QR code for an existing client
301+ --uninstall remove WireGuard and delete all configuration
302+ -y, --yes assume "yes" as answer to prompts when removing a client or removing WireGuard
303+ -h, --help show this help message and exit
198304
199305To customize install options, run this script without arguments.
200306EOF
204310show_welcome () {
205311 if [ " $auto " = 0 ]; then
206312 show_header2
207- echo
208313 echo ' I need to ask you a few questions before starting setup.'
209314 echo ' You can use the default options and just press enter if you are OK with them.'
210315 else
@@ -368,12 +473,6 @@ enter_custom_dns() {
368473 done
369474}
370475
371- set_client_name () {
372- # Allow a limited set of characters to avoid conflicts
373- # Limit to 15 characters for compatibility with Linux clients
374- client=$( sed ' s/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< " $unsanitized_client" | cut -c-15)
375- }
376-
377476enter_first_client_name () {
378477 if [ " $auto " = 0 ]; then
379478 echo
@@ -720,7 +819,7 @@ select_client_ip() {
720819new_client () {
721820 select_client_ip
722821 specify_ip=n
723- if [ " $1 " = " add_client" ]; then
822+ if [ " $1 " = " add_client" ] && [ " $add_client " = 0 ] ; then
724823 echo
725824 read -rp " Do you want to specify an internal IP address for the new client? [y/N]: " specify_ip
726825 until [[ " $specify_ip " =~ ^[yYnN]* $ ]]; do
@@ -887,7 +986,11 @@ enter_client_name() {
887986 [ -z " $unsanitized_client " ] && abort_and_exit
888987 set_client_name
889988 while [[ -z " $client " ]] || grep -q " ^# BEGIN_PEER $client $" " $WG_CONF " ; do
890- echo " $client : invalid name."
989+ if [ -z " $client " ]; then
990+ echo " Invalid client name. Use one word only, no special characters except '-' and '_'."
991+ else
992+ echo " $client : invalid name. Client already exists."
993+ fi
891994 read -rp " Name: " unsanitized_client
892995 [ -z " $unsanitized_client " ] && abort_and_exit
893996 set_client_name
@@ -914,7 +1017,7 @@ check_clients() {
9141017 if [[ " $num_of_clients " = 0 ]]; then
9151018 echo
9161019 echo " There are no existing clients!"
917- exit
1020+ exit 1
9181021 fi
9191022}
9201023
@@ -941,12 +1044,16 @@ select_client_to() {
9411044}
9421045
9431046confirm_remove_client () {
944- echo
945- read -rp " Confirm $client removal? [y/N]: " remove
946- until [[ " $remove " =~ ^[yYnN]* $ ]]; do
947- echo " $remove : invalid selection."
1047+ if [ " $assume_yes " != 1 ]; then
1048+ echo
9481049 read -rp " Confirm $client removal? [y/N]: " remove
949- done
1050+ until [[ " $remove " =~ ^[yYnN]* $ ]]; do
1051+ echo " $remove : invalid selection."
1052+ read -rp " Confirm $client removal? [y/N]: " remove
1053+ done
1054+ else
1055+ remove=y
1056+ fi
9501057}
9511058
9521059remove_client_conf () {
@@ -963,7 +1070,7 @@ print_remove_client() {
9631070 echo " Removing $client ..."
9641071}
9651072
966- remove_client () {
1073+ remove_client_wg () {
9671074 # The following is the right way to avoid disrupting other active connections:
9681075 # Remove from the live interface
9691076 wg set wg0 peer " $( sed -n " /^# BEGIN_PEER $client $/,\$ p" " $WG_CONF " | grep -m 1 PublicKey | cut -d " " -f 3) " remove
@@ -997,12 +1104,16 @@ print_client_conf() {
9971104}
9981105
9991106confirm_remove_wg () {
1000- echo
1001- read -rp " Confirm WireGuard removal? [y/N]: " remove
1002- until [[ " $remove " =~ ^[yYnN]* $ ]]; do
1003- echo " $remove : invalid selection."
1107+ if [ " $assume_yes " != 1 ]; then
1108+ echo
10041109 read -rp " Confirm WireGuard removal? [y/N]: " remove
1005- done
1110+ until [[ " $remove " =~ ^[yYnN]* $ ]]; do
1111+ echo " $remove : invalid selection."
1112+ read -rp " Confirm WireGuard removal? [y/N]: " remove
1113+ done
1114+ else
1115+ remove=y
1116+ fi
10061117}
10071118
10081119print_remove_wg () {
@@ -1054,9 +1165,82 @@ check_container
10541165WG_CONF=" /etc/wireguard/wg0.conf"
10551166
10561167auto=0
1168+ assume_yes=0
1169+ add_client=0
1170+ list_clients=0
1171+ remove_client=0
1172+ show_client_qr=0
1173+ remove_wg=0
1174+ dns1=" "
1175+ dns2=" "
1176+
1177+ parse_args " $@ "
1178+ check_args
1179+
1180+ if [ " $add_client " = 1 ]; then
1181+ show_header
1182+ new_client add_client
1183+ update_wg_conf
1184+ echo
1185+ show_client_qr_code
1186+ print_client_added
1187+ exit 0
1188+ fi
1189+
1190+ if [ " $list_clients " = 1 ]; then
1191+ show_header
1192+ print_check_clients
1193+ check_clients
1194+ echo
1195+ show_clients
1196+ print_client_total
1197+ exit 0
1198+ fi
1199+
1200+ if [ " $remove_client " = 1 ]; then
1201+ show_header
1202+ confirm_remove_client
1203+ if [[ " $remove " =~ ^[yY]$ ]]; then
1204+ print_remove_client
1205+ remove_client_wg
1206+ print_client_removed
1207+ exit 0
1208+ else
1209+ print_client_removal_aborted
1210+ exit 1
1211+ fi
1212+ fi
1213+
1214+ if [ " $show_client_qr " = 1 ]; then
1215+ show_header
1216+ echo
1217+ get_export_dir
1218+ check_client_conf
1219+ show_client_qr_code
1220+ print_client_conf
1221+ exit 0
1222+ fi
1223+
1224+ if [ " $remove_wg " = 1 ]; then
1225+ show_header
1226+ confirm_remove_wg
1227+ if [[ " $remove " =~ ^[yY]$ ]]; then
1228+ print_remove_wg
1229+ remove_firewall_rules
1230+ disable_wg_service
1231+ remove_sysctl_rules
1232+ remove_rclocal_rules
1233+ remove_pkgs
1234+ print_wg_removed
1235+ exit 0
1236+ else
1237+ print_wg_removal_aborted
1238+ exit 1
1239+ fi
1240+ fi
1241+
10571242if [[ ! -e " $WG_CONF " ]]; then
10581243 check_nftables
1059- parse_args " $@ "
10601244 install_wget
10611245 install_iproute
10621246 show_welcome
@@ -1100,28 +1284,29 @@ else
11001284 echo
11011285 show_client_qr_code
11021286 print_client_added
1103- exit
1287+ exit 0
11041288 ;;
11051289 2)
11061290 print_check_clients
11071291 check_clients
11081292 echo
11091293 show_clients
11101294 print_client_total
1111- exit
1295+ exit 0
11121296 ;;
11131297 3)
11141298 check_clients
11151299 select_client_to remove
11161300 confirm_remove_client
11171301 if [[ " $remove " =~ ^[yY]$ ]]; then
11181302 print_remove_client
1119- remove_client
1303+ remove_client_wg
11201304 print_client_removed
1305+ exit 0
11211306 else
11221307 print_client_removal_aborted
1308+ exit 1
11231309 fi
1124- exit
11251310 ;;
11261311 4)
11271312 check_clients
@@ -1131,7 +1316,7 @@ else
11311316 check_client_conf
11321317 show_client_qr_code
11331318 print_client_conf
1134- exit
1319+ exit 0
11351320 ;;
11361321 5)
11371322 confirm_remove_wg
@@ -1143,13 +1328,14 @@ else
11431328 remove_rclocal_rules
11441329 remove_pkgs
11451330 print_wg_removed
1331+ exit 0
11461332 else
11471333 print_wg_removal_aborted
1334+ exit 1
11481335 fi
1149- exit
11501336 ;;
11511337 6)
1152- exit
1338+ exit 0
11531339 ;;
11541340 esac
11551341fi
0 commit comments