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