0
|
1 #!/bin/bash
|
|
2 #
|
|
3 # https://github.com/hwdsl2/openvpn-install
|
|
4 #
|
|
5 # Based on the work of Nyr and contributors at:
|
|
6 # https://github.com/Nyr/openvpn-install
|
|
7 #
|
|
8 # Copyright (c) 2022-2024 Lin Song <linsongui@gmail.com>
|
|
9 # Copyright (c) 2013-2023 Nyr
|
|
10 #
|
|
11 # Released under the MIT License, see the accompanying file LICENSE.txt
|
|
12 # or https://opensource.org/licenses/MIT
|
|
13
|
|
14 exiterr() { echo "Error: $1" >&2; exit 1; }
|
|
15 exiterr2() { exiterr "'apt-get install' failed."; }
|
|
16 exiterr3() { exiterr "'yum install' failed."; }
|
|
17 exiterr4() { exiterr "'zypper install' failed."; }
|
|
18
|
|
19 check_ip() {
|
|
20 IP_REGEX='^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$'
|
|
21 printf '%s' "$1" | tr -d '\n' | grep -Eq "$IP_REGEX"
|
|
22 }
|
|
23
|
|
24 check_os() {
|
|
25 if grep -qs "ubuntu" /etc/os-release; then
|
|
26 os="ubuntu"
|
|
27 os_version=$(grep 'VERSION_ID' /etc/os-release | cut -d '"' -f 2 | tr -d '.')
|
|
28 group_name="nogroup"
|
|
29 elif [[ -e /etc/debian_version ]]; then
|
|
30 os="debian"
|
|
31 os_version=$(grep -oE '[0-9]+' /etc/debian_version | head -1)
|
|
32 group_name="nogroup"
|
|
33 elif [[ -e /etc/almalinux-release || -e /etc/rocky-release || -e /etc/centos-release ]]; then
|
|
34 os="centos"
|
|
35 os_version=$(grep -shoE '[0-9]+' /etc/almalinux-release /etc/rocky-release /etc/centos-release | head -1)
|
|
36 group_name="nobody"
|
|
37 elif grep -qs "Amazon Linux release 2 " /etc/system-release; then
|
|
38 os="centos"
|
|
39 os_version="7"
|
|
40 group_name="nobody"
|
|
41 elif grep -qs "Amazon Linux release 2023" /etc/system-release; then
|
|
42 exiterr "Amazon Linux 2023 is not supported."
|
|
43 elif [[ -e /etc/fedora-release ]]; then
|
|
44 os="fedora"
|
|
45 os_version=$(grep -oE '[0-9]+' /etc/fedora-release | head -1)
|
|
46 group_name="nobody"
|
|
47 elif [[ -e /etc/SUSE-brand && "$(head -1 /etc/SUSE-brand)" == "openSUSE" ]]; then
|
|
48 os="openSUSE"
|
|
49 os_version=$(tail -1 /etc/SUSE-brand | grep -oE '[0-9\\.]+')
|
|
50 group_name="nogroup"
|
|
51 else
|
|
52 exiterr "This installer seems to be running on an unsupported distribution.
|
|
53 Supported distros are Ubuntu, Debian, AlmaLinux, Rocky Linux, CentOS, Fedora, openSUSE and Amazon Linux 2."
|
|
54 fi
|
|
55 }
|
|
56
|
|
57 check_os_ver() {
|
|
58 if [[ "$os" == "ubuntu" && "$os_version" -lt 1804 ]]; then
|
|
59 exiterr "Ubuntu 18.04 or higher is required to use this installer.
|
|
60 This version of Ubuntu is too old and unsupported."
|
|
61 fi
|
|
62
|
|
63 if [[ "$os" == "debian" && "$os_version" -lt 9 ]]; then
|
|
64 exiterr "Debian 9 or higher is required to use this installer.
|
|
65 This version of Debian is too old and unsupported."
|
|
66 fi
|
|
67
|
|
68 if [[ "$os" == "centos" && "$os_version" -lt 7 ]]; then
|
|
69 exiterr "CentOS 7 or higher is required to use this installer.
|
|
70 This version of CentOS is too old and unsupported."
|
|
71 fi
|
|
72 }
|
|
73
|
|
74 check_nftables() {
|
|
75 if [ "$os" = "centos" ]; then
|
|
76 if grep -qs "hwdsl2 VPN script" /etc/sysconfig/nftables.conf \
|
|
77 || systemctl is-active --quiet nftables 2>/dev/null; then
|
|
78 exiterr "This system has nftables enabled, which is not supported by this installer."
|
|
79 fi
|
|
80 fi
|
|
81 }
|
|
82
|
|
83 check_dns_name() {
|
|
84 FQDN_REGEX='^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$'
|
|
85 printf '%s' "$1" | tr -d '\n' | grep -Eq "$FQDN_REGEX"
|
|
86 }
|
|
87
|
|
88 install_wget() {
|
|
89 # Detect some Debian minimal setups where neither wget nor curl are installed
|
|
90 if ! hash wget 2>/dev/null && ! hash curl 2>/dev/null; then
|
|
91 if [ "$auto" = 0 ]; then
|
|
92 echo "Wget is required to use this installer."
|
|
93 read -n1 -r -p "Press any key to install Wget and continue..."
|
|
94 fi
|
|
95 export DEBIAN_FRONTEND=noninteractive
|
|
96 (
|
|
97 set -x
|
|
98 apt-get -yqq update || apt-get -yqq update
|
|
99 apt-get -yqq install wget >/dev/null
|
|
100 ) || exiterr2
|
|
101 fi
|
|
102 }
|
|
103
|
|
104 install_iproute() {
|
|
105 if ! hash ip 2>/dev/null; then
|
|
106 if [ "$auto" = 0 ]; then
|
|
107 echo "iproute is required to use this installer."
|
|
108 read -n1 -r -p "Press any key to install iproute and continue..."
|
|
109 fi
|
|
110 if [ "$os" = "debian" ] || [ "$os" = "ubuntu" ]; then
|
|
111 export DEBIAN_FRONTEND=noninteractive
|
|
112 (
|
|
113 set -x
|
|
114 apt-get -yqq update || apt-get -yqq update
|
|
115 apt-get -yqq install iproute2 >/dev/null
|
|
116 ) || exiterr2
|
|
117 elif [ "$os" = "openSUSE" ]; then
|
|
118 (
|
|
119 set -x
|
|
120 zypper install iproute2 >/dev/null
|
|
121 ) || exiterr4
|
|
122 else
|
|
123 (
|
|
124 set -x
|
|
125 yum -y -q install iproute >/dev/null
|
|
126 ) || exiterr3
|
|
127 fi
|
|
128 fi
|
|
129 }
|
|
130
|
|
131 show_start_setup() {
|
|
132 if [ "$auto" = 0 ]; then
|
|
133 echo
|
|
134 echo 'Welcome to this OpenVPN server installer!'
|
|
135 echo 'GitHub: https://github.com/hwdsl2/openvpn-install'
|
|
136 echo
|
|
137 echo 'I need to ask you a few questions before starting setup.'
|
|
138 echo 'You can use the default options and just press enter if you are OK with them.'
|
|
139 else
|
|
140 show_header
|
|
141 echo
|
|
142 echo 'Starting OpenVPN setup using default options.'
|
|
143 fi
|
|
144 }
|
|
145
|
|
146 enter_server_address() {
|
|
147 echo
|
|
148 echo "Do you want OpenVPN clients to connect to this server using a DNS name,"
|
|
149 printf "e.g. vpn.example.com, instead of its IP address? [y/N] "
|
|
150 read -r response
|
|
151 case $response in
|
|
152 [yY][eE][sS]|[yY])
|
|
153 use_dns_name=1
|
|
154 echo
|
|
155 ;;
|
|
156 *)
|
|
157 use_dns_name=0
|
|
158 ;;
|
|
159 esac
|
|
160 if [ "$use_dns_name" = 1 ]; then
|
|
161 read -rp "Enter the DNS name of this VPN server: " server_addr
|
|
162 until check_dns_name "$server_addr"; do
|
|
163 echo "Invalid DNS name. You must enter a fully qualified domain name (FQDN)."
|
|
164 read -rp "Enter the DNS name of this VPN server: " server_addr
|
|
165 done
|
|
166 ip="$server_addr"
|
|
167 echo
|
|
168 echo "Note: Make sure this DNS name resolves to the IPv4 address"
|
|
169 echo " of this server. If you add or update the DNS record"
|
|
170 echo " at a later time, reboot this server to take effect."
|
|
171 else
|
|
172 detect_ip
|
|
173 check_nat_ip
|
|
174 fi
|
|
175 }
|
|
176
|
|
177 find_public_ip() {
|
|
178 ip_url1="http://ipv4.icanhazip.com"
|
|
179 ip_url2="http://ip1.dynupdate.no-ip.com"
|
|
180 # Get public IP and sanitize with grep
|
|
181 get_public_ip=$(grep -m 1 -oE '^[0-9]{1,3}(\.[0-9]{1,3}){3}$' <<< "$(wget -T 10 -t 1 -4qO- "$ip_url1" || curl -m 10 -4Ls "$ip_url1")")
|
|
182 if ! check_ip "$get_public_ip"; then
|
|
183 get_public_ip=$(grep -m 1 -oE '^[0-9]{1,3}(\.[0-9]{1,3}){3}$' <<< "$(wget -T 10 -t 1 -4qO- "$ip_url2" || curl -m 10 -4Ls "$ip_url2")")
|
|
184 fi
|
|
185 }
|
|
186
|
|
187 detect_ip() {
|
|
188 # If system has a single IPv4, it is selected automatically.
|
|
189 if [[ $(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}') -eq 1 ]]; then
|
|
190 ip=$(ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}')
|
|
191 else
|
|
192 # Use the IP address on the default route
|
|
193 ip=$(ip -4 route get 1 | sed 's/ uid .*//' | awk '{print $NF;exit}' 2>/dev/null)
|
|
194 if ! check_ip "$ip"; then
|
|
195 find_public_ip
|
|
196 ip_match=0
|
|
197 if [ -n "$get_public_ip" ]; then
|
|
198 ip_list=$(ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}')
|
|
199 while IFS= read -r line; do
|
|
200 if [ "$line" = "$get_public_ip" ]; then
|
|
201 ip_match=1
|
|
202 ip="$line"
|
|
203 fi
|
|
204 done <<< "$ip_list"
|
|
205 fi
|
|
206 if [ "$ip_match" = 0 ]; then
|
|
207 if [ "$auto" = 0 ]; then
|
|
208 echo
|
|
209 echo "Which IPv4 address should be used?"
|
|
210 num_of_ip=$(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}')
|
|
211 ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | nl -s ') '
|
|
212 read -rp "IPv4 address [1]: " ip_num
|
|
213 until [[ -z "$ip_num" || "$ip_num" =~ ^[0-9]+$ && "$ip_num" -le "$num_of_ip" ]]; do
|
|
214 echo "$ip_num: invalid selection."
|
|
215 read -rp "IPv4 address [1]: " ip_num
|
|
216 done
|
|
217 [[ -z "$ip_num" ]] && ip_num=1
|
|
218 else
|
|
219 ip_num=1
|
|
220 fi
|
|
221 ip=$(ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | sed -n "$ip_num"p)
|
|
222 fi
|
|
223 fi
|
|
224 fi
|
|
225 if ! check_ip "$ip"; then
|
|
226 echo "Error: Could not detect this server's IP address." >&2
|
|
227 echo "Abort. No changes were made." >&2
|
|
228 exit 1
|
|
229 fi
|
|
230 }
|
|
231
|
|
232 check_nat_ip() {
|
|
233 # If $ip is a private IP address, the server must be behind NAT
|
|
234 if printf '%s' "$ip" | grep -qE '^(10|127|172\.(1[6-9]|2[0-9]|3[0-1])|192\.168|169\.254)\.'; then
|
|
235 find_public_ip
|
|
236 if ! check_ip "$get_public_ip"; then
|
|
237 if [ "$auto" = 0 ]; then
|
|
238 echo
|
|
239 echo "This server is behind NAT. What is the public IPv4 address?"
|
|
240 read -rp "Public IPv4 address: " public_ip
|
|
241 until check_ip "$public_ip"; do
|
|
242 echo "Invalid input."
|
|
243 read -rp "Public IPv4 address: " public_ip
|
|
244 done
|
|
245 else
|
|
246 echo "Error: Could not detect this server's public IP." >&2
|
|
247 echo "Abort. No changes were made." >&2
|
|
248 exit 1
|
|
249 fi
|
|
250 else
|
|
251 public_ip="$get_public_ip"
|
|
252 fi
|
|
253 fi
|
|
254 }
|
|
255
|
|
256 show_config() {
|
|
257 if [ "$auto" != 0 ]; then
|
|
258 echo
|
|
259 printf '%s' "Server IP: "
|
|
260 [ -n "$public_ip" ] && printf '%s\n' "$public_ip" || printf '%s\n' "$ip"
|
|
261 echo "Port: UDP/1194"
|
|
262 echo "Client name: client"
|
|
263 echo "Client DNS: Google Public DNS"
|
|
264 fi
|
|
265 }
|
|
266
|
|
267 detect_ipv6() {
|
|
268 ip6=""
|
|
269 if [[ $(ip -6 addr | grep -c 'inet6 [23]') -ne 0 ]]; then
|
|
270 ip6=$(ip -6 addr | grep 'inet6 [23]' | cut -d '/' -f 1 | grep -oE '([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}' | sed -n 1p)
|
|
271 fi
|
|
272 }
|
|
273
|
|
274 select_protocol() {
|
|
275 if [ "$auto" = 0 ]; then
|
|
276 echo
|
|
277 echo "Which protocol should OpenVPN use?"
|
|
278 echo " 1) UDP (recommended)"
|
|
279 echo " 2) TCP"
|
|
280 read -rp "Protocol [1]: " protocol
|
|
281 until [[ -z "$protocol" || "$protocol" =~ ^[12]$ ]]; do
|
|
282 echo "$protocol: invalid selection."
|
|
283 read -rp "Protocol [1]: " protocol
|
|
284 done
|
|
285 else
|
|
286 protocol=1
|
|
287 fi
|
|
288 case "$protocol" in
|
|
289 1|"")
|
|
290 protocol=udp
|
|
291 ;;
|
|
292 2)
|
|
293 protocol=tcp
|
|
294 ;;
|
|
295 esac
|
|
296 }
|
|
297
|
|
298 select_port() {
|
|
299 if [ "$auto" = 0 ]; then
|
|
300 echo
|
|
301 echo "Which port should OpenVPN listen to?"
|
|
302 read -rp "Port [1194]: " port
|
|
303 until [[ -z "$port" || "$port" =~ ^[0-9]+$ && "$port" -le 65535 ]]; do
|
|
304 echo "$port: invalid port."
|
|
305 read -rp "Port [1194]: " port
|
|
306 done
|
|
307 [[ -z "$port" ]] && port=1194
|
|
308 else
|
|
309 port=1194
|
|
310 fi
|
|
311 }
|
|
312
|
|
313 enter_custom_dns() {
|
|
314 read -rp "Enter primary DNS server: " dns1
|
|
315 until check_ip "$dns1"; do
|
|
316 echo "Invalid DNS server."
|
|
317 read -rp "Enter primary DNS server: " dns1
|
|
318 done
|
|
319 read -rp "Enter secondary DNS server (Enter to skip): " dns2
|
|
320 until [ -z "$dns2" ] || check_ip "$dns2"; do
|
|
321 echo "Invalid DNS server."
|
|
322 read -rp "Enter secondary DNS server (Enter to skip): " dns2
|
|
323 done
|
|
324 }
|
|
325
|
|
326 select_dns() {
|
|
327 if [ "$auto" = 0 ]; then
|
|
328 echo
|
|
329 echo "Select a DNS server for the clients:"
|
|
330 echo " 1) Current system resolvers"
|
|
331 echo " 2) Google Public DNS"
|
|
332 echo " 3) Cloudflare DNS"
|
|
333 echo " 4) OpenDNS"
|
|
334 echo " 5) Quad9"
|
|
335 echo " 6) AdGuard DNS"
|
|
336 echo " 7) Custom"
|
|
337 read -rp "DNS server [2]: " dns
|
|
338 until [[ -z "$dns" || "$dns" =~ ^[1-7]$ ]]; do
|
|
339 echo "$dns: invalid selection."
|
|
340 read -rp "DNS server [2]: " dns
|
|
341 done
|
|
342 else
|
|
343 dns=2
|
|
344 fi
|
|
345 if [ "$dns" = 7 ]; then
|
|
346 enter_custom_dns
|
|
347 fi
|
|
348 }
|
|
349
|
|
350 set_client_name() {
|
|
351 # Allow a limited set of characters to avoid conflicts
|
|
352 client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
|
|
353 }
|
|
354
|
|
355 enter_client_name() {
|
|
356 if [ "$auto" = 0 ]; then
|
|
357 echo
|
|
358 echo "Enter a name for the first client:"
|
|
359 read -rp "Name [client]: " unsanitized_client
|
|
360 set_client_name
|
|
361 [[ -z "$client" ]] && client=client
|
|
362 else
|
|
363 client=client
|
|
364 fi
|
|
365 }
|
|
366
|
|
367 check_firewall() {
|
|
368 # Install a firewall if firewalld or iptables are not already available
|
|
369 if ! systemctl is-active --quiet firewalld.service && ! hash iptables 2>/dev/null; then
|
|
370 if [[ "$os" == "centos" || "$os" == "fedora" ]]; then
|
|
371 firewall="firewalld"
|
|
372 elif [[ "$os" == "openSUSE" ]]; then
|
|
373 firewall="firewalld"
|
|
374 elif [[ "$os" == "debian" || "$os" == "ubuntu" ]]; then
|
|
375 firewall="iptables"
|
|
376 fi
|
|
377 if [[ "$firewall" == "firewalld" ]]; then
|
|
378 # We don't want to silently enable firewalld, so we give a subtle warning
|
|
379 # If the user continues, firewalld will be installed and enabled during setup
|
|
380 echo
|
|
381 echo "Note: firewalld, which is required to manage routing tables, will also be installed."
|
|
382 fi
|
|
383 fi
|
|
384 }
|
|
385
|
|
386 abort_and_exit() {
|
|
387 echo "Abort. No changes were made." >&2
|
|
388 exit 1
|
|
389 }
|
|
390
|
|
391 confirm_setup() {
|
|
392 if [ "$auto" = 0 ]; then
|
|
393 printf "Do you want to continue? [Y/n] "
|
|
394 read -r response
|
|
395 case $response in
|
|
396 [yY][eE][sS]|[yY]|'')
|
|
397 :
|
|
398 ;;
|
|
399 *)
|
|
400 abort_and_exit
|
|
401 ;;
|
|
402 esac
|
|
403 fi
|
|
404 }
|
|
405
|
|
406 get_export_dir() {
|
|
407 export_to_home_dir=0
|
|
408 export_dir=~/
|
|
409 if [ -n "$SUDO_USER" ] && getent group "$SUDO_USER" >/dev/null 2>&1; then
|
|
410 user_home_dir=$(getent passwd "$SUDO_USER" 2>/dev/null | cut -d: -f6)
|
|
411 if [ -d "$user_home_dir" ] && [ "$user_home_dir" != "/" ]; then
|
|
412 export_dir="$user_home_dir/"
|
|
413 export_to_home_dir=1
|
|
414 fi
|
|
415 fi
|
|
416 }
|
|
417
|
|
418 new_client() {
|
|
419 get_export_dir
|
|
420 # Generates the custom client.ovpn
|
|
421 {
|
|
422 cat /etc/openvpn/server/client-common.txt
|
|
423 echo "<ca>"
|
|
424 cat /etc/openvpn/server/easy-rsa/pki/ca.crt
|
|
425 echo "</ca>"
|
|
426 echo "<cert>"
|
|
427 sed -ne '/BEGIN CERTIFICATE/,$ p' /etc/openvpn/server/easy-rsa/pki/issued/"$client".crt
|
|
428 echo "</cert>"
|
|
429 echo "<key>"
|
|
430 cat /etc/openvpn/server/easy-rsa/pki/private/"$client".key
|
|
431 echo "</key>"
|
|
432 echo "<tls-crypt>"
|
|
433 sed -ne '/BEGIN OpenVPN Static key/,$ p' /etc/openvpn/server/tc.key
|
|
434 echo "</tls-crypt>"
|
|
435 } > "$export_dir$client".ovpn
|
|
436 if [ "$export_to_home_dir" = 1 ]; then
|
|
437 chown "$SUDO_USER:$SUDO_USER" "$export_dir$client".ovpn
|
|
438 fi
|
|
439 chmod 600 "$export_dir$client".ovpn
|
|
440 }
|
|
441
|
|
442 update_sysctl() {
|
|
443 mkdir -p /etc/sysctl.d
|
|
444 conf_fwd="/etc/sysctl.d/99-openvpn-forward.conf"
|
|
445 conf_opt="/etc/sysctl.d/99-openvpn-optimize.conf"
|
|
446 # Enable net.ipv4.ip_forward for the system
|
|
447 echo 'net.ipv4.ip_forward=1' > "$conf_fwd"
|
|
448 if [[ -n "$ip6" ]]; then
|
|
449 # Enable net.ipv6.conf.all.forwarding for the system
|
|
450 echo "net.ipv6.conf.all.forwarding=1" >> "$conf_fwd"
|
|
451 fi
|
|
452 # Optimize sysctl settings such as TCP buffer sizes
|
|
453 base_url="https://github.com/hwdsl2/vpn-extras/releases/download/v1.0.0"
|
|
454 conf_url="$base_url/sysctl-ovpn-$os"
|
|
455 [ "$auto" != 0 ] && conf_url="${conf_url}-auto"
|
|
456 wget -t 3 -T 30 -q -O "$conf_opt" "$conf_url" 2>/dev/null \
|
|
457 || curl -m 30 -fsL "$conf_url" -o "$conf_opt" 2>/dev/null \
|
|
458 || { /bin/rm -f "$conf_opt"; touch "$conf_opt"; }
|
|
459 # Enable TCP BBR congestion control if kernel version >= 4.20
|
|
460 if modprobe -q tcp_bbr \
|
|
461 && printf '%s\n%s' "4.20" "$(uname -r)" | sort -C -V \
|
|
462 && [ -f /proc/sys/net/ipv4/tcp_congestion_control ]; then
|
|
463 cat >> "$conf_opt" <<'EOF'
|
|
464 net.core.default_qdisc = fq
|
|
465 net.ipv4.tcp_congestion_control = bbr
|
|
466 EOF
|
|
467 fi
|
|
468 # Apply sysctl settings
|
|
469 sysctl -e -q -p "$conf_fwd"
|
|
470 sysctl -e -q -p "$conf_opt"
|
|
471 }
|
|
472
|
|
473 update_rclocal() {
|
|
474 ipt_cmd="systemctl restart openvpn-iptables.service"
|
|
475 if ! grep -qs "$ipt_cmd" /etc/rc.local; then
|
|
476 if [ ! -f /etc/rc.local ]; then
|
|
477 echo '#!/bin/sh' > /etc/rc.local
|
|
478 else
|
|
479 if [ "$os" = "ubuntu" ] || [ "$os" = "debian" ]; then
|
|
480 sed --follow-symlinks -i '/^exit 0/d' /etc/rc.local
|
|
481 fi
|
|
482 fi
|
|
483 cat >> /etc/rc.local <<EOF
|
|
484
|
|
485 $ipt_cmd
|
|
486 EOF
|
|
487 if [ "$os" = "ubuntu" ] || [ "$os" = "debian" ]; then
|
|
488 echo "exit 0" >> /etc/rc.local
|
|
489 fi
|
|
490 chmod +x /etc/rc.local
|
|
491 fi
|
|
492 }
|
|
493
|
|
494 show_header() {
|
|
495 cat <<'EOF'
|
|
496
|
|
497 OpenVPN Script
|
|
498 https://github.com/hwdsl2/openvpn-install
|
|
499 EOF
|
|
500 }
|
|
501
|
|
502 show_header2() {
|
|
503 cat <<'EOF'
|
|
504
|
|
505 Copyright (c) 2022-2024 Lin Song
|
|
506 Copyright (c) 2013-2023 Nyr
|
|
507 EOF
|
|
508 }
|
|
509
|
|
510 show_usage() {
|
|
511 if [ -n "$1" ]; then
|
|
512 echo "Error: $1" >&2
|
|
513 fi
|
|
514 show_header
|
|
515 show_header2
|
|
516 cat 1>&2 <<EOF
|
|
517
|
|
518 Usage: bash $0 [options]
|
|
519
|
|
520 Options:
|
|
521 --auto auto install OpenVPN using default options
|
|
522 -h, --help show this help message and exit
|
|
523
|
|
524 To customize install options, run this script without arguments.
|
|
525 EOF
|
|
526 exit 1
|
|
527 }
|
|
528
|
|
529 ovpnsetup() {
|
|
530
|
|
531 export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
532
|
|
533 if [ "$(id -u)" != 0 ]; then
|
|
534 exiterr "This installer must be run as root. Try 'sudo bash $0'"
|
|
535 fi
|
|
536
|
|
537 # Detect Debian users running the script with "sh" instead of bash
|
|
538 if readlink /proc/$$/exe | grep -q "dash"; then
|
|
539 exiterr 'This installer needs to be run with "bash", not "sh".'
|
|
540 fi
|
|
541
|
|
542 # Detect OpenVZ 6
|
|
543 if [[ $(uname -r | cut -d "." -f 1) -eq 2 ]]; then
|
|
544 exiterr "The system is running an old kernel, which is incompatible with this installer."
|
|
545 fi
|
|
546
|
|
547 check_os
|
|
548 check_os_ver
|
|
549
|
|
550 if [[ ! -e /dev/net/tun ]] || ! ( exec 7<>/dev/net/tun ) 2>/dev/null; then
|
|
551 exiterr "The system does not have the TUN device available.
|
|
552 TUN needs to be enabled before running this installer."
|
|
553 fi
|
|
554
|
|
555 auto=0
|
|
556 if [[ ! -e /etc/openvpn/server/server.conf ]]; then
|
|
557 check_nftables
|
|
558 while [ "$#" -gt 0 ]; do
|
|
559 case $1 in
|
|
560 --auto)
|
|
561 auto=1
|
|
562 shift
|
|
563 ;;
|
|
564 -h|--help)
|
|
565 show_usage
|
|
566 ;;
|
|
567 *)
|
|
568 show_usage "Unknown parameter: $1"
|
|
569 ;;
|
|
570 esac
|
|
571 done
|
|
572 install_wget
|
|
573 install_iproute
|
|
574 show_start_setup
|
|
575 public_ip=""
|
|
576 if [ "$auto" = 0 ]; then
|
|
577 enter_server_address
|
|
578 else
|
|
579 detect_ip
|
|
580 check_nat_ip
|
|
581 fi
|
|
582 show_config
|
|
583 detect_ipv6
|
|
584 select_protocol
|
|
585 select_port
|
|
586 select_dns
|
|
587 enter_client_name
|
|
588 if [ "$auto" = 0 ]; then
|
|
589 echo
|
|
590 echo "OpenVPN installation is ready to begin."
|
|
591 fi
|
|
592 check_firewall
|
|
593 confirm_setup
|
|
594 echo
|
|
595 echo "Installing OpenVPN, please wait..."
|
|
596 # If running inside a container, disable LimitNPROC to prevent conflicts
|
|
597 if systemd-detect-virt -cq; then
|
|
598 mkdir /etc/systemd/system/openvpn-server@server.service.d/ 2>/dev/null
|
|
599 echo "[Service]
|
|
600 LimitNPROC=infinity" > /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf
|
|
601 fi
|
|
602 if [[ "$os" = "debian" || "$os" = "ubuntu" ]]; then
|
|
603 export DEBIAN_FRONTEND=noninteractive
|
|
604 (
|
|
605 set -x
|
|
606 apt-get -yqq update || apt-get -yqq update
|
|
607 apt-get -yqq --no-install-recommends install openvpn >/dev/null
|
|
608 ) || exiterr2
|
|
609 (
|
|
610 set -x
|
|
611 apt-get -yqq install openssl ca-certificates $firewall >/dev/null
|
|
612 ) || exiterr2
|
|
613 elif [[ "$os" = "centos" ]]; then
|
|
614 if grep -qs "Amazon Linux release 2 " /etc/system-release; then
|
|
615 (
|
|
616 set -x
|
|
617 amazon-linux-extras install epel -y >/dev/null
|
|
618 ) || exit 1
|
|
619 else
|
|
620 (
|
|
621 set -x
|
|
622 yum -y -q install epel-release >/dev/null
|
|
623 ) || exiterr3
|
|
624 fi
|
|
625 (
|
|
626 set -x
|
|
627 yum -y -q install openvpn openssl ca-certificates tar $firewall >/dev/null 2>&1
|
|
628 ) || exiterr3
|
|
629 elif [[ "$os" = "fedora" ]]; then
|
|
630 (
|
|
631 set -x
|
|
632 dnf install -y openvpn openssl ca-certificates tar $firewall >/dev/null
|
|
633 ) || exiterr "'dnf install' failed."
|
|
634 else
|
|
635 # Else, OS must be openSUSE
|
|
636 (
|
|
637 set -x
|
|
638 zypper install -y openvpn openssl ca-certificates tar $firewall >/dev/null
|
|
639 ) || exiterr4
|
|
640 fi
|
|
641 # If firewalld was just installed, enable it
|
|
642 if [[ "$firewall" == "firewalld" ]]; then
|
|
643 (
|
|
644 set -x
|
|
645 systemctl enable --now firewalld.service >/dev/null 2>&1
|
|
646 )
|
|
647 fi
|
|
648 # Get easy-rsa
|
|
649 easy_rsa_url='https://github.com/OpenVPN/easy-rsa/releases/download/v3.1.7/EasyRSA-3.1.7.tgz'
|
|
650 mkdir -p /etc/openvpn/server/easy-rsa/
|
|
651 { wget -t 3 -T 30 -qO- "$easy_rsa_url" 2>/dev/null || curl -m 30 -sL "$easy_rsa_url" ; } | tar xz -C /etc/openvpn/server/easy-rsa/ --strip-components 1
|
|
652 if [ ! -f /etc/openvpn/server/easy-rsa/easyrsa ]; then
|
|
653 exiterr "Failed to download EasyRSA from $easy_rsa_url."
|
|
654 fi
|
|
655 chown -R root:root /etc/openvpn/server/easy-rsa/
|
|
656 cd /etc/openvpn/server/easy-rsa/ || exit 1
|
|
657 (
|
|
658 set -x
|
|
659 # Create the PKI, set up the CA and the server and client certificates
|
|
660 ./easyrsa --batch init-pki >/dev/null
|
|
661 ./easyrsa --batch build-ca nopass >/dev/null 2>&1
|
|
662 ./easyrsa --batch --days=3650 build-server-full server nopass >/dev/null 2>&1
|
|
663 ./easyrsa --batch --days=3650 build-client-full "$client" nopass >/dev/null 2>&1
|
|
664 ./easyrsa --batch --days=3650 gen-crl >/dev/null 2>&1
|
|
665 )
|
|
666 # Move the stuff we need
|
|
667 cp pki/ca.crt pki/private/ca.key pki/issued/server.crt pki/private/server.key pki/crl.pem /etc/openvpn/server
|
|
668 # CRL is read with each client connection, while OpenVPN is dropped to nobody
|
|
669 chown nobody:"$group_name" /etc/openvpn/server/crl.pem
|
|
670 # Without +x in the directory, OpenVPN can't run a stat() on the CRL file
|
|
671 chmod o+x /etc/openvpn/server/
|
|
672 (
|
|
673 set -x
|
|
674 # Generate key for tls-crypt
|
|
675 openvpn --genkey --secret /etc/openvpn/server/tc.key >/dev/null
|
|
676 )
|
|
677 # Create the DH parameters file using the predefined ffdhe2048 group
|
|
678 echo '-----BEGIN DH PARAMETERS-----
|
|
679 MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
|
|
680 +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
|
|
681 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
|
|
682 YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
|
|
683 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
|
|
684 ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
|
|
685 -----END DH PARAMETERS-----' > /etc/openvpn/server/dh.pem
|
|
686 # Generate server.conf
|
|
687 echo "local $ip
|
|
688 port $port
|
|
689 proto $protocol
|
|
690 dev tun
|
|
691 ca ca.crt
|
|
692 cert server.crt
|
|
693 key server.key
|
|
694 dh dh.pem
|
|
695 auth SHA256
|
|
696 tls-crypt tc.key
|
|
697 topology subnet
|
|
698 server 10.8.0.0 255.255.255.0" > /etc/openvpn/server/server.conf
|
|
699 # IPv6
|
|
700 if [[ -z "$ip6" ]]; then
|
|
701 echo 'push "block-ipv6"' >> /etc/openvpn/server/server.conf
|
|
702 echo 'push "ifconfig-ipv6 fddd:1194:1194:1194::2/64 fddd:1194:1194:1194::1"' >> /etc/openvpn/server/server.conf
|
|
703 else
|
|
704 echo 'server-ipv6 fddd:1194:1194:1194::/64' >> /etc/openvpn/server/server.conf
|
|
705 fi
|
|
706 echo 'push "redirect-gateway def1 ipv6 bypass-dhcp"' >> /etc/openvpn/server/server.conf
|
|
707 echo 'ifconfig-pool-persist ipp.txt' >> /etc/openvpn/server/server.conf
|
|
708 # DNS
|
|
709 case "$dns" in
|
|
710 1)
|
|
711 # Locate the proper resolv.conf
|
|
712 # Needed for systems running systemd-resolved
|
|
713 if grep '^nameserver' "/etc/resolv.conf" | grep -qv '127.0.0.53' ; then
|
|
714 resolv_conf="/etc/resolv.conf"
|
|
715 else
|
|
716 resolv_conf="/run/systemd/resolve/resolv.conf"
|
|
717 fi
|
|
718 # Obtain the resolvers from resolv.conf and use them for OpenVPN
|
|
719 grep -v '^#\|^;' "$resolv_conf" | grep '^nameserver' | grep -v '127.0.0.53' | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | while read line; do
|
|
720 echo "push \"dhcp-option DNS $line\"" >> /etc/openvpn/server/server.conf
|
|
721 done
|
|
722 ;;
|
|
723 2|"")
|
|
724 echo 'push "dhcp-option DNS 8.8.8.8"' >> /etc/openvpn/server/server.conf
|
|
725 echo 'push "dhcp-option DNS 8.8.4.4"' >> /etc/openvpn/server/server.conf
|
|
726 ;;
|
|
727 3)
|
|
728 echo 'push "dhcp-option DNS 1.1.1.1"' >> /etc/openvpn/server/server.conf
|
|
729 echo 'push "dhcp-option DNS 1.0.0.1"' >> /etc/openvpn/server/server.conf
|
|
730 ;;
|
|
731 4)
|
|
732 echo 'push "dhcp-option DNS 208.67.222.222"' >> /etc/openvpn/server/server.conf
|
|
733 echo 'push "dhcp-option DNS 208.67.220.220"' >> /etc/openvpn/server/server.conf
|
|
734 ;;
|
|
735 5)
|
|
736 echo 'push "dhcp-option DNS 9.9.9.9"' >> /etc/openvpn/server/server.conf
|
|
737 echo 'push "dhcp-option DNS 149.112.112.112"' >> /etc/openvpn/server/server.conf
|
|
738 ;;
|
|
739 6)
|
|
740 echo 'push "dhcp-option DNS 94.140.14.14"' >> /etc/openvpn/server/server.conf
|
|
741 echo 'push "dhcp-option DNS 94.140.15.15"' >> /etc/openvpn/server/server.conf
|
|
742 ;;
|
|
743 7)
|
|
744 echo "push \"dhcp-option DNS $dns1\"" >> /etc/openvpn/server/server.conf
|
|
745 if [ -n "$dns2" ]; then
|
|
746 echo "push \"dhcp-option DNS $dns2\"" >> /etc/openvpn/server/server.conf
|
|
747 fi
|
|
748 ;;
|
|
749 esac
|
|
750 echo 'push "block-outside-dns"' >> /etc/openvpn/server/server.conf
|
|
751 echo "keepalive 10 120
|
|
752 cipher AES-128-GCM
|
|
753 user nobody
|
|
754 group $group_name
|
|
755 persist-key
|
|
756 persist-tun
|
|
757 verb 3
|
|
758 crl-verify crl.pem" >> /etc/openvpn/server/server.conf
|
|
759 if [[ "$protocol" = "udp" ]]; then
|
|
760 echo "explicit-exit-notify" >> /etc/openvpn/server/server.conf
|
|
761 fi
|
|
762 update_sysctl
|
|
763 if systemctl is-active --quiet firewalld.service; then
|
|
764 # Using both permanent and not permanent rules to avoid a firewalld
|
|
765 # reload.
|
|
766 # We don't use --add-service=openvpn because that would only work with
|
|
767 # the default port and protocol.
|
|
768 firewall-cmd -q --add-port="$port"/"$protocol"
|
|
769 firewall-cmd -q --zone=trusted --add-source=10.8.0.0/24
|
|
770 firewall-cmd -q --permanent --add-port="$port"/"$protocol"
|
|
771 firewall-cmd -q --permanent --zone=trusted --add-source=10.8.0.0/24
|
|
772 # Set NAT for the VPN subnet
|
|
773 firewall-cmd -q --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j MASQUERADE
|
|
774 firewall-cmd -q --permanent --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j MASQUERADE
|
|
775 if [[ -n "$ip6" ]]; then
|
|
776 firewall-cmd -q --zone=trusted --add-source=fddd:1194:1194:1194::/64
|
|
777 firewall-cmd -q --permanent --zone=trusted --add-source=fddd:1194:1194:1194::/64
|
|
778 firewall-cmd -q --direct --add-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j MASQUERADE
|
|
779 firewall-cmd -q --permanent --direct --add-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j MASQUERADE
|
|
780 fi
|
|
781 else
|
|
782 # Create a service to set up persistent iptables rules
|
|
783 iptables_path=$(command -v iptables)
|
|
784 ip6tables_path=$(command -v ip6tables)
|
|
785 # nf_tables is not available as standard in OVZ kernels. So use iptables-legacy
|
|
786 # if we are in OVZ, with a nf_tables backend and iptables-legacy is available.
|
|
787 if [[ $(systemd-detect-virt) == "openvz" ]] && readlink -f "$(command -v iptables)" | grep -q "nft" && hash iptables-legacy 2>/dev/null; then
|
|
788 iptables_path=$(command -v iptables-legacy)
|
|
789 ip6tables_path=$(command -v ip6tables-legacy)
|
|
790 fi
|
|
791 echo "[Unit]
|
|
792 Before=network.target
|
|
793 [Service]
|
|
794 Type=oneshot
|
|
795 ExecStart=$iptables_path -t nat -A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j MASQUERADE
|
|
796 ExecStart=$iptables_path -I INPUT -p $protocol --dport $port -j ACCEPT
|
|
797 ExecStart=$iptables_path -I FORWARD -s 10.8.0.0/24 -j ACCEPT
|
|
798 ExecStart=$iptables_path -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
|
|
799 ExecStop=$iptables_path -t nat -D POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j MASQUERADE
|
|
800 ExecStop=$iptables_path -D INPUT -p $protocol --dport $port -j ACCEPT
|
|
801 ExecStop=$iptables_path -D FORWARD -s 10.8.0.0/24 -j ACCEPT
|
|
802 ExecStop=$iptables_path -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" > /etc/systemd/system/openvpn-iptables.service
|
|
803 if [[ -n "$ip6" ]]; then
|
|
804 echo "ExecStart=$ip6tables_path -t nat -A POSTROUTING -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j MASQUERADE
|
|
805 ExecStart=$ip6tables_path -I FORWARD -s fddd:1194:1194:1194::/64 -j ACCEPT
|
|
806 ExecStart=$ip6tables_path -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
|
|
807 ExecStop=$ip6tables_path -t nat -D POSTROUTING -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j MASQUERADE
|
|
808 ExecStop=$ip6tables_path -D FORWARD -s fddd:1194:1194:1194::/64 -j ACCEPT
|
|
809 ExecStop=$ip6tables_path -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" >> /etc/systemd/system/openvpn-iptables.service
|
|
810 fi
|
|
811 echo "RemainAfterExit=yes
|
|
812 [Install]
|
|
813 WantedBy=multi-user.target" >> /etc/systemd/system/openvpn-iptables.service
|
|
814 (
|
|
815 set -x
|
|
816 systemctl enable --now openvpn-iptables.service >/dev/null 2>&1
|
|
817 )
|
|
818 fi
|
|
819 if [ "$os" != "openSUSE" ]; then
|
|
820 update_rclocal
|
|
821 fi
|
|
822 # If SELinux is enabled and a custom port was selected, we need this
|
|
823 if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$port" != 1194 ]]; then
|
|
824 # Install semanage if not already present
|
|
825 if ! hash semanage 2>/dev/null; then
|
|
826 if [[ "$os_version" -eq 7 ]]; then
|
|
827 # Centos 7
|
|
828 (
|
|
829 set -x
|
|
830 yum -y -q install policycoreutils-python >/dev/null
|
|
831 ) || exiterr3
|
|
832 else
|
|
833 # CentOS 8/9 or Fedora
|
|
834 (
|
|
835 set -x
|
|
836 dnf install -y policycoreutils-python-utils >/dev/null
|
|
837 ) || exiterr "'dnf install' failed."
|
|
838 fi
|
|
839 fi
|
|
840 semanage port -a -t openvpn_port_t -p "$protocol" "$port"
|
|
841 fi
|
|
842 # If the server is behind NAT, use the correct IP address
|
|
843 [[ -n "$public_ip" ]] && ip="$public_ip"
|
|
844 # client-common.txt is created so we have a template to add further users later
|
|
845 echo "client
|
|
846 dev tun
|
|
847 proto $protocol
|
|
848 remote $ip $port
|
|
849 resolv-retry infinite
|
|
850 nobind
|
|
851 persist-key
|
|
852 persist-tun
|
|
853 remote-cert-tls server
|
|
854 auth SHA256
|
|
855 cipher AES-128-GCM
|
|
856 ignore-unknown-option block-outside-dns block-ipv6
|
|
857 verb 3" > /etc/openvpn/server/client-common.txt
|
|
858 # Enable and start the OpenVPN service
|
|
859 if [ "$os" != "openSUSE" ]; then
|
|
860 (
|
|
861 set -x
|
|
862 systemctl enable --now openvpn-server@server.service >/dev/null 2>&1
|
|
863 )
|
|
864 else
|
|
865 ln -s /etc/openvpn/server/* /etc/openvpn >/dev/null 2>&1
|
|
866 (
|
|
867 set -x
|
|
868 systemctl enable --now openvpn@server.service >/dev/null 2>&1
|
|
869 )
|
|
870 fi
|
|
871 # Generates the custom client.ovpn
|
|
872 new_client
|
|
873 echo
|
|
874 echo "Finished!"
|
|
875 echo
|
|
876 echo "The client configuration is available in: $export_dir$client.ovpn"
|
|
877 echo "New clients can be added by running this script again."
|
|
878 else
|
|
879 show_header
|
|
880 echo
|
|
881 echo "OpenVPN is already installed."
|
|
882 echo
|
|
883 echo "Select an option:"
|
|
884 echo " 1) Add a new client"
|
|
885 echo " 2) Export config for an existing client"
|
|
886 echo " 3) List existing clients"
|
|
887 echo " 4) Revoke an existing client"
|
|
888 echo " 5) Remove OpenVPN"
|
|
889 echo " 6) Exit"
|
|
890 read -rp "Option: " option
|
|
891 until [[ "$option" =~ ^[1-6]$ ]]; do
|
|
892 echo "$option: invalid selection."
|
|
893 read -rp "Option: " option
|
|
894 done
|
|
895 case "$option" in
|
|
896 1)
|
|
897 echo
|
|
898 echo "Provide a name for the client:"
|
|
899 read -rp "Name: " unsanitized_client
|
|
900 [ -z "$unsanitized_client" ] && abort_and_exit
|
|
901 set_client_name
|
|
902 while [[ -z "$client" || -e /etc/openvpn/server/easy-rsa/pki/issued/"$client".crt ]]; do
|
|
903 echo "$client: invalid name."
|
|
904 read -rp "Name: " unsanitized_client
|
|
905 [ -z "$unsanitized_client" ] && abort_and_exit
|
|
906 set_client_name
|
|
907 done
|
|
908 cd /etc/openvpn/server/easy-rsa/ || exit 1
|
|
909 (
|
|
910 set -x
|
|
911 ./easyrsa --batch --days=3650 build-client-full "$client" nopass >/dev/null 2>&1
|
|
912 )
|
|
913 # Generates the custom client.ovpn
|
|
914 new_client
|
|
915 echo
|
|
916 echo "$client added. Configuration available in: $export_dir$client.ovpn"
|
|
917 exit
|
|
918 ;;
|
|
919 2)
|
|
920 num_of_clients=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -c "^V")
|
|
921 if [[ "$num_of_clients" = 0 ]]; then
|
|
922 echo
|
|
923 echo "There are no existing clients!"
|
|
924 exit
|
|
925 fi
|
|
926 echo
|
|
927 echo "Select the client to export:"
|
|
928 tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
|
|
929 read -rp "Client: " client_num
|
|
930 [ -z "$client_num" ] && abort_and_exit
|
|
931 until [[ "$client_num" =~ ^[0-9]+$ && "$client_num" -le "$num_of_clients" ]]; do
|
|
932 echo "$client_num: invalid selection."
|
|
933 read -rp "Client: " client_num
|
|
934 [ -z "$client_num" ] && abort_and_exit
|
|
935 done
|
|
936 client=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$client_num"p)
|
|
937 new_client
|
|
938 echo
|
|
939 echo "$client exported. Configuration available in: $export_dir$client.ovpn"
|
|
940 exit
|
|
941 ;;
|
|
942 3)
|
|
943 echo
|
|
944 echo "Checking for existing client(s)..."
|
|
945 num_of_clients=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -c "^V")
|
|
946 if [[ "$num_of_clients" = 0 ]]; then
|
|
947 echo
|
|
948 echo "There are no existing clients!"
|
|
949 exit
|
|
950 fi
|
|
951 echo
|
|
952 tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
|
|
953 if [ "$num_of_clients" = 1 ]; then
|
|
954 printf '\n%s\n' "Total: 1 client"
|
|
955 elif [ -n "$num_of_clients" ]; then
|
|
956 printf '\n%s\n' "Total: $num_of_clients clients"
|
|
957 fi
|
|
958 exit
|
|
959 ;;
|
|
960 4)
|
|
961 num_of_clients=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -c "^V")
|
|
962 if [[ "$num_of_clients" = 0 ]]; then
|
|
963 echo
|
|
964 echo "There are no existing clients!"
|
|
965 exit
|
|
966 fi
|
|
967 echo
|
|
968 echo "Select the client to revoke:"
|
|
969 tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
|
|
970 read -rp "Client: " client_num
|
|
971 [ -z "$client_num" ] && abort_and_exit
|
|
972 until [[ "$client_num" =~ ^[0-9]+$ && "$client_num" -le "$num_of_clients" ]]; do
|
|
973 echo "$client_num: invalid selection."
|
|
974 read -rp "Client: " client_num
|
|
975 [ -z "$client_num" ] && abort_and_exit
|
|
976 done
|
|
977 client=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$client_num"p)
|
|
978 echo
|
|
979 read -rp "Confirm $client revocation? [y/N]: " revoke
|
|
980 until [[ "$revoke" =~ ^[yYnN]*$ ]]; do
|
|
981 echo "$revoke: invalid selection."
|
|
982 read -rp "Confirm $client revocation? [y/N]: " revoke
|
|
983 done
|
|
984 if [[ "$revoke" =~ ^[yY]$ ]]; then
|
|
985 echo
|
|
986 echo "Revoking $client..."
|
|
987 cd /etc/openvpn/server/easy-rsa/ || exit 1
|
|
988 (
|
|
989 set -x
|
|
990 ./easyrsa --batch revoke "$client" >/dev/null 2>&1
|
|
991 ./easyrsa --batch --days=3650 gen-crl >/dev/null 2>&1
|
|
992 )
|
|
993 rm -f /etc/openvpn/server/crl.pem
|
|
994 cp /etc/openvpn/server/easy-rsa/pki/crl.pem /etc/openvpn/server/crl.pem
|
|
995 # CRL is read with each client connection, when OpenVPN is dropped to nobody
|
|
996 chown nobody:"$group_name" /etc/openvpn/server/crl.pem
|
|
997 get_export_dir
|
|
998 ovpn_file="$export_dir$client.ovpn"
|
|
999 if [ -f "$ovpn_file" ]; then
|
|
1000 echo "Removing $ovpn_file..."
|
|
1001 rm -f "$ovpn_file"
|
|
1002 fi
|
|
1003 echo
|
|
1004 echo "$client revoked!"
|
|
1005 else
|
|
1006 echo
|
|
1007 echo "$client revocation aborted!"
|
|
1008 fi
|
|
1009 exit
|
|
1010 ;;
|
|
1011 5)
|
|
1012 echo
|
|
1013 read -rp "Confirm OpenVPN removal? [y/N]: " remove
|
|
1014 until [[ "$remove" =~ ^[yYnN]*$ ]]; do
|
|
1015 echo "$remove: invalid selection."
|
|
1016 read -rp "Confirm OpenVPN removal? [y/N]: " remove
|
|
1017 done
|
|
1018 if [[ "$remove" =~ ^[yY]$ ]]; then
|
|
1019 echo
|
|
1020 echo "Removing OpenVPN, please wait..."
|
|
1021 port=$(grep '^port ' /etc/openvpn/server/server.conf | cut -d " " -f 2)
|
|
1022 protocol=$(grep '^proto ' /etc/openvpn/server/server.conf | cut -d " " -f 2)
|
|
1023 if systemctl is-active --quiet firewalld.service; then
|
|
1024 ip=$(firewall-cmd --direct --get-rules ipv4 nat POSTROUTING | grep '\-s 10.8.0.0/24 '"'"'!'"'"' -d 10.8.0.0/24' | grep -oE '[^ ]+$')
|
|
1025 # Using both permanent and not permanent rules to avoid a firewalld reload.
|
|
1026 firewall-cmd -q --remove-port="$port"/"$protocol"
|
|
1027 firewall-cmd -q --zone=trusted --remove-source=10.8.0.0/24
|
|
1028 firewall-cmd -q --permanent --remove-port="$port"/"$protocol"
|
|
1029 firewall-cmd -q --permanent --zone=trusted --remove-source=10.8.0.0/24
|
|
1030 firewall-cmd -q --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j MASQUERADE
|
|
1031 firewall-cmd -q --permanent --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j MASQUERADE
|
|
1032 if grep -qs "server-ipv6" /etc/openvpn/server/server.conf; then
|
|
1033 ip6=$(firewall-cmd --direct --get-rules ipv6 nat POSTROUTING | grep '\-s fddd:1194:1194:1194::/64 '"'"'!'"'"' -d fddd:1194:1194:1194::/64' | grep -oE '[^ ]+$')
|
|
1034 firewall-cmd -q --zone=trusted --remove-source=fddd:1194:1194:1194::/64
|
|
1035 firewall-cmd -q --permanent --zone=trusted --remove-source=fddd:1194:1194:1194::/64
|
|
1036 firewall-cmd -q --direct --remove-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j MASQUERADE
|
|
1037 firewall-cmd -q --permanent --direct --remove-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j MASQUERADE
|
|
1038 fi
|
|
1039 else
|
|
1040 systemctl disable --now openvpn-iptables.service
|
|
1041 rm -f /etc/systemd/system/openvpn-iptables.service
|
|
1042 fi
|
|
1043 if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$port" != 1194 ]]; then
|
|
1044 semanage port -d -t openvpn_port_t -p "$protocol" "$port"
|
|
1045 fi
|
|
1046 if [ "$os" != "openSUSE" ]; then
|
|
1047 systemctl disable --now openvpn-server@server.service
|
|
1048 else
|
|
1049 systemctl disable --now openvpn@server.service
|
|
1050 fi
|
|
1051 rm -f /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf
|
|
1052 rm -f /etc/sysctl.d/99-openvpn-forward.conf /etc/sysctl.d/99-openvpn-optimize.conf
|
|
1053 if [ ! -f /usr/bin/wg-quick ] && [ ! -f /usr/sbin/ipsec ] \
|
|
1054 && [ ! -f /usr/local/sbin/ipsec ]; then
|
|
1055 echo 0 > /proc/sys/net/ipv4/ip_forward
|
|
1056 echo 0 > /proc/sys/net/ipv6/conf/all/forwarding
|
|
1057 fi
|
|
1058 ipt_cmd="systemctl restart openvpn-iptables.service"
|
|
1059 if grep -qs "$ipt_cmd" /etc/rc.local; then
|
|
1060 sed --follow-symlinks -i "/^$ipt_cmd/d" /etc/rc.local
|
|
1061 fi
|
|
1062 if [[ "$os" = "debian" || "$os" = "ubuntu" ]]; then
|
|
1063 (
|
|
1064 set -x
|
|
1065 rm -rf /etc/openvpn/server
|
|
1066 apt-get remove --purge -y openvpn >/dev/null
|
|
1067 )
|
|
1068 elif [[ "$os" = "openSUSE" ]]; then
|
|
1069 (
|
|
1070 set -x
|
|
1071 zypper remove -y openvpn >/dev/null
|
|
1072 rm -rf /etc/openvpn/server
|
|
1073 )
|
|
1074 rm -f /etc/openvpn/ipp.txt
|
|
1075 else
|
|
1076 # Else, OS must be CentOS or Fedora
|
|
1077 (
|
|
1078 set -x
|
|
1079 yum -y -q remove openvpn >/dev/null
|
|
1080 rm -rf /etc/openvpn/server
|
|
1081 )
|
|
1082 fi
|
|
1083 echo
|
|
1084 echo "OpenVPN removed!"
|
|
1085 else
|
|
1086 echo
|
|
1087 echo "OpenVPN removal aborted!"
|
|
1088 fi
|
|
1089 exit
|
|
1090 ;;
|
|
1091 6)
|
|
1092 exit
|
|
1093 ;;
|
|
1094 esac
|
|
1095 fi
|
|
1096 }
|
|
1097
|
|
1098 ## Defer setup until we have the complete script
|
|
1099 ovpnsetup "$@"
|
|
1100
|
|
1101 exit 0
|