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