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