|
|
; H( n3 T1 F, ]2 ^- #!/bin/bash
' J0 r9 w0 Y' w8 @ - #/ b+ q. d$ A/ o
- # https://github.com/Nyr/openvpn-install% l$ Q4 h) s( p# [5 i, H! j
- #
! F* l( Q) B3 d/ c% J - # Copyright (c) 2013 Nyr. Released under the MIT License.0 |# s; L, l' i0 F; \3 ^3 M
- # s4 \" N# t( L/ i+ X
- 0 {% Y2 o7 L5 _, U$ \# r6 s
- # Detect Debian users running the script with "sh" instead of bash
# J7 J: G# @) O - if readlink /proc/$$/exe | grep -q "dash"; then
$ G3 p0 [# B8 Q& L - echo 'This installer needs to be run with "bash", not "sh".'6 n5 b, x R% ~1 x# G, j
- exit
% d* Z; @4 W+ k7 B% ~; B - fi
+ U, j, H5 W, j5 Z' e - & ^, v4 Q4 Q% \% f" z7 h# `
- # Discard stdin. Needed when running from an one-liner which includes a newline
, y* g: h2 r& w - read -N 999999 -t 0.001, z% o' e% q; y, m' m4 w/ ?0 d ]
- 1 `( h; r* K0 P$ `. t' r
- # Detect OpenVZ 6' N" V4 {8 @ \3 a$ H8 K+ N7 q
- if [[ $(uname -r | cut -d "." -f 1) -eq 2 ]]; then6 a& q! I2 _) g) D4 h1 a8 a& q
- echo "The system is running an old kernel, which is incompatible with this installer."" S+ q1 o5 g* | w4 G" |; j
- exit% A9 k/ ~& J4 d+ s8 E5 s
- fi5 i/ Z& r9 [2 q# l0 j8 O R+ |
/ [; x- _) q3 r4 l* X: {- B4 H$ r- # Detect OS! s7 s0 P! M" w* p3 _
- # $os_version variables aren't always in use, but are kept here for convenience
8 |* t9 N, b! \4 u3 {5 _0 p9 L7 `0 t - if grep -qs "ubuntu" /etc/os-release; then
) }) c0 d8 N1 S - os="ubuntu"& p8 q& Q8 u' b# S. d3 B% Q) g
- os_version=$(grep 'VERSION_ID' /etc/os-release | cut -d '"' -f 2 | tr -d '.')# X$ c7 c7 R6 h$ n
- group_name="nogroup"- N5 N) J5 w4 k# E0 I
- elif [[ -e /etc/debian_version ]]; then) G# H: X9 _3 v U, H4 k" \( y% K
- os="debian"3 c/ f- l7 {. C' x
- os_version=$(grep -oE '[0-9]+' /etc/debian_version | head -1)
" M4 E- k8 R. }3 A f* O; w - group_name="nogroup"' h" {' E0 w1 |5 D
- elif [[ -e /etc/almalinux-release || -e /etc/rocky-release || -e /etc/centos-release ]]; then, E9 J$ ?+ i- B: j8 ^
- os="centos"
& k5 `7 [+ B% [9 i$ p. Z1 w - os_version=$(grep -shoE '[0-9]+' /etc/almalinux-release /etc/rocky-release /etc/centos-release | head -1)% ~7 c6 Q9 I0 w& {2 q7 c! V
- group_name="nobody", H* j( m+ X* Z! o9 R
- elif [[ -e /etc/fedora-release ]]; then
8 [" U, C; n0 g/ I( ] - os="fedora"
( K# @9 }: q! H5 \2 }1 J - os_version=$(grep -oE '[0-9]+' /etc/fedora-release | head -1): k) S5 Q# S" j0 @0 I' Y1 T
- group_name="nobody" a* l0 G3 `' e1 [4 z) z1 T" F% v
- else
5 P5 I/ V% x/ N9 p& \- U K - echo "This installer seems to be running on an unsupported distribution.
' j) H; v" E) c9 c! j/ o - Supported distros are Ubuntu, Debian, AlmaLinux, Rocky Linux, CentOS and Fedora.", {* i4 E8 G F0 z
- exit* U* w3 ?3 A6 G; \4 J
- fi4 I' T$ W- b) C9 ]9 y. u& {$ g4 S
- & B+ [ v. J' F# \* m* v* e" B
- if [[ "$os" == "ubuntu" && "$os_version" -lt 1804 ]]; then; B/ m _. o8 G6 k# t2 ]
- echo "Ubuntu 18.04 or higher is required to use this installer.( g2 L" R0 s( ?" f) b
- This version of Ubuntu is too old and unsupported."7 w5 W* q# C9 g; Z
- exit. Q( f8 w( Q6 W2 P- y- }# K" _ H
- fi) Z. D- [* x2 r5 b% ~9 l3 n
- . D5 A* f5 P% _3 x# R) f* ]
- if [[ "$os" == "debian" && "$os_version" -lt 9 ]]; then! i: W% T e/ @3 I/ G$ u I7 n( |
- echo "Debian 9 or higher is required to use this installer. V5 A7 g2 }5 \) M: h5 r
- This version of Debian is too old and unsupported."5 q, x! Z- z7 {1 ?/ t9 ]
- exit
5 f- O! }; i! ]& H - fi7 J5 q& s" c9 R$ j/ j3 [
V- r% F7 I% @/ r. ~+ a. k J- if [[ "$os" == "centos" && "$os_version" -lt 7 ]]; then$ j& H3 }6 `3 n6 ~9 Y$ y8 x: J b
- echo "CentOS 7 or higher is required to use this installer.
5 l" Z4 p4 n5 M4 } - This version of CentOS is too old and unsupported."
5 o+ S! u5 N6 a4 l8 R - exit
5 f5 j) U0 R9 J: t. g- S: L6 T - fi
- n1 U1 q2 L! H' ^5 L4 g- y( `- s
# H% H2 [8 A3 v+ a2 c: {8 Z- # Detect environments where $PATH does not include the sbin directories
# @7 O. B; M+ S - if ! grep -q sbin <<< "$PATH"; then
9 |3 ^) o3 w- c - echo '$PATH does not include sbin. Try using "su -" instead of "su".'
`- e% x5 k+ n9 ] - exit u; s3 d; B* D$ k7 x! N
- fi# l9 ?9 E) Y9 ?) Q) H4 Z- [" b
' k. M9 w( v. ~& K# o9 P- if [[ "$EUID" -ne 0 ]]; then4 }; Y% W# e$ r& d/ o2 m
- echo "This installer needs to be run with superuser privileges."
: r! t8 K2 L% {; O0 f - exit
; G% n* A; R4 h- `* u. z* t6 p - fi! T" B; E& N. k* m' G* z& \, V
% a s8 g) I/ ?7 y. J- if [[ ! -e /dev/net/tun ]] || ! ( exec 7<>/dev/net/tun ) 2>/dev/null; then" X0 J9 H+ U$ a; Q
- echo "The system does not have the TUN device available.% i. P$ ]" F) q) A
- TUN needs to be enabled before running this installer."* N3 m$ q1 Q0 M& G' F- p
- exit$ k9 L2 Q5 d3 y Y' C( I6 ^( F
- fi2 @! _6 @' j. ]; g
) m5 `0 E v) e9 Q( s" Z t# [$ ]- new_client () {
3 p0 N! `8 W0 r8 O - # Generates the custom client.ovpn
/ |8 s# b" D& u& q& e - {& c0 v3 B. l+ }5 b" h5 @
- cat /etc/openvpn/server/client-common.txt
5 B2 e0 F1 |6 w* @$ J2 _ - echo "<ca>"/ D! Z0 M+ H! t: T; ]
- cat /etc/openvpn/server/easy-rsa/pki/ca.crt- }0 Q2 M9 X: p
- echo "</ca>"
( q8 A6 T) r3 H% p& c3 { - echo "<cert>"
8 e7 W9 b4 H: P6 h& o0 \ - sed -ne '/BEGIN CERTIFICATE/,$ p' /etc/openvpn/server/easy-rsa/pki/issued/"$client".crt
- F) u* ?& w$ q: ^8 w: x - echo "</cert>"
( B$ {9 q7 S7 c* V% i; P/ v- m - echo "<key>"0 h" `1 W8 z2 @. i' }
- cat /etc/openvpn/server/easy-rsa/pki/private/"$client".key3 C8 S5 d4 J: d( N
- echo "</key>": Z( T3 M2 Z/ r) o1 l
- echo "<tls-crypt>"
. {4 ~5 q2 v* o7 a4 n9 ?4 @ - sed -ne '/BEGIN OpenVPN Static key/,$ p' /etc/openvpn/server/tc.key: \ f6 y) S3 F- i: U
- echo "</tls-crypt>"+ V9 c" j! g, Y6 v
- } > ~/"$client".ovpn
6 z2 @' a+ [! d& a: s - }
9 Y! K. v+ X- `
1 {& L# W; n1 u" Y+ ]! Z6 Q4 F% O- if [[ ! -e /etc/openvpn/server/server.conf ]]; then
# M; w3 d+ G- D( \ P; V - # Detect some Debian minimal setups where neither wget nor curl are installed
& g5 l* S; w7 w [9 _6 f - if ! hash wget 2>/dev/null && ! hash curl 2>/dev/null; then
8 v O- R( ?/ C" V7 G - echo "Wget is required to use this installer."5 U9 A: L9 J4 p; G# d) J4 j
- read -n1 -r -p "Press any key to install Wget and continue..."8 k; E$ M5 }! g, r* M( @+ Z
- apt-get update
" }( l; C/ y" J: |# S: q5 n - apt-get install -y wget' D' o4 J! @) m( T
- fi
6 q$ y- d; ?2 Q' c, Q: s3 i - clear
( z! z' a6 h" _ - echo 'Welcome to this OpenVPN road warrior installer!'
( }- D3 A$ d/ Y& u- b) ? - # If system has a single IPv4, it is selected automatically. Else, ask the user
8 A6 c9 w3 A, G* }, h4 l* W - if [[ $(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}') -eq 1 ]]; then; n# U4 N0 v" U: W& ^: R; o4 ?8 z
- 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}')
( G$ i9 ~% ]# E/ ]! M: h0 }8 T6 O3 F - else
$ \6 j. O% ~0 q) S - number_of_ip=$(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}')
1 ^" \( T5 d8 j0 Z7 W% ~- A - echo
$ ^6 x$ Y7 X5 S t8 k+ F- a - echo "Which IPv4 address should be used?": C R( V& l0 G+ q6 j# U1 X% h
- 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 ') '
3 g, G" O1 E3 N7 s, K% O, C8 V - read -p "IPv4 address [1]: " ip_number' O4 d& C. t% h% U, W5 Y- W* N/ @
- until [[ -z "$ip_number" || "$ip_number" =~ ^[0-9]+$ && "$ip_number" -le "$number_of_ip" ]]; do
$ e9 Z i8 w& i' h8 F. v - echo "$ip_number: invalid selection." m6 @1 v/ R$ c0 a/ L
- read -p "IPv4 address [1]: " ip_number
* x/ M, {# I) ` - done z0 m! I4 G. l! K
- [[ -z "$ip_number" ]] && ip_number="1", d6 H7 @, s. ^% c" U' ?! K
- 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): d' W# H6 \* B; f& k; z6 |
- fi
9 c/ m$ U5 @# U: M( c - # If $ip is a private IP address, the server must be behind NAT
! L: T9 ^4 {, V [7 E4 v- U, X - if echo "$ip" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168)'; then
, {3 h7 B2 U' A8 y) e2 i+ P- Y - echo
% c" b2 h6 J: I1 V! y5 t/ v7 J( V, a - echo "This server is behind NAT. What is the public IPv4 address or hostname?"
6 b2 f+ D6 }! m: z1 s, d; b - # Get public IP and sanitize with grep
; e) p# y1 ~' H- J, d. ^" K+ m+ W - 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/")")
' z3 [ A8 M3 }( ^1 I& ^ - read -p "Public IPv4 address / hostname [$get_public_ip]: " public_ip1 ?/ b) g2 ?( @, F) ]
- # If the checkip service is unavailable and user didn't provide input, ask again
- A. k8 {% [# ?5 c/ p G8 H - until [[ -n "$get_public_ip" || -n "$public_ip" ]]; do
# p4 A6 q P8 U0 `& G! O4 J - echo "Invalid input."
) m) f$ n3 M8 E+ a3 x, H% E, ^ - read -p "Public IPv4 address / hostname: " public_ip g5 s% i/ u5 U5 F2 K
- done
) x* w" a/ `: `# C4 w: L - [[ -z "$public_ip" ]] && public_ip="$get_public_ip"
! V0 |9 k+ N2 X0 ]7 d6 B. K/ ^ - fi/ h& l& W8 b+ K) T* }" m5 m
- # If system has a single IPv6, it is selected automatically8 I+ a% A9 P3 l* Q# g' F
- if [[ $(ip -6 addr | grep -c 'inet6 [23]') -eq 1 ]]; then/ [ Q: u [; c" g s
- 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}')
* s1 N) U4 c3 i% e+ T& y - fi$ d, k7 i# `2 s6 |7 F3 ]3 Y' L
- # If system has multiple IPv6, ask the user to select one' ~' O& w# D3 X( |# P
- if [[ $(ip -6 addr | grep -c 'inet6 [23]') -gt 1 ]]; then
/ [" y5 N, e9 A- z; Z - number_of_ip6=$(ip -6 addr | grep -c 'inet6 [23]')5 J3 v6 H6 j2 w: |& v4 A: G4 V0 m# Y
- echo! G7 O# M8 \$ Q) T5 F
- echo "Which IPv6 address should be used?"1 H1 T. E/ j* a3 k3 ?! P
- 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 ') '7 m% ]1 n* D. A! W6 G
- read -p "IPv6 address [1]: " ip6_number' e) P) K" `1 Z5 X
- until [[ -z "$ip6_number" || "$ip6_number" =~ ^[0-9]+$ && "$ip6_number" -le "$number_of_ip6" ]]; do
; k2 }0 m0 Q0 m0 V - echo "$ip6_number: invalid selection."
: a9 H: k: L+ v( b( \ Y - read -p "IPv6 address [1]: " ip6_number P' L# Z& y9 t/ z& D
- done
+ k# m% d i4 p. @& ~$ Y - [[ -z "$ip6_number" ]] && ip6_number="1"( E* c# c; l; ^4 E/ y' N6 r
- 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)3 [/ T3 ]" L+ e4 {
- fi
3 |) I; s# }( }, m8 c& A5 O* y5 u; P0 d - echo
1 b ~0 w4 C& G) u/ b6 A$ N. \ | - echo "Which protocol should OpenVPN use?"
! r" o4 j" {, N: e4 w F& x) g4 B - echo " 1) UDP (recommended)"6 Z* S( N7 F3 D! R! h
- echo " 2) TCP"
( s. A- {: H0 y$ ~( M% s - read -p "Protocol [1]: " protocol
& z6 v) f' y8 _# U3 x - until [[ -z "$protocol" || "$protocol" =~ ^[12]$ ]]; do
4 E; L. P4 w% I4 B - echo "$protocol: invalid selection."
- X0 ? I; p% q# f' G5 G( [ z - read -p "Protocol [1]: " protocol# A: M" r0 S1 s; u) S
- done& D- Z1 Z) ?, P' m) Z
- case "$protocol" in; I0 Q, O7 L- \2 H" j) a# T
- 1|"")
$ r* @% b5 Q' I - protocol=udp
/ S9 |: X# }8 O, M4 \ - ;;+ a% R" h6 J' p' q1 r& H
- 2)
- }) F, D3 W9 p8 \8 ~$ v - protocol=tcp9 o( @1 t5 @$ L! {, P) ]
- ;;
0 u! m* }0 m; T; Q - esac
# W8 { l9 |4 k - echo5 A4 |8 K, g* q W1 p% W
- echo "What port should OpenVPN listen to?"
* B& z4 F( B3 V" I - read -p "Port [1194]: " port3 p+ C! h4 e8 y) v; S% e
- until [[ -z "$port" || "$port" =~ ^[0-9]+$ && "$port" -le 65535 ]]; do
( B( r) `: P' s9 n5 M - echo "$port: invalid port."
# n, G0 u* z$ K: A1 d1 S" M% n& B - read -p "Port [1194]: " port* N, ^. }2 l$ X; M
- done ~- y% I' P' f0 y8 w( H
- [[ -z "$port" ]] && port="1194"6 x: o0 K: \& y+ l4 z9 ~
- echo
. n, H2 U) v5 r4 y8 g! I! `2 }7 ~ - echo "Select a DNS server for the clients:"1 Q7 M3 @3 u: y* d- X0 E
- echo " 1) Current system resolvers"$ e- H, v4 L" R0 N- D
- echo " 2) Google"
- T3 ?2 b) L# ? - echo " 3) 1.1.1.1"
i" ~/ N1 g6 d' x - echo " 4) OpenDNS"
' g7 ~* c5 E1 M - echo " 5) Quad9") L: ]# i) s9 z2 ?# s0 z
- echo " 6) AdGuard"
{! `1 e8 o$ D - read -p "DNS server [1]: " dns' \9 `* n. o5 I, E% m4 W% l$ e
- until [[ -z "$dns" || "$dns" =~ ^[1-6]$ ]]; do
* e# e6 s4 c9 _# y% x5 B9 t - echo "$dns: invalid selection.". \5 |5 k2 S8 O! y7 \/ ?
- read -p "DNS server [1]: " dns
7 H9 l u* [' L( Q& z5 Q - done3 d( B0 w+ i/ B% |2 e5 Z' m
- echo
7 P5 u5 P4 ~- M - echo "Enter a name for the first client:"
. G- [# q! ]0 J6 h. t6 L - read -p "Name [client]: " unsanitized_client; a3 u6 |+ Y. c& q' O! }+ V
- # Allow a limited set of characters to avoid conflicts/ s3 K3 w% b( H: B' M; v& K
- client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")# o8 f6 o! q8 O, G: Z" W6 F; ]- A
- [[ -z "$client" ]] && client="client"2 N0 i6 B$ B: K6 D% W4 F0 d
- echo
7 u0 r* d6 e8 I, w - echo "OpenVPN installation is ready to begin.": ]7 ]- C- X* a6 G0 d
- # Install a firewall if firewalld or iptables are not already available6 D& u& q. G/ C4 X( t. k
- if ! systemctl is-active --quiet firewalld.service && ! hash iptables 2>/dev/null; then
2 ^+ T% B1 j- U% @3 R - if [[ "$os" == "centos" || "$os" == "fedora" ]]; then& z. @0 C2 u( b' y) K r8 ?
- firewall="firewalld"
' T- k9 R/ ?. B) K8 v4 G3 Z - # We don't want to silently enable firewalld, so we give a subtle warning# \5 _% V2 Y4 k; {9 f
- # If the user continues, firewalld will be installed and enabled during setup
& u9 ]7 R* k N0 R - echo "firewalld, which is required to manage routing tables, will also be installed."
5 F% d+ u9 |# V/ i T' I: c8 t - elif [[ "$os" == "debian" || "$os" == "ubuntu" ]]; then3 A! J/ k% z1 h, Z
- # iptables is way less invasive than firewalld so no warning is given j9 S0 A4 E1 U/ u! C
- firewall="iptables"
4 Y3 I9 f. e% Y' t5 C4 ^2 }: [* } - fi/ c; f$ J/ `$ H. ~
- fi
0 F8 ~% M- Z2 w' `6 k+ y8 h - read -n1 -r -p "Press any key to continue..."
9 d3 ?; }# _* U) r7 ^8 F& a" D - # If running inside a container, disable LimitNPROC to prevent conflicts
; [5 z0 I/ o) F( ]' A% j - if systemd-detect-virt -cq; then
% s, Z$ I5 m( C/ o* ]/ ]. l - mkdir /etc/systemd/system/openvpn-server@server.service.d/ 2>/dev/null/ e% Q ^ C8 A
- echo "[Service]
) C( g# p& ^4 w+ J% g- U - LimitNPROC=infinity" > /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf
. I4 J! {' d6 g/ ^* u! |' g - fi, a3 q6 O1 O9 i9 m, O
- if [[ "$os" = "debian" || "$os" = "ubuntu" ]]; then2 v" e: ~3 j/ m1 Z, i0 H' L
- apt-get update# B# L) k7 O! F, p
- apt-get install -y openvpn openssl ca-certificates $firewall, R Q. x4 F( n! G
- elif [[ "$os" = "centos" ]]; then
# z% u$ j, Z: f- f7 B: K - yum install -y epel-release& z+ Z; K* N: U, z! l; L. O1 w
- yum install -y openvpn openssl ca-certificates tar $firewall) f6 _( X: B/ [
- else
( \! |. C7 e: c8 ? - # Else, OS must be Fedora
! u& Z# d- `0 J$ e5 y - dnf install -y openvpn openssl ca-certificates tar $firewall- n% r/ @8 h5 B) e2 K' m
- fi
& J7 N& X( q! w0 C* I - # If firewalld was just installed, enable it
c, v3 ^$ u; ^ - if [[ "$firewall" == "firewalld" ]]; then
3 ^* W' ~ T( u - systemctl enable --now firewalld.service
' t" J9 \8 e# S. N: j+ m - fi
) R% [. A# B' D3 C' J+ {$ f" {+ l - # Get easy-rsa
* ]# ]2 `1 U" a2 Y3 ]( s - easy_rsa_url='https://github.com/OpenVPN/easy-rsa/releases/download/v3.1.0/EasyRSA-3.1.0.tgz'( }: n9 w: g- y* P- }/ p
- mkdir -p /etc/openvpn/server/easy-rsa/. i4 |! a' u. K
- { wget -qO- "$easy_rsa_url" 2>/dev/null || curl -sL "$easy_rsa_url" ; } | tar xz -C /etc/openvpn/server/easy-rsa/ --strip-components 1
: {$ D9 w; s3 h9 _; i! Z6 f) _" O - chown -R root:root /etc/openvpn/server/easy-rsa/# P" q2 K4 M. r" Q
- cd /etc/openvpn/server/easy-rsa/
* Z$ @& m0 `2 r$ G4 j - # Create the PKI, set up the CA and the server and client certificates
% n j* H* x! F - ./easyrsa init-pki
0 l0 h, R9 u& k' ], b# ~" i+ D - ./easyrsa --batch build-ca nopass
/ t( t5 A* j# d - EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-server-full server nopass$ k. F! s" L: ^5 F/ A
- EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full "$client" nopass
3 p( W& V2 p/ P* c( E - EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl: \4 R2 T% e' b
- # Move the stuff we need8 X. E) A8 S0 s0 ~0 d# P7 K
- cp pki/ca.crt pki/private/ca.key pki/issued/server.crt pki/private/server.key pki/crl.pem /etc/openvpn/server9 N' P% I; g" `7 Z) O( C8 n5 k
- # CRL is read with each client connection, while OpenVPN is dropped to nobody
/ _- h8 g2 q2 g! c0 a; I - chown nobody:"$group_name" /etc/openvpn/server/crl.pem
+ M; T1 w2 `; W- H# o - # Without +x in the directory, OpenVPN can't run a stat() on the CRL file
3 ]! T/ y s* M* h - chmod o+x /etc/openvpn/server/
2 y, ?5 R1 s0 ]4 c+ g - # Generate key for tls-crypt
9 @2 M# c8 u, ?/ d5 @% c @ - openvpn --genkey --secret /etc/openvpn/server/tc.key
9 p9 W" O" C5 e6 `( { - # Create the DH parameters file using the predefined ffdhe2048 group
$ q" \* c0 d0 u3 h' G - echo '-----BEGIN DH PARAMETERS-----: y4 m$ A; t& {
- MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz& ] X- E! x: x: d$ P( d
- +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
! f- ~5 N) h9 |# G - 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7: t: r+ h& `% U2 G7 x. s- H
- YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi+ O) }7 n. W- E9 r$ r8 ?5 I
- 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
/ t* F" s& D/ H* G- G! X - ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
6 A/ q: x. P n2 h0 d - -----END DH PARAMETERS-----' > /etc/openvpn/server/dh.pem
; o* Q$ e# _! j( l) O7 e, e - # Generate server.conf
3 x! A: Y) \& d+ Q4 i8 ^ - echo "local $ip. l$ n( O5 K# {4 V/ p8 v E
- port $port
0 I! s: l4 D" o1 d# a - proto $protocol2 Y9 Z3 f ?: b' @; h) V
- dev tun( c5 I( l- T7 D5 ?- E
- ca ca.crt: V4 w; Y! _, L
- cert server.crt: V) ]" d5 q, C1 J/ z& Y7 ^' e
- key server.key
4 Y, w3 E$ P* M B* P V6 v7 [ - dh dh.pem- }3 o# F3 P- e' c
- auth SHA512
5 i5 J2 i7 W5 J; R N0 s - tls-crypt tc.key- H" c! H5 {9 P& W9 z0 x; w8 u
- topology subnet- L* O+ E, N3 H! ?/ u; |% _
- server 10.8.0.0 255.255.255.0" > /etc/openvpn/server/server.conf
# k3 Y! H* \+ d: s( G - # IPv6/ G. g4 v% _6 G3 ?! C* v% k% |3 V
- if [[ -z "$ip6" ]]; then5 k' H/ Z0 X1 P9 }9 Q
- echo 'push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server/server.conf6 z0 p! C& f' p1 D: m2 @9 A; \6 O- l
- else' a; n' i) Q0 s9 f- g. Z' P; Z
- echo 'server-ipv6 fddd:1194:1194:1194::/64' >> /etc/openvpn/server/server.conf
9 }* C- D4 h. U% X1 S - echo 'push "redirect-gateway def1 ipv6 bypass-dhcp"' >> /etc/openvpn/server/server.conf& ?" ^9 u9 E8 a$ K" m) ?$ F- G
- fi& d1 V7 P2 k. C1 Q9 B& t
- echo 'ifconfig-pool-persist ipp.txt' >> /etc/openvpn/server/server.conf/ b7 ^/ [9 k% `& @, K6 F2 j
- # DNS) K ^# n' N9 d8 B9 L6 @6 i! N' }
- case "$dns" in
# K& A8 `( v8 \/ x2 ]9 _ - 1|"")
8 P& S, s; s$ `. Z9 S - # Locate the proper resolv.conf7 ^# L& G0 |* g% c
- # Needed for systems running systemd-resolved
1 S, |8 A& C- @: a - if grep -q '^nameserver 127.0.0.53' "/etc/resolv.conf"; then0 }% F3 O) k: R" O( q, O0 K. ?- r
- resolv_conf="/run/systemd/resolve/resolv.conf"* a& [4 r- l# L# P6 R% W2 k
- else" F Q( X0 e! \) y( M' l
- resolv_conf="/etc/resolv.conf"
# I+ f; }1 V. { A% [ - fi
2 x1 c4 a g# }$ Z5 i - # Obtain the resolvers from resolv.conf and use them for OpenVPN
! ~% j2 R' x C: s s& b1 C3 j - grep -v '^#\|^;' "$resolv_conf" | grep '^nameserver' | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | while read line; do
' l i A E, M! ~- ~0 c' t - echo "push "dhcp-option DNS $line"" >> /etc/openvpn/server/server.conf# E- `0 ?4 V! k
- done0 V% [% Y6 I0 A) a& z* |4 Y
- ;;3 s1 K. a3 W6 c- Y2 ^' j- d' @
- 2)
* }9 `$ d" _6 X: `7 A/ r0 H - echo 'push "dhcp-option DNS 8.8.8.8"' >> /etc/openvpn/server/server.conf) v5 ~6 m1 a, a- C$ s8 ^& K( ^" z
- echo 'push "dhcp-option DNS 8.8.4.4"' >> /etc/openvpn/server/server.conf
9 T: z& ~& }- T* I0 o - ;;
2 q. w6 r2 U1 X4 p7 C* N - 3)9 s- L$ [0 J4 ~0 y# J# B- u" t
- echo 'push "dhcp-option DNS 1.1.1.1"' >> /etc/openvpn/server/server.conf. ]; V/ d# D8 b* j, o; e& J8 Q$ E
- echo 'push "dhcp-option DNS 1.0.0.1"' >> /etc/openvpn/server/server.conf
4 d2 h/ w' B& r - ;;7 d( _- z, Z2 x$ o: r- `
- 4)/ m: q5 R! z \0 x" l" T& E
- echo 'push "dhcp-option DNS 208.67.222.222"' >> /etc/openvpn/server/server.conf1 ^0 c4 k6 d6 J. L+ S
- echo 'push "dhcp-option DNS 208.67.220.220"' >> /etc/openvpn/server/server.conf# e6 z1 ~* T P
- ;;% a9 c: V7 h9 n" c% v1 {
- 5)0 p p( h2 F% S0 i; ~4 e
- echo 'push "dhcp-option DNS 9.9.9.9"' >> /etc/openvpn/server/server.conf
+ ^- D* w$ x2 {- b" I2 M0 Q - echo 'push "dhcp-option DNS 149.112.112.112"' >> /etc/openvpn/server/server.conf+ v+ L# Q& s$ p) S: `
- ;;
5 O4 P: |% d) M" ` - 6)
7 C3 r& c! Y5 f0 V, X - echo 'push "dhcp-option DNS 94.140.14.14"' >> /etc/openvpn/server/server.conf- q2 z: {5 }3 q# H6 e
- echo 'push "dhcp-option DNS 94.140.15.15"' >> /etc/openvpn/server/server.conf
2 Q$ g% I* A M1 x - ;;' ~+ B& d1 M5 e: B8 W( }
- esac, E1 `9 G6 P. g5 T/ s
- echo "keepalive 10 1205 m3 d3 r# a6 \; V4 U$ B/ s
- cipher AES-256-CBC
: J& R1 F0 x# l3 I/ } - user nobody
( x1 y4 U1 S3 \" U* K" A - group $group_name: w$ b4 `, T$ ^) @4 [- d' I. C
- persist-key2 F* k: c1 ^) U( {" H* D! R+ A7 O
- persist-tun
! @5 T( _: w" ?4 Z$ S - verb 3# G! s% w- m0 R. c* q2 }
- crl-verify crl.pem" >> /etc/openvpn/server/server.conf9 X6 J$ Z3 Z0 ~: a9 E9 Y, d7 a# m
- if [[ "$protocol" = "udp" ]]; then9 w5 l! Y, e! l: N; S# \8 C
- echo "explicit-exit-notify" >> /etc/openvpn/server/server.conf
0 x1 C2 p/ k- Q8 ]4 ` w3 ~- e - fi
* ~" S$ `( T! a4 ~0 T, K2 ]6 W1 M* X - # Enable net.ipv4.ip_forward for the system
5 H/ O( W B& J q3 u' Z/ D/ L - echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/99-openvpn-forward.conf& P. e2 r& j6 h& X p1 x
- # Enable without waiting for a reboot or service restart
: {& h# Q7 F& M2 y! T4 ~ - echo 1 > /proc/sys/net/ipv4/ip_forward
; l) S& T0 E1 p - if [[ -n "$ip6" ]]; then
$ }: [/ i. F$ h' L/ f* s - # Enable net.ipv6.conf.all.forwarding for the system
9 t S" k8 M* {# w - echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.d/99-openvpn-forward.conf( c( [& u5 z2 r! B- _( K3 @
- # Enable without waiting for a reboot or service restart$ G5 W0 w) h7 p# @
- echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
, K" i. c2 L! m% |" }) y7 b) } - fi: a% q) m! ]! ^4 x& z# R0 u
- if systemctl is-active --quiet firewalld.service; then" G$ u! A4 m3 ]) l; L" m4 {
- # Using both permanent and not permanent rules to avoid a firewalld9 M. C2 w! l4 A: g3 h
- # reload.2 ~) {* n/ F# ?% v
- # We don't use --add-service=openvpn because that would only work with
" @5 `9 q1 `& ?! s' w - # the default port and protocol.
" \1 U! W- {8 U+ f& g9 B - firewall-cmd --add-port="$port"/"$protocol"& B, X% |' Q0 A2 a. |
- firewall-cmd --zone=trusted --add-source=10.8.0.0/24
0 j9 o( u7 D y; ]% D3 Y7 P - firewall-cmd --permanent --add-port="$port"/"$protocol"( k) S) G" M+ p* X+ W! L4 y( O
- firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24: h9 i8 k4 s$ V' z- e, |7 [8 W
- # Set NAT for the VPN subnet
9 F4 J* k5 a) [: s3 o4 D( e - 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"
7 H8 w0 a, ^2 T$ W% W% F - 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"
9 v& }" }$ ^; j* E' ~# B3 R, ~ - if [[ -n "$ip6" ]]; then; U/ x" ^5 a$ n9 M6 e% ]* y- d" Q5 Y
- firewall-cmd --zone=trusted --add-source=fddd:1194:1194:1194::/64) _5 `2 b5 W, S {# S8 d% A
- firewall-cmd --permanent --zone=trusted --add-source=fddd:1194:1194:1194::/64
6 m$ k" m, b, Y% p - 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"
! p: s: C. \, C7 Q6 ?: a - 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"' R/ m1 t, R5 j6 }' k
- fi9 u9 S3 q4 h, K/ l0 s- J
- else; {+ \" g0 Z! b' g# g/ X+ @1 k+ q
- # Create a service to set up persistent iptables rules
1 o5 x$ e m" b: f+ h - iptables_path=$(command -v iptables)9 z' ~; \3 Q5 h7 |
- ip6tables_path=$(command -v ip6tables)- Q2 \9 D- s8 d5 r9 y9 e; o1 q0 z
- # nf_tables is not available as standard in OVZ kernels. So use iptables-legacy0 Q! ^' P- Y2 n" p; f& M
- # if we are in OVZ, with a nf_tables backend and iptables-legacy is available.
0 h+ {% N/ ?& y0 h - if [[ $(systemd-detect-virt) == "openvz" ]] && readlink -f "$(command -v iptables)" | grep -q "nft" && hash iptables-legacy 2>/dev/null; then
' u/ U8 z5 c! L$ k2 d - iptables_path=$(command -v iptables-legacy)
! M2 u! A) j6 P$ E - ip6tables_path=$(command -v ip6tables-legacy)
( i3 Q; ?& a# I: }7 T$ D - fi
1 f: B0 {7 _3 X ^ C6 @3 { - echo "[Unit]: Q1 T y3 I: ]
- Before=network.target/ j Q" S* q1 p7 |
- [Service]4 \' ~: n7 e: i, Q+ u
- Type=oneshot% _( `! E/ Z% O& b. |
- ExecStart=$iptables_path -t nat -A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $ip
+ r1 e2 P$ Y% `: J$ q9 ` - ExecStart=$iptables_path -I INPUT -p $protocol --dport $port -j ACCEPT+ p/ g' Q# g" g
- ExecStart=$iptables_path -I FORWARD -s 10.8.0.0/24 -j ACCEPT& `. l O g" p
- ExecStart=$iptables_path -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
6 c* f* I9 E6 }/ f - ExecStop=$iptables_path -t nat -D POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $ip" Q$ h, G: |3 x$ U1 Q
- ExecStop=$iptables_path -D INPUT -p $protocol --dport $port -j ACCEPT
6 F5 |8 @) j: W7 X - ExecStop=$iptables_path -D FORWARD -s 10.8.0.0/24 -j ACCEPT
6 ?2 E3 ]$ I) M- h' P. a, {$ A+ ?$ q% t - ExecStop=$iptables_path -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" > /etc/systemd/system/openvpn-iptables.service/ b! z2 Y/ B& Z6 l7 h4 G$ F
- if [[ -n "$ip6" ]]; then
9 I: W( Q3 l2 `" H0 i' G( k* B - echo "ExecStart=$ip6tables_path -t nat -A POSTROUTING -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to $ip6
- N3 B/ d r3 e. M2 v - ExecStart=$ip6tables_path -I FORWARD -s fddd:1194:1194:1194::/64 -j ACCEPT
* y. j+ a8 _9 F( x+ w7 | - ExecStart=$ip6tables_path -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
; H2 D* Q9 _ g# B, r4 i% x - ExecStop=$ip6tables_path -t nat -D POSTROUTING -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to $ip60 x3 |" `6 h, x3 E
- ExecStop=$ip6tables_path -D FORWARD -s fddd:1194:1194:1194::/64 -j ACCEPT
; W- S+ w c2 G+ N! j - ExecStop=$ip6tables_path -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" >> /etc/systemd/system/openvpn-iptables.service
M" p( Z6 {# Q) J3 b0 k% A/ P7 X - fi
3 x4 M: }* ? @) C% L4 Y. J - echo "RemainAfterExit=yes" W% y3 W3 f/ V; d* s, H6 D+ N
- [Install] l% Y1 x+ G* G0 v" t3 X
- WantedBy=multi-user.target" >> /etc/systemd/system/openvpn-iptables.service
1 @. R' |9 ^% @& l r: O6 A+ \ - systemctl enable --now openvpn-iptables.service6 [! E3 [2 U0 a" M/ h' p7 u
- fi
9 P- v& d0 z7 A/ W - # If SELinux is enabled and a custom port was selected, we need this# B) [+ ~( ?# ?" I4 Y: M
- if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$port" != 1194 ]]; then) X; S9 ` S# J. k, _& |
- # Install semanage if not already present
4 A6 ? M# v; ]4 L - if ! hash semanage 2>/dev/null; then" U4 p( Q2 \0 x0 V+ A6 D( b4 T
- if [[ "$os_version" -eq 7 ]]; then: F9 K6 e r+ B9 P
- # Centos 77 s" Q; l8 S/ U+ D
- yum install -y policycoreutils-python
& a( \# v0 y% D( X6 B: _ - else
! h) I2 m7 N. T# z. K - # CentOS 8 or Fedora' D" w! `. p$ W1 B7 x
- dnf install -y policycoreutils-python-utils: c8 Y8 i; \. t- ~: d! i: J
- fi
! v% ?: p! u, _! [0 }3 q/ v - fi
" W; \) j( d+ W" t' b. h - semanage port -a -t openvpn_port_t -p "$protocol" "$port"/ G, H9 c+ y; I ]4 ?% ^' M
- fi( I& Q" s9 P) T
- # If the server is behind NAT, use the correct IP address/ I5 \* N% q0 ?+ [2 ]1 t ~7 K. k V
- [[ -n "$public_ip" ]] && ip="$public_ip"
: _5 V% ?- F% e# t4 z: a; k - # client-common.txt is created so we have a template to add further users later# M& j" {# J9 V/ A: G( g5 ~
- echo "client
4 k# _: [! c+ r j - dev tun2 i% t4 f* I7 c* B4 ~" q
- proto $protocol+ a* o3 D u2 `" o7 |+ m
- remote $ip $port
8 X% w, _$ x( k - resolv-retry infinite' U, z7 p' `/ ~3 I
- nobind
0 D) i m' j% y7 g$ Z - persist-key, J2 ~- w1 i$ Q; U+ I
- persist-tun' c0 O! b+ W" n$ G4 F
- remote-cert-tls server$ S8 J; ^% I& _& O4 R7 d6 r
- auth SHA512- i; R9 P' V) S
- cipher AES-256-CBC
; I7 y! F5 O% C0 T* a0 Y - ignore-unknown-option block-outside-dns
6 c- Q% m5 v- L - block-outside-dns
' W9 `3 k* ^9 } - verb 3" > /etc/openvpn/server/client-common.txt
N0 n1 k5 ^; f( t$ S8 W - # Enable and start the OpenVPN service
! ^) R3 \% A, T' n( a% Q8 k - systemctl enable --now openvpn-server@server.service* w- Y& B8 [8 f9 V7 f
- # Generates the custom client.ovpn
j5 I; }/ \; c( e' {/ [7 J - new_client z) b& D$ a1 A/ v: ^
- echo6 D0 m% M; N; m% W7 p, M" H f
- echo "Finished!". N4 |1 t3 z+ j4 W: D1 G& m
- echo8 O6 U& v, Y) g/ E
- echo "The client configuration is available in:" ~/"$client.ovpn"
2 s* I4 B+ @4 T& B' k* b - echo "New clients can be added by running this script again."
! z# B4 S2 }8 n* {# N1 o( u - else: m+ H7 }* o) \) i' Z
- clear/ j, c/ Z# r( @" g5 y9 z
- echo "OpenVPN is already installed."8 G( M4 h% o+ X: X
- echo
4 M# z I3 y" I: g9 D0 w: { - echo "Select an option:"# M. U; d2 f- u6 X; Z9 m8 Z1 m/ p
- echo " 1) Add a new client"
6 _1 N$ ] t4 A! F8 \- n# U' y - echo " 2) Revoke an existing client"7 }. I6 N' [$ v' ^
- echo " 3) Remove OpenVPN"
! i$ h1 K( n: _+ a - echo " 4) Exit"7 w0 p3 v- D3 `7 v# I1 F( S
- read -p "Option: " option3 [6 ^4 S9 Y; S8 J
- until [[ "$option" =~ ^[1-4]$ ]]; do
& Z$ I f* L8 d" p) L2 d/ Y' Q1 w - echo "$option: invalid selection."
$ Y8 X# E7 L: Z) A5 l - read -p "Option: " option$ T2 ?3 _0 a7 a- ~
- done' k' w/ x; p3 {/ w& w" J* @! c
- case "$option" in
2 g4 h0 y7 o" Y' R9 I; } - 1)( E C7 a* c- u e) Q9 d
- echo; b' u' t, V: Q6 M: ^4 n; s9 E- `; A
- echo "Provide a name for the client:"
( N- U2 H% O3 g6 Z) | - read -p "Name: " unsanitized_client' _( H5 k/ l2 n- k) a
- client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
! ~' G7 n1 w' G2 `7 L4 c - while [[ -z "$client" || -e /etc/openvpn/server/easy-rsa/pki/issued/"$client".crt ]]; do
0 J$ S6 W0 b: d0 _ - echo "$client: invalid name."
- j! l' D" X5 b% E0 n/ {& o. J - read -p "Name: " unsanitized_client
# V2 e+ ]. ]8 {8 H - client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
$ c7 t( M# r" N$ ^& R, O2 i - done
$ u+ x4 o2 [$ r: a( g$ E2 @ - cd /etc/openvpn/server/easy-rsa/
* R: P9 v6 d! `: C3 u1 M - EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full "$client" nopass8 n8 E& b, \ Z2 R
- # Generates the custom client.ovpn" t7 g7 d* b7 g; }; H/ Q
- new_client
I! e$ S( ?2 R$ H. d# R. {- x - echo8 X p' P$ b! K: A9 `% w. G" F
- echo "$client added. Configuration available in:" ~/"$client.ovpn"
+ j2 q: V8 V- A, `) @( Z2 u6 a' k3 Z - exit
- h& |9 u* ~! m; X- o' ^8 r - ;;$ r" v' Z E( X
- 2)
+ {) u5 `5 c$ O2 j# e - # This option could be documented a bit better and maybe even be simplified, P4 ]3 c& K# E* S( n
- # ...but what can I say, I want some sleep too
# v& W' ^( k3 E/ K; a: i7 q3 ~ - number_of_clients=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -c "^V")
p3 r2 F3 E5 G; n0 a - if [[ "$number_of_clients" = 0 ]]; then9 U$ J7 @1 Q# V# o6 ]
- echo
2 o! w8 z( D( a% f) H - echo "There are no existing clients!"0 T" k4 ~/ P9 o) x8 S
- exit# S1 O1 Y+ d/ ?. P
- fi
$ N; j' S |" M; O, O; A/ x - echo7 `3 \% f" K% |( T: f3 C
- echo "Select the client to revoke:"% j3 A* S+ W1 X) K. Q) W0 o
- tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
[! d( L; x+ F4 D0 q3 j) F - read -p "Client: " client_number
+ K5 k M8 F) \/ \& z% a - until [[ "$client_number" =~ ^[0-9]+$ && "$client_number" -le "$number_of_clients" ]]; do! T. T2 i- c9 l; F5 K* E! v1 G
- echo "$client_number: invalid selection."
: h" m* V8 }. N- b, U8 { - read -p "Client: " client_number
% M s) }& \1 D( i - done/ C5 c/ g# H" V
- client=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$client_number"p)+ |4 G' Q. E1 r
- echo
* n! Q: w. J$ O0 M. O7 Z - read -p "Confirm $client revocation? [y/N]: " revoke
9 F# X4 |& d0 d' i" C - until [[ "$revoke" =~ ^[yYnN]*$ ]]; do N: T" T- U6 h6 U& y
- echo "$revoke: invalid selection."" [3 C- F3 M! z8 K# q% _
- read -p "Confirm $client revocation? [y/N]: " revoke( F0 w7 w5 P. Z0 L! c
- done# `6 i% y! }1 C# V. e) s
- if [[ "$revoke" =~ ^[yY]$ ]]; then# C0 _6 l; v8 o$ `0 B
- cd /etc/openvpn/server/easy-rsa/
3 z' _8 ^# T- Z/ K2 y, x9 | - ./easyrsa --batch revoke "$client"3 |0 O' |8 Y$ p
- EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl5 J4 W' `( _! O7 d& T' S. l x
- rm -f /etc/openvpn/server/crl.pem
; @# S) ~* ~' a) w - cp /etc/openvpn/server/easy-rsa/pki/crl.pem /etc/openvpn/server/crl.pem
% H& A. T j: Z: B. v( s M - # CRL is read with each client connection, when OpenVPN is dropped to nobody5 A2 F% C0 X: }/ u
- chown nobody:"$group_name" /etc/openvpn/server/crl.pem
, m! f' |9 Z% [# }3 K- L - echo
8 ^5 b+ W& x( b! F: c. b - echo "$client revoked!"
* T5 y5 s/ _- X+ J. @8 g, i: S! Z8 J2 Z - else8 o) e9 L. c; i5 R0 A
- echo
7 J0 F; M5 _% K - echo "$client revocation aborted!"
: J& |* y( s1 G" {- T( Z - fi
( Q# s" k& F! @* F# p - exit
# |3 }6 _0 d3 ^7 S. q6 ^ - ;;
7 k* P% \6 j' P2 y) r6 W( q4 n1 a - 3)
, L' {/ Q7 @: y4 f" t8 N - echo" h5 u7 [) }1 n$ r X$ B Q% T
- read -p "Confirm OpenVPN removal? [y/N]: " remove
: M( Q' d. E h. B6 ` - until [[ "$remove" =~ ^[yYnN]*$ ]]; do
& Q7 |4 u! q9 g' C0 D: y - echo "$remove: invalid selection."6 L2 g: Z& Y4 V- c1 b
- read -p "Confirm OpenVPN removal? [y/N]: " remove
) |) m% M# A/ B; G; C' u - done
% |; W+ O6 }0 ?; s2 u& ?; Q& w - if [[ "$remove" =~ ^[yY]$ ]]; then
, x1 D u9 f% x: K+ o - port=$(grep '^port ' /etc/openvpn/server/server.conf | cut -d " " -f 2)
: l6 H; `$ r7 @4 C' N4 [ - protocol=$(grep '^proto ' /etc/openvpn/server/server.conf | cut -d " " -f 2)
% H3 I/ q) e8 W - if systemctl is-active --quiet firewalld.service; then) F- S- A8 e- |6 @; K [
- ip=$(firewall-cmd --direct --get-rules ipv4 nat POSTROUTING | grep '\-s 10.8.0.0/24 '"'"'!'"'"' -d 10.8.0.0/24' | grep -oE '[^ ]+$')
/ z- j' T; W: D3 C% ^" K& n2 I& c - # Using both permanent and not permanent rules to avoid a firewalld reload.( u4 Z* s5 E! z' M7 m: m
- firewall-cmd --remove-port="$port"/"$protocol"9 D% n" @# G' |/ x' m
- firewall-cmd --zone=trusted --remove-source=10.8.0.0/24- e/ e3 x8 _+ j( D( T; E4 @, r
- firewall-cmd --permanent --remove-port="$port"/"$protocol"
7 m/ \* @6 t) E y) p - firewall-cmd --permanent --zone=trusted --remove-source=10.8.0.0/24 w6 Q9 q, J; x
- 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"
; Z: E5 s. ]0 ?6 z6 |9 h" H - 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"
% t3 g1 b8 A% b. b @ - if grep -qs "server-ipv6" /etc/openvpn/server/server.conf; then; q' o% \: p6 Z
- ip6=$(firewall-cmd --direct --get-rules ipv6 nat POSTROUTING | grep '\-s fddd:1194:1194:1194::/64 '"'"'!'"'"' -d fddd:1194:1194:1194::/64' | grep -oE '[^ ]+$')
* q; F: z! Y4 W3 c+ q: w6 ~3 j - firewall-cmd --zone=trusted --remove-source=fddd:1194:1194:1194::/64
" y" q# t; b' i& A - firewall-cmd --permanent --zone=trusted --remove-source=fddd:1194:1194:1194::/64 \+ M3 P5 h" D) v% l! b) D
- 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"
8 b: `5 j; E+ ^. Z4 b - 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"
9 m3 g0 A$ w+ ~3 g% V* G! Q. A5 i. ` - fi
2 O4 t5 k9 @$ n; n2 T1 _# y - else
( q$ e }& L2 S8 ~: M - systemctl disable --now openvpn-iptables.service
) _) }' [$ b5 {0 P1 W - rm -f /etc/systemd/system/openvpn-iptables.service( {$ n: {' P1 `( Y1 F/ H4 Y
- fi. V- d8 y0 t" d9 X/ o
- if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$port" != 1194 ]]; then
/ b* |1 u. o, ]: i4 p) O: D7 ? B- P - semanage port -d -t openvpn_port_t -p "$protocol" "$port"9 N# K. n7 ? Y# C# M3 o. J5 S8 x- m
- fi4 g! C6 F. R5 T- U3 P3 |5 c
- systemctl disable --now openvpn-server@server.service5 g' P4 T6 o9 s1 }/ ^: H2 U
- rm -f /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf
' s) F7 ^- p) D - rm -f /etc/sysctl.d/99-openvpn-forward.conf: \* @" [( a1 C' J {8 f
- if [[ "$os" = "debian" || "$os" = "ubuntu" ]]; then
; h C: `# i3 Q% Q {: A - rm -rf /etc/openvpn/server
) [5 d" N2 a7 ?9 }! l - apt-get remove --purge -y openvpn
! R4 B! K) ?) x8 O* K i - else5 x2 |1 \" K" z# w$ m% f% g# J
- # Else, OS must be CentOS or Fedora" X: T' h+ w9 h# S3 z4 ~
- yum remove -y openvpn% B! ?- d4 o: e5 Q r/ A
- rm -rf /etc/openvpn/server
. U2 c1 |) J+ P" ]3 d. } - fi" c, Y/ N c/ N% Y
- echo( s) V: j( y4 s6 }1 _0 U1 u
- echo "OpenVPN removed!"- K" t( c/ x! t- }( y
- else0 j# ?- P, _4 _7 P B) f' Q
- echo
8 V4 P0 N% b9 J, F - echo "OpenVPN removal aborted!"
/ w& n+ i* i* f( b4 r - fi; ^9 j2 K) x n4 \+ \, w8 @: ?6 l+ H
- exit- ?) L6 }4 W, Q& e4 J0 a
- ;;8 f" O* O* y# o! j
- 4)
4 ^6 Q+ M/ N; r+ G i9 d+ ~, s - exit E7 ^: e' q, E4 T
- ;;$ C& [: G$ o3 g
- esac
& G$ w, Y. I, ~' w- I6 S/ A& u5 H - fi
\! P* p4 }9 S! S$ @. x3 {7 Z
复制代码 ( M( h# v) W i& X$ b% g8 I
& B1 m2 O7 O s! I5 [# o& ^
* h& A( Q, C7 |( F8 U8 X; h5 n3 a0 m z# b& C
|
|