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