comparison openvpn-install-Nyr.sh @ 0:ebdb0cecebc0 default tip

新增
author Pluto <meokcin@gmail.com>
date Sun, 01 Sep 2024 16:38:41 +0800
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:ebdb0cecebc0
1 #!/bin/bash
2 #
3 # https://github.com/Nyr/openvpn-install
4 #
5 # Copyright (c) 2013 Nyr. Released under the MIT License.
6
7
8 # Detect Debian users running the script with "sh" instead of bash
9 if readlink /proc/$$/exe | grep -q "dash"; then
10 echo 'This installer needs to be run with "bash", not "sh".'
11 exit
12 fi
13
14 # Discard stdin. Needed when running from an one-liner which includes a newline
15 read -N 999999 -t 0.001
16
17 # Detect OS
18 # $os_version variables aren't always in use, but are kept here for convenience
19 if grep -qs "ubuntu" /etc/os-release; then
20 os="ubuntu"
21 os_version=$(grep 'VERSION_ID' /etc/os-release | cut -d '"' -f 2 | tr -d '.')
22 group_name="nogroup"
23 elif [[ -e /etc/debian_version ]]; then
24 os="debian"
25 os_version=$(grep -oE '[0-9]+' /etc/debian_version | head -1)
26 group_name="nogroup"
27 elif [[ -e /etc/almalinux-release || -e /etc/rocky-release || -e /etc/centos-release ]]; then
28 os="centos"
29 os_version=$(grep -shoE '[0-9]+' /etc/almalinux-release /etc/rocky-release /etc/centos-release | head -1)
30 group_name="nobody"
31 elif [[ -e /etc/fedora-release ]]; then
32 os="fedora"
33 os_version=$(grep -oE '[0-9]+' /etc/fedora-release | head -1)
34 group_name="nobody"
35 else
36 echo "This installer seems to be running on an unsupported distribution.
37 Supported distros are Ubuntu, Debian, AlmaLinux, Rocky Linux, CentOS and Fedora."
38 exit
39 fi
40
41 if [[ "$os" == "ubuntu" && "$os_version" -lt 2204 ]]; then
42 echo "Ubuntu 22.04 or higher is required to use this installer.
43 This version of Ubuntu is too old and unsupported."
44 exit
45 fi
46
47 if [[ "$os" == "debian" ]]; then
48 if grep -q '/sid' /etc/debian_version; then
49 echo "Debian Testing and Debian Unstable are unsupported by this installer."
50 exit
51 fi
52 if [[ "$os_version" -lt 11 ]]; then
53 echo "Debian 11 or higher is required to use this installer.
54 This version of Debian is too old and unsupported."
55 exit
56 fi
57 fi
58
59 if [[ "$os" == "centos" && "$os_version" -lt 9 ]]; then
60 os_name=$(sed 's/ release.*//' /etc/almalinux-release /etc/rocky-release /etc/centos-release 2>/dev/null | head -1)
61 echo "$os_name 9 or higher is required to use this installer.
62 This version of $os_name is too old and unsupported."
63 exit
64 fi
65
66 # Detect environments where $PATH does not include the sbin directories
67 if ! grep -q sbin <<< "$PATH"; then
68 echo '$PATH does not include sbin. Try using "su -" instead of "su".'
69 exit
70 fi
71
72 if [[ "$EUID" -ne 0 ]]; then
73 echo "This installer needs to be run with superuser privileges."
74 exit
75 fi
76
77 if [[ ! -e /dev/net/tun ]] || ! ( exec 7<>/dev/net/tun ) 2>/dev/null; then
78 echo "The system does not have the TUN device available.
79 TUN needs to be enabled before running this installer."
80 exit
81 fi
82
83 new_client () {
84 # Generates the custom client.ovpn
85 {
86 cat /etc/openvpn/server/client-common.txt
87 echo "<ca>"
88 cat /etc/openvpn/server/easy-rsa/pki/ca.crt
89 echo "</ca>"
90 echo "<cert>"
91 sed -ne '/BEGIN CERTIFICATE/,$ p' /etc/openvpn/server/easy-rsa/pki/issued/"$client".crt
92 echo "</cert>"
93 echo "<key>"
94 cat /etc/openvpn/server/easy-rsa/pki/private/"$client".key
95 echo "</key>"
96 echo "<tls-crypt>"
97 sed -ne '/BEGIN OpenVPN Static key/,$ p' /etc/openvpn/server/tc.key
98 echo "</tls-crypt>"
99 } > ~/"$client".ovpn
100 }
101
102 if [[ ! -e /etc/openvpn/server/server.conf ]]; then
103 # Detect some Debian minimal setups where neither wget nor curl are installed
104 if ! hash wget 2>/dev/null && ! hash curl 2>/dev/null; then
105 echo "Wget is required to use this installer."
106 read -n1 -r -p "Press any key to install Wget and continue..."
107 apt-get update
108 apt-get install -y wget
109 fi
110 clear
111 echo 'Welcome to this OpenVPN road warrior installer!'
112 # If system has a single IPv4, it is selected automatically. Else, ask the user
113 if [[ $(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}') -eq 1 ]]; then
114 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}')
115 else
116 number_of_ip=$(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}')
117 echo
118 echo "Which IPv4 address should be used?"
119 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 ') '
120 read -p "IPv4 address [1]: " ip_number
121 until [[ -z "$ip_number" || "$ip_number" =~ ^[0-9]+$ && "$ip_number" -le "$number_of_ip" ]]; do
122 echo "$ip_number: invalid selection."
123 read -p "IPv4 address [1]: " ip_number
124 done
125 [[ -z "$ip_number" ]] && ip_number="1"
126 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_number"p)
127 fi
128 # If $ip is a private IP address, the server must be behind NAT
129 if echo "$ip" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168)'; then
130 echo
131 echo "This server is behind NAT. What is the public IPv4 address or hostname?"
132 # Get public IP and sanitize with grep
133 get_public_ip=$(grep -m 1 -oE '^[0-9]{1,3}(\.[0-9]{1,3}){3}$' <<< "$(wget -T 10 -t 1 -4qO- "http://ip1.dynupdate.no-ip.com/" || curl -m 10 -4Ls "http://ip1.dynupdate.no-ip.com/")")
134 read -p "Public IPv4 address / hostname [$get_public_ip]: " public_ip
135 # If the checkip service is unavailable and user didn't provide input, ask again
136 until [[ -n "$get_public_ip" || -n "$public_ip" ]]; do
137 echo "Invalid input."
138 read -p "Public IPv4 address / hostname: " public_ip
139 done
140 [[ -z "$public_ip" ]] && public_ip="$get_public_ip"
141 fi
142 # If system has a single IPv6, it is selected automatically
143 if [[ $(ip -6 addr | grep -c 'inet6 [23]') -eq 1 ]]; then
144 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}')
145 fi
146 # If system has multiple IPv6, ask the user to select one
147 if [[ $(ip -6 addr | grep -c 'inet6 [23]') -gt 1 ]]; then
148 number_of_ip6=$(ip -6 addr | grep -c 'inet6 [23]')
149 echo
150 echo "Which IPv6 address should be used?"
151 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}' | nl -s ') '
152 read -p "IPv6 address [1]: " ip6_number
153 until [[ -z "$ip6_number" || "$ip6_number" =~ ^[0-9]+$ && "$ip6_number" -le "$number_of_ip6" ]]; do
154 echo "$ip6_number: invalid selection."
155 read -p "IPv6 address [1]: " ip6_number
156 done
157 [[ -z "$ip6_number" ]] && ip6_number="1"
158 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 "$ip6_number"p)
159 fi
160 echo
161 echo "Which protocol should OpenVPN use?"
162 echo " 1) UDP (recommended)"
163 echo " 2) TCP"
164 read -p "Protocol [1]: " protocol
165 until [[ -z "$protocol" || "$protocol" =~ ^[12]$ ]]; do
166 echo "$protocol: invalid selection."
167 read -p "Protocol [1]: " protocol
168 done
169 case "$protocol" in
170 1|"")
171 protocol=udp
172 ;;
173 2)
174 protocol=tcp
175 ;;
176 esac
177 echo
178 echo "What port should OpenVPN listen to?"
179 read -p "Port [1194]: " port
180 until [[ -z "$port" || "$port" =~ ^[0-9]+$ && "$port" -le 65535 ]]; do
181 echo "$port: invalid port."
182 read -p "Port [1194]: " port
183 done
184 [[ -z "$port" ]] && port="1194"
185 echo
186 echo "Select a DNS server for the clients:"
187 echo " 1) Current system resolvers"
188 echo " 2) Google"
189 echo " 3) 1.1.1.1"
190 echo " 4) OpenDNS"
191 echo " 5) Quad9"
192 echo " 6) AdGuard"
193 read -p "DNS server [1]: " dns
194 until [[ -z "$dns" || "$dns" =~ ^[1-6]$ ]]; do
195 echo "$dns: invalid selection."
196 read -p "DNS server [1]: " dns
197 done
198 echo
199 echo "Enter a name for the first client:"
200 read -p "Name [client]: " unsanitized_client
201 # Allow a limited set of characters to avoid conflicts
202 client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
203 [[ -z "$client" ]] && client="client"
204 echo
205 echo "OpenVPN installation is ready to begin."
206 # Install a firewall if firewalld or iptables are not already available
207 if ! systemctl is-active --quiet firewalld.service && ! hash iptables 2>/dev/null; then
208 if [[ "$os" == "centos" || "$os" == "fedora" ]]; then
209 firewall="firewalld"
210 # We don't want to silently enable firewalld, so we give a subtle warning
211 # If the user continues, firewalld will be installed and enabled during setup
212 echo "firewalld, which is required to manage routing tables, will also be installed."
213 elif [[ "$os" == "debian" || "$os" == "ubuntu" ]]; then
214 # iptables is way less invasive than firewalld so no warning is given
215 firewall="iptables"
216 fi
217 fi
218 read -n1 -r -p "Press any key to continue..."
219 # If running inside a container, disable LimitNPROC to prevent conflicts
220 if systemd-detect-virt -cq; then
221 mkdir /etc/systemd/system/openvpn-server@server.service.d/ 2>/dev/null
222 echo "[Service]
223 LimitNPROC=infinity" > /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf
224 fi
225 if [[ "$os" = "debian" || "$os" = "ubuntu" ]]; then
226 apt-get update
227 apt-get install -y --no-install-recommends openvpn openssl ca-certificates $firewall
228 elif [[ "$os" = "centos" ]]; then
229 dnf install -y epel-release
230 dnf install -y openvpn openssl ca-certificates tar $firewall
231 else
232 # Else, OS must be Fedora
233 dnf install -y openvpn openssl ca-certificates tar $firewall
234 fi
235 # If firewalld was just installed, enable it
236 if [[ "$firewall" == "firewalld" ]]; then
237 systemctl enable --now firewalld.service
238 fi
239 # Get easy-rsa
240 easy_rsa_url='https://github.com/OpenVPN/easy-rsa/releases/download/v3.2.0/EasyRSA-3.2.0.tgz'
241 mkdir -p /etc/openvpn/server/easy-rsa/
242 { wget -qO- "$easy_rsa_url" 2>/dev/null || curl -sL "$easy_rsa_url" ; } | tar xz -C /etc/openvpn/server/easy-rsa/ --strip-components 1
243 chown -R root:root /etc/openvpn/server/easy-rsa/
244 cd /etc/openvpn/server/easy-rsa/
245 # Create the PKI, set up the CA and the server and client certificates
246 ./easyrsa --batch init-pki
247 ./easyrsa --batch build-ca nopass
248 ./easyrsa --batch --days=3650 build-server-full server nopass
249 ./easyrsa --batch --days=3650 build-client-full "$client" nopass
250 ./easyrsa --batch --days=3650 gen-crl
251 # Move the stuff we need
252 cp pki/ca.crt pki/private/ca.key pki/issued/server.crt pki/private/server.key pki/crl.pem /etc/openvpn/server
253 # CRL is read with each client connection, while OpenVPN is dropped to nobody
254 chown nobody:"$group_name" /etc/openvpn/server/crl.pem
255 # Without +x in the directory, OpenVPN can't run a stat() on the CRL file
256 chmod o+x /etc/openvpn/server/
257 # Generate key for tls-crypt
258 openvpn --genkey secret /etc/openvpn/server/tc.key
259 # Create the DH parameters file using the predefined ffdhe2048 group
260 echo '-----BEGIN DH PARAMETERS-----
261 MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
262 +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
263 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
264 YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
265 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
266 ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
267 -----END DH PARAMETERS-----' > /etc/openvpn/server/dh.pem
268 # Generate server.conf
269 echo "local $ip
270 port $port
271 proto $protocol
272 dev tun
273 ca ca.crt
274 cert server.crt
275 key server.key
276 dh dh.pem
277 auth SHA512
278 tls-crypt tc.key
279 topology subnet
280 server 10.8.0.0 255.255.255.0" > /etc/openvpn/server/server.conf
281 # IPv6
282 if [[ -z "$ip6" ]]; then
283 echo 'push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server/server.conf
284 else
285 echo 'server-ipv6 fddd:1194:1194:1194::/64' >> /etc/openvpn/server/server.conf
286 echo 'push "redirect-gateway def1 ipv6 bypass-dhcp"' >> /etc/openvpn/server/server.conf
287 fi
288 echo 'ifconfig-pool-persist ipp.txt' >> /etc/openvpn/server/server.conf
289 # DNS
290 case "$dns" in
291 1|"")
292 # Locate the proper resolv.conf
293 # Needed for systems running systemd-resolved
294 if grep '^nameserver' "/etc/resolv.conf" | grep -qv '127.0.0.53' ; then
295 resolv_conf="/etc/resolv.conf"
296 else
297 resolv_conf="/run/systemd/resolve/resolv.conf"
298 fi
299 # Obtain the resolvers from resolv.conf and use them for OpenVPN
300 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
301 echo "push \"dhcp-option DNS $line\"" >> /etc/openvpn/server/server.conf
302 done
303 ;;
304 2)
305 echo 'push "dhcp-option DNS 8.8.8.8"' >> /etc/openvpn/server/server.conf
306 echo 'push "dhcp-option DNS 8.8.4.4"' >> /etc/openvpn/server/server.conf
307 ;;
308 3)
309 echo 'push "dhcp-option DNS 1.1.1.1"' >> /etc/openvpn/server/server.conf
310 echo 'push "dhcp-option DNS 1.0.0.1"' >> /etc/openvpn/server/server.conf
311 ;;
312 4)
313 echo 'push "dhcp-option DNS 208.67.222.222"' >> /etc/openvpn/server/server.conf
314 echo 'push "dhcp-option DNS 208.67.220.220"' >> /etc/openvpn/server/server.conf
315 ;;
316 5)
317 echo 'push "dhcp-option DNS 9.9.9.9"' >> /etc/openvpn/server/server.conf
318 echo 'push "dhcp-option DNS 149.112.112.112"' >> /etc/openvpn/server/server.conf
319 ;;
320 6)
321 echo 'push "dhcp-option DNS 94.140.14.14"' >> /etc/openvpn/server/server.conf
322 echo 'push "dhcp-option DNS 94.140.15.15"' >> /etc/openvpn/server/server.conf
323 ;;
324 esac
325 echo 'push "block-outside-dns"' >> /etc/openvpn/server/server.conf
326 echo "keepalive 10 120
327 user nobody
328 group $group_name
329 persist-key
330 persist-tun
331 verb 3
332 crl-verify crl.pem" >> /etc/openvpn/server/server.conf
333 if [[ "$protocol" = "udp" ]]; then
334 echo "explicit-exit-notify" >> /etc/openvpn/server/server.conf
335 fi
336 # Enable net.ipv4.ip_forward for the system
337 echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/99-openvpn-forward.conf
338 # Enable without waiting for a reboot or service restart
339 echo 1 > /proc/sys/net/ipv4/ip_forward
340 if [[ -n "$ip6" ]]; then
341 # Enable net.ipv6.conf.all.forwarding for the system
342 echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.d/99-openvpn-forward.conf
343 # Enable without waiting for a reboot or service restart
344 echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
345 fi
346 if systemctl is-active --quiet firewalld.service; then
347 # Using both permanent and not permanent rules to avoid a firewalld
348 # reload.
349 # We don't use --add-service=openvpn because that would only work with
350 # the default port and protocol.
351 firewall-cmd --add-port="$port"/"$protocol"
352 firewall-cmd --zone=trusted --add-source=10.8.0.0/24
353 firewall-cmd --permanent --add-port="$port"/"$protocol"
354 firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24
355 # Set NAT for the VPN subnet
356 firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip"
357 firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip"
358 if [[ -n "$ip6" ]]; then
359 firewall-cmd --zone=trusted --add-source=fddd:1194:1194:1194::/64
360 firewall-cmd --permanent --zone=trusted --add-source=fddd:1194:1194:1194::/64
361 firewall-cmd --direct --add-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to "$ip6"
362 firewall-cmd --permanent --direct --add-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to "$ip6"
363 fi
364 else
365 # Create a service to set up persistent iptables rules
366 iptables_path=$(command -v iptables)
367 ip6tables_path=$(command -v ip6tables)
368 # nf_tables is not available as standard in OVZ kernels. So use iptables-legacy
369 # if we are in OVZ, with a nf_tables backend and iptables-legacy is available.
370 if [[ $(systemd-detect-virt) == "openvz" ]] && readlink -f "$(command -v iptables)" | grep -q "nft" && hash iptables-legacy 2>/dev/null; then
371 iptables_path=$(command -v iptables-legacy)
372 ip6tables_path=$(command -v ip6tables-legacy)
373 fi
374 echo "[Unit]
375 Before=network.target
376 [Service]
377 Type=oneshot
378 ExecStart=$iptables_path -t nat -A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $ip
379 ExecStart=$iptables_path -I INPUT -p $protocol --dport $port -j ACCEPT
380 ExecStart=$iptables_path -I FORWARD -s 10.8.0.0/24 -j ACCEPT
381 ExecStart=$iptables_path -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
382 ExecStop=$iptables_path -t nat -D POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $ip
383 ExecStop=$iptables_path -D INPUT -p $protocol --dport $port -j ACCEPT
384 ExecStop=$iptables_path -D FORWARD -s 10.8.0.0/24 -j ACCEPT
385 ExecStop=$iptables_path -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" > /etc/systemd/system/openvpn-iptables.service
386 if [[ -n "$ip6" ]]; then
387 echo "ExecStart=$ip6tables_path -t nat -A POSTROUTING -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to $ip6
388 ExecStart=$ip6tables_path -I FORWARD -s fddd:1194:1194:1194::/64 -j ACCEPT
389 ExecStart=$ip6tables_path -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
390 ExecStop=$ip6tables_path -t nat -D POSTROUTING -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to $ip6
391 ExecStop=$ip6tables_path -D FORWARD -s fddd:1194:1194:1194::/64 -j ACCEPT
392 ExecStop=$ip6tables_path -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" >> /etc/systemd/system/openvpn-iptables.service
393 fi
394 echo "RemainAfterExit=yes
395 [Install]
396 WantedBy=multi-user.target" >> /etc/systemd/system/openvpn-iptables.service
397 systemctl enable --now openvpn-iptables.service
398 fi
399 # If SELinux is enabled and a custom port was selected, we need this
400 if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$port" != 1194 ]]; then
401 # Install semanage if not already present
402 if ! hash semanage 2>/dev/null; then
403 dnf install -y policycoreutils-python-utils
404 fi
405 semanage port -a -t openvpn_port_t -p "$protocol" "$port"
406 fi
407 # If the server is behind NAT, use the correct IP address
408 [[ -n "$public_ip" ]] && ip="$public_ip"
409 # client-common.txt is created so we have a template to add further users later
410 echo "client
411 dev tun
412 proto $protocol
413 remote $ip $port
414 resolv-retry infinite
415 nobind
416 persist-key
417 persist-tun
418 remote-cert-tls server
419 auth SHA512
420 ignore-unknown-option block-outside-dns
421 verb 3" > /etc/openvpn/server/client-common.txt
422 # Enable and start the OpenVPN service
423 systemctl enable --now openvpn-server@server.service
424 # Generates the custom client.ovpn
425 new_client
426 echo
427 echo "Finished!"
428 echo
429 echo "The client configuration is available in:" ~/"$client.ovpn"
430 echo "New clients can be added by running this script again."
431 else
432 clear
433 echo "OpenVPN is already installed."
434 echo
435 echo "Select an option:"
436 echo " 1) Add a new client"
437 echo " 2) Revoke an existing client"
438 echo " 3) Remove OpenVPN"
439 echo " 4) Exit"
440 read -p "Option: " option
441 until [[ "$option" =~ ^[1-4]$ ]]; do
442 echo "$option: invalid selection."
443 read -p "Option: " option
444 done
445 case "$option" in
446 1)
447 echo
448 echo "Provide a name for the client:"
449 read -p "Name: " unsanitized_client
450 client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
451 while [[ -z "$client" || -e /etc/openvpn/server/easy-rsa/pki/issued/"$client".crt ]]; do
452 echo "$client: invalid name."
453 read -p "Name: " unsanitized_client
454 client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
455 done
456 cd /etc/openvpn/server/easy-rsa/
457 ./easyrsa --batch --days=3650 build-client-full "$client" nopass
458 # Generates the custom client.ovpn
459 new_client
460 echo
461 echo "$client added. Configuration available in:" ~/"$client.ovpn"
462 exit
463 ;;
464 2)
465 # This option could be documented a bit better and maybe even be simplified
466 # ...but what can I say, I want some sleep too
467 number_of_clients=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -c "^V")
468 if [[ "$number_of_clients" = 0 ]]; then
469 echo
470 echo "There are no existing clients!"
471 exit
472 fi
473 echo
474 echo "Select the client to revoke:"
475 tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
476 read -p "Client: " client_number
477 until [[ "$client_number" =~ ^[0-9]+$ && "$client_number" -le "$number_of_clients" ]]; do
478 echo "$client_number: invalid selection."
479 read -p "Client: " client_number
480 done
481 client=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$client_number"p)
482 echo
483 read -p "Confirm $client revocation? [y/N]: " revoke
484 until [[ "$revoke" =~ ^[yYnN]*$ ]]; do
485 echo "$revoke: invalid selection."
486 read -p "Confirm $client revocation? [y/N]: " revoke
487 done
488 if [[ "$revoke" =~ ^[yY]$ ]]; then
489 cd /etc/openvpn/server/easy-rsa/
490 ./easyrsa --batch revoke "$client"
491 ./easyrsa --batch --days=3650 gen-crl
492 rm -f /etc/openvpn/server/crl.pem
493 cp /etc/openvpn/server/easy-rsa/pki/crl.pem /etc/openvpn/server/crl.pem
494 # CRL is read with each client connection, when OpenVPN is dropped to nobody
495 chown nobody:"$group_name" /etc/openvpn/server/crl.pem
496 echo
497 echo "$client revoked!"
498 else
499 echo
500 echo "$client revocation aborted!"
501 fi
502 exit
503 ;;
504 3)
505 echo
506 read -p "Confirm OpenVPN removal? [y/N]: " remove
507 until [[ "$remove" =~ ^[yYnN]*$ ]]; do
508 echo "$remove: invalid selection."
509 read -p "Confirm OpenVPN removal? [y/N]: " remove
510 done
511 if [[ "$remove" =~ ^[yY]$ ]]; then
512 port=$(grep '^port ' /etc/openvpn/server/server.conf | cut -d " " -f 2)
513 protocol=$(grep '^proto ' /etc/openvpn/server/server.conf | cut -d " " -f 2)
514 if systemctl is-active --quiet firewalld.service; then
515 ip=$(firewall-cmd --direct --get-rules ipv4 nat POSTROUTING | grep '\-s 10.8.0.0/24 '"'"'!'"'"' -d 10.8.0.0/24' | grep -oE '[^ ]+$')
516 # Using both permanent and not permanent rules to avoid a firewalld reload.
517 firewall-cmd --remove-port="$port"/"$protocol"
518 firewall-cmd --zone=trusted --remove-source=10.8.0.0/24
519 firewall-cmd --permanent --remove-port="$port"/"$protocol"
520 firewall-cmd --permanent --zone=trusted --remove-source=10.8.0.0/24
521 firewall-cmd --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip"
522 firewall-cmd --permanent --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip"
523 if grep -qs "server-ipv6" /etc/openvpn/server/server.conf; then
524 ip6=$(firewall-cmd --direct --get-rules ipv6 nat POSTROUTING | grep '\-s fddd:1194:1194:1194::/64 '"'"'!'"'"' -d fddd:1194:1194:1194::/64' | grep -oE '[^ ]+$')
525 firewall-cmd --zone=trusted --remove-source=fddd:1194:1194:1194::/64
526 firewall-cmd --permanent --zone=trusted --remove-source=fddd:1194:1194:1194::/64
527 firewall-cmd --direct --remove-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to "$ip6"
528 firewall-cmd --permanent --direct --remove-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to "$ip6"
529 fi
530 else
531 systemctl disable --now openvpn-iptables.service
532 rm -f /etc/systemd/system/openvpn-iptables.service
533 fi
534 if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$port" != 1194 ]]; then
535 semanage port -d -t openvpn_port_t -p "$protocol" "$port"
536 fi
537 systemctl disable --now openvpn-server@server.service
538 rm -f /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf
539 rm -f /etc/sysctl.d/99-openvpn-forward.conf
540 if [[ "$os" = "debian" || "$os" = "ubuntu" ]]; then
541 rm -rf /etc/openvpn/server
542 apt-get remove --purge -y openvpn
543 else
544 # Else, OS must be CentOS or Fedora
545 dnf remove -y openvpn
546 rm -rf /etc/openvpn/server
547 fi
548 echo
549 echo "OpenVPN removed!"
550 else
551 echo
552 echo "OpenVPN removal aborted!"
553 fi
554 exit
555 ;;
556 4)
557 exit
558 ;;
559 esac
560 fi
备案号:苏ICP备2024087954号-2 | 渝公网安备50010402001513