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