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