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