mirror of
https://github.com/Nyr/openvpn-install.git
synced 2024-11-27 15:36:07 +03:00
Miscellaneous improvements
This commit contains lots changes which are not very significant on its own but provide important usability improvements and future proofing. It also includes changes which required OpenVPN v2.4+ and were pending until that version became widely available. - General cleanup - Improved IP address and NAT configuration - Added input validation and sanitization - Fix #603 - Remove "sndbuf" and "recvbuf" parameters - Add server-side "explicit-exit-notify" - Switch from "setenv opt" to "ignore-unknown-option" - Switch from "tls-auth" to "tls-crypt" - Other minor bugfixes and optimizations
This commit is contained in:
parent
68e48d21b6
commit
6a29a6babd
@ -5,22 +5,22 @@
|
|||||||
# Copyright (c) 2013 Nyr. Released under the MIT License.
|
# Copyright (c) 2013 Nyr. Released under the MIT License.
|
||||||
|
|
||||||
|
|
||||||
if grep -qs "14.04" "/etc/os-release"; then
|
if grep -qs "14.04" /etc/os-release; then
|
||||||
echo "Ubuntu 14.04 is too old and not supported"
|
echo "Ubuntu 14.04 is too old and not supported"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if grep -qs "jessie" "/etc/os-release"; then
|
if grep -qs "jessie" /etc/os-release; then
|
||||||
echo "Debian 8 is too old and not supported"
|
echo "Debian 8 is too old and not supported"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if grep -qs "CentOS release 6" "/etc/redhat-release"; then
|
if grep -qs "CentOS release 6" /etc/redhat-release; then
|
||||||
echo "CentOS 6 is too old and not supported"
|
echo "CentOS 6 is too old and not supported"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if grep -qs "Ubuntu 16.04" "/etc/os-release"; then
|
if grep -qs "Ubuntu 16.04" /etc/os-release; then
|
||||||
echo 'Ubuntu 16.04 is no longer supported in the current version of openvpn-install
|
echo 'Ubuntu 16.04 is no longer supported in the current version of openvpn-install
|
||||||
Use an older version if Ubuntu 16.04 support is needed: https://git.io/vpn1604'
|
Use an older version if Ubuntu 16.04 support is needed: https://git.io/vpn1604'
|
||||||
exit
|
exit
|
||||||
@ -44,31 +44,33 @@ You need to enable TUN before running this script"
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -e /etc/debian_version ]]; then
|
if [[ -e /etc/debian_version ]]; then
|
||||||
OS=debian
|
os="debian"
|
||||||
GROUPNAME=nogroup
|
group_name="nogroup"
|
||||||
elif [[ -e /etc/centos-release || -e /etc/redhat-release ]]; then
|
elif [[ -e /etc/centos-release || -e /etc/redhat-release ]]; then
|
||||||
OS=centos
|
os="centos"
|
||||||
GROUPNAME=nobody
|
group_name="nobody"
|
||||||
else
|
else
|
||||||
echo "Looks like you aren't running this installer on Debian, Ubuntu or CentOS"
|
echo "Looks like you aren't running this installer on Debian, Ubuntu or CentOS"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
newclient () {
|
new_client () {
|
||||||
# Generates the custom client.ovpn
|
# Generates the custom client.ovpn
|
||||||
cp /etc/openvpn/server/client-common.txt ~/$1.ovpn
|
{
|
||||||
echo "<ca>" >> ~/$1.ovpn
|
cat /etc/openvpn/server/client-common.txt
|
||||||
cat /etc/openvpn/server/easy-rsa/pki/ca.crt >> ~/$1.ovpn
|
echo "<ca>"
|
||||||
echo "</ca>" >> ~/$1.ovpn
|
cat /etc/openvpn/server/easy-rsa/pki/ca.crt
|
||||||
echo "<cert>" >> ~/$1.ovpn
|
echo "</ca>"
|
||||||
sed -ne '/BEGIN CERTIFICATE/,$ p' /etc/openvpn/server/easy-rsa/pki/issued/$1.crt >> ~/$1.ovpn
|
echo "<cert>"
|
||||||
echo "</cert>" >> ~/$1.ovpn
|
sed -ne '/BEGIN CERTIFICATE/,$ p' /etc/openvpn/server/easy-rsa/pki/issued/"$1".crt
|
||||||
echo "<key>" >> ~/$1.ovpn
|
echo "</cert>"
|
||||||
cat /etc/openvpn/server/easy-rsa/pki/private/$1.key >> ~/$1.ovpn
|
echo "<key>"
|
||||||
echo "</key>" >> ~/$1.ovpn
|
cat /etc/openvpn/server/easy-rsa/pki/private/"$1".key
|
||||||
echo "<tls-auth>" >> ~/$1.ovpn
|
echo "</key>"
|
||||||
sed -ne '/BEGIN OpenVPN Static key/,$ p' /etc/openvpn/server/ta.key >> ~/$1.ovpn
|
echo "<tls-crypt>"
|
||||||
echo "</tls-auth>" >> ~/$1.ovpn
|
sed -ne '/BEGIN OpenVPN Static key/,$ p' /etc/openvpn/server/tc.key
|
||||||
|
echo "</tls-crypt>"
|
||||||
|
} > ~/"$1".ovpn
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ -e /etc/openvpn/server/server.conf ]]; then
|
if [[ -e /etc/openvpn/server/server.conf ]]; then
|
||||||
@ -82,26 +84,35 @@ if [[ -e /etc/openvpn/server/server.conf ]]; then
|
|||||||
echo " 2) Revoke an existing user"
|
echo " 2) Revoke an existing user"
|
||||||
echo " 3) Remove OpenVPN"
|
echo " 3) Remove OpenVPN"
|
||||||
echo " 4) Exit"
|
echo " 4) Exit"
|
||||||
read -p "Select an option [1-4]: " option
|
read -p "Select an option: " option
|
||||||
case $option in
|
until [[ "$option" =~ ^[1-4]$ ]]; do
|
||||||
|
echo "$option: invalid selection."
|
||||||
|
read -p "Select an option: " option
|
||||||
|
done
|
||||||
|
case "$option" in
|
||||||
1)
|
1)
|
||||||
echo
|
echo
|
||||||
echo "Tell me a name for the client certificate."
|
echo "Tell me a name for the client certificate."
|
||||||
echo "Please, use one word only, no special characters."
|
read -p "Client name: " unsanitized_client
|
||||||
read -p "Client name: " -e CLIENT
|
client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
|
||||||
|
while [[ -z "$client" || -e /etc/openvpn/server/easy-rsa/pki/issued/"$client".crt ]]; do
|
||||||
|
echo "$client: invalid client name."
|
||||||
|
read -p "Client name: " unsanitized_client
|
||||||
|
client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
|
||||||
|
done
|
||||||
cd /etc/openvpn/server/easy-rsa/
|
cd /etc/openvpn/server/easy-rsa/
|
||||||
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full $CLIENT nopass
|
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full "$client" nopass
|
||||||
# Generates the custom client.ovpn
|
# Generates the custom client.ovpn
|
||||||
newclient "$CLIENT"
|
new_client "$client"
|
||||||
echo
|
echo
|
||||||
echo "Client $CLIENT added, configuration is available at:" ~/"$CLIENT.ovpn"
|
echo "Client $client added, configuration is available at:" ~/"$client.ovpn"
|
||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
# This option could be documented a bit better and maybe even be simplified
|
# This option could be documented a bit better and maybe even be simplified
|
||||||
# ...but what can I say, I want some sleep too
|
# ...but what can I say, I want some sleep too
|
||||||
NUMBEROFCLIENTS=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -c "^V")
|
number_of_clients=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -c "^V")
|
||||||
if [[ "$NUMBEROFCLIENTS" = '0' ]]; then
|
if [[ "$number_of_clients" = 0 ]]; then
|
||||||
echo
|
echo
|
||||||
echo "You have no existing clients!"
|
echo "You have no existing clients!"
|
||||||
exit
|
exit
|
||||||
@ -109,60 +120,68 @@ if [[ -e /etc/openvpn/server/server.conf ]]; then
|
|||||||
echo
|
echo
|
||||||
echo "Select the existing client certificate you want to revoke:"
|
echo "Select the existing client certificate you want to revoke:"
|
||||||
tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
|
tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
|
||||||
if [[ "$NUMBEROFCLIENTS" = '1' ]]; then
|
read -p "Select one client: " client_number
|
||||||
read -p "Select one client [1]: " CLIENTNUMBER
|
until [[ "$client_number" =~ ^[0-9]+$ && "$client_number" -le "$number_of_clients" ]]; do
|
||||||
else
|
echo "$client_number: invalid selection."
|
||||||
read -p "Select one client [1-$NUMBEROFCLIENTS]: " CLIENTNUMBER
|
read -p "Select one client: " client_number
|
||||||
fi
|
done
|
||||||
CLIENT=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p)
|
client=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$client_number"p)
|
||||||
echo
|
echo
|
||||||
read -p "Do you really want to revoke access for client $CLIENT? [y/N]: " -e REVOKE
|
read -p "Do you really want to revoke access for client $client? [y/N]: " revoke
|
||||||
if [[ "$REVOKE" = 'y' || "$REVOKE" = 'Y' ]]; then
|
until [[ "$revoke" =~ ^[yYnN]*$ ]]; do
|
||||||
|
echo "$revoke: invalid selection."
|
||||||
|
read -p "Do you really want to revoke access for client $client? [y/N]: " revoke
|
||||||
|
done
|
||||||
|
if [[ "$revoke" =~ ^[yY]$ ]]; then
|
||||||
cd /etc/openvpn/server/easy-rsa/
|
cd /etc/openvpn/server/easy-rsa/
|
||||||
./easyrsa --batch revoke $CLIENT
|
./easyrsa --batch revoke "$client"
|
||||||
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
|
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
|
||||||
rm -f pki/reqs/$CLIENT.req
|
rm -f pki/reqs/"$client".req
|
||||||
rm -f pki/private/$CLIENT.key
|
rm -f pki/private/"$client".key
|
||||||
rm -f pki/issued/$CLIENT.crt
|
rm -f pki/issued/"$client".crt
|
||||||
rm -f /etc/openvpn/server/crl.pem
|
rm -f /etc/openvpn/server/crl.pem
|
||||||
cp /etc/openvpn/server/easy-rsa/pki/crl.pem /etc/openvpn/server/crl.pem
|
cp /etc/openvpn/server/easy-rsa/pki/crl.pem /etc/openvpn/server/crl.pem
|
||||||
# CRL is read with each client connection, when OpenVPN is dropped to nobody
|
# CRL is read with each client connection, when OpenVPN is dropped to nobody
|
||||||
chown nobody:$GROUPNAME /etc/openvpn/server/crl.pem
|
chown nobody:"$group_name" /etc/openvpn/server/crl.pem
|
||||||
echo
|
echo
|
||||||
echo "Certificate for client $CLIENT revoked!"
|
echo "Certificate for client $client revoked!"
|
||||||
else
|
else
|
||||||
echo
|
echo
|
||||||
echo "Certificate revocation for client $CLIENT aborted!"
|
echo "Certificate revocation for client $client aborted!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
3)
|
3)
|
||||||
echo
|
echo
|
||||||
read -p "Do you really want to remove OpenVPN? [y/N]: " -e REMOVE
|
read -p "Do you really want to remove OpenVPN? [y/N]: " remove
|
||||||
if [[ "$REMOVE" = 'y' || "$REMOVE" = 'Y' ]]; then
|
until [[ "$remove" =~ ^[yYnN]*$ ]]; do
|
||||||
PORT=$(grep '^port ' /etc/openvpn/server/server.conf | cut -d " " -f 2)
|
echo "$remove: invalid selection."
|
||||||
PROTOCOL=$(grep '^proto ' /etc/openvpn/server/server.conf | cut -d " " -f 2)
|
read -p "Do you really want to remove OpenVPN? [y/N]: " remove
|
||||||
|
done
|
||||||
|
if [[ "$remove" =~ ^[yY]$ ]]; then
|
||||||
|
port=$(grep '^port ' /etc/openvpn/server/server.conf | cut -d " " -f 2)
|
||||||
|
protocol=$(grep '^proto ' /etc/openvpn/server/server.conf | cut -d " " -f 2)
|
||||||
if pgrep firewalld; then
|
if pgrep firewalld; then
|
||||||
IP=$(firewall-cmd --direct --get-rules ipv4 nat POSTROUTING | grep '\-s 10.8.0.0/24 '"'"'!'"'"' -d 10.8.0.0/24 -j SNAT --to ' | cut -d " " -f 10)
|
ip=$(firewall-cmd --direct --get-rules ipv4 nat POSTROUTING | grep '\-s 10.8.0.0/24 '"'"'!'"'"' -d 10.8.0.0/24 -j SNAT --to ' | cut -d " " -f 10)
|
||||||
# Using both permanent and not permanent rules to avoid a firewalld reload.
|
# Using both permanent and not permanent rules to avoid a firewalld reload.
|
||||||
firewall-cmd --remove-port=$PORT/$PROTOCOL
|
firewall-cmd --remove-port="$port"/"$protocol"
|
||||||
firewall-cmd --zone=trusted --remove-source=10.8.0.0/24
|
firewall-cmd --zone=trusted --remove-source=10.8.0.0/24
|
||||||
firewall-cmd --permanent --remove-port=$PORT/$PROTOCOL
|
firewall-cmd --permanent --remove-port="$port"/"$protocol"
|
||||||
firewall-cmd --permanent --zone=trusted --remove-source=10.8.0.0/24
|
firewall-cmd --permanent --zone=trusted --remove-source=10.8.0.0/24
|
||||||
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
|
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"
|
||||||
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
|
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"
|
||||||
else
|
else
|
||||||
systemctl disable --now openvpn-iptables.service
|
systemctl disable --now openvpn-iptables.service
|
||||||
rm -f /etc/systemd/system/openvpn-iptables.service
|
rm -f /etc/systemd/system/openvpn-iptables.service
|
||||||
fi
|
fi
|
||||||
if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$PORT" != '1194' ]]; then
|
if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$port" != 1194 ]]; then
|
||||||
semanage port -d -t openvpn_port_t -p $PROTOCOL $PORT
|
semanage port -d -t openvpn_port_t -p "$protocol" "$port"
|
||||||
fi
|
fi
|
||||||
systemctl disable --now openvpn-server@server.service
|
systemctl disable --now openvpn-server@server.service
|
||||||
rm -rf /etc/openvpn/server
|
rm -rf /etc/openvpn/server
|
||||||
rm -f /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf
|
rm -f /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf
|
||||||
rm -f /etc/sysctl.d/30-openvpn-forward.conf
|
rm -f /etc/sysctl.d/30-openvpn-forward.conf
|
||||||
if [[ "$OS" = 'debian' ]]; then
|
if [[ "$os" = "debian" ]]; then
|
||||||
apt-get remove --purge -y openvpn
|
apt-get remove --purge -y openvpn
|
||||||
else
|
else
|
||||||
yum remove openvpn -y
|
yum remove openvpn -y
|
||||||
@ -180,39 +199,59 @@ if [[ -e /etc/openvpn/server/server.conf ]]; then
|
|||||||
done
|
done
|
||||||
else
|
else
|
||||||
clear
|
clear
|
||||||
echo 'Welcome to this OpenVPN "road warrior" installer!'
|
echo "Welcome to this OpenVPN "road warrior" installer!"
|
||||||
echo
|
echo
|
||||||
# OpenVPN setup and first user creation
|
echo "I need to ask you a few questions before starting setup."
|
||||||
echo "I need to ask you a few questions before starting the setup."
|
echo "You can use the default options and just press enter if you are ok with them."
|
||||||
echo "You can leave the default options and just press enter if you are ok with them."
|
# If system has a single IPv4, it is selected automatically. Else, ask the user
|
||||||
|
if [[ $(ip addr | grep inet | grep -v inet6 | grep -vEc '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') -eq 1 ]]; then
|
||||||
|
ip=$(ip addr | grep inet | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
|
||||||
|
else
|
||||||
|
number_of_ips=$(ip addr | grep inet | grep -v inet6 | grep -vEc '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
|
||||||
echo
|
echo
|
||||||
echo "First, provide the IPv4 address of the network interface you want OpenVPN"
|
echo "What IPv4 address should the OpenVPN server bind to?"
|
||||||
echo "listening to."
|
ip addr | grep inet | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | nl -s ') '
|
||||||
# Autodetect IP address and pre-fill for the user
|
read -p "IPv4 address [1]: " ip_number
|
||||||
IP=$(ip addr | grep 'inet' | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1)
|
until [[ -z "$ip_number" || "$ip_number" =~ ^[0-9]+$ && "$ip_number" -le "$number_of_ips" ]]; do
|
||||||
read -p "IP address: " -e -i $IP IP
|
echo "$ip_number: invalid selection."
|
||||||
|
read -p "IPv4 address [1]: " ip_number
|
||||||
|
done
|
||||||
|
[[ -z "$ip_number" ]] && ip_number="1"
|
||||||
|
ip=$(ip addr | grep inet | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sed -n "$ip_number"p)
|
||||||
|
fi
|
||||||
# If $IP is a private IP address, the server must be behind NAT
|
# If $IP is a private IP address, the server must be behind NAT
|
||||||
if echo "$IP" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168)'; then
|
if echo "$ip" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168)'; then
|
||||||
echo
|
echo
|
||||||
echo "This server is behind NAT. What is the public IPv4 address or hostname?"
|
echo "This server is behind NAT. What is the public IPv4 address or hostname?"
|
||||||
read -p "Public IP address / hostname: " -e PUBLICIP
|
get_public_ip=$(wget -4qO- "http://whatismyip.akamai.com/" || curl -4Ls "http://whatismyip.akamai.com/")
|
||||||
|
read -p "Public IPv4 address / hostname [$get_public_ip]: " public_ip
|
||||||
|
[ -z "$public_ip" ] && public_ip="$get_public_ip"
|
||||||
fi
|
fi
|
||||||
echo
|
echo
|
||||||
echo "Which protocol do you want for OpenVPN connections?"
|
echo "Which protocol do you want for OpenVPN connections?"
|
||||||
echo " 1) UDP (recommended)"
|
echo " 1) UDP (recommended)"
|
||||||
echo " 2) TCP"
|
echo " 2) TCP"
|
||||||
read -p "Protocol [1-2]: " -e -i 1 PROTOCOL
|
read -p "Protocol [1]: " protocol
|
||||||
case $PROTOCOL in
|
until [[ -z "$protocol" || "$protocol" =~ ^[12]$ ]]; do
|
||||||
1)
|
echo "$protocol: invalid selection."
|
||||||
PROTOCOL=udp
|
read -p "Protocol [1]: " protocol
|
||||||
|
done
|
||||||
|
case "$protocol" in
|
||||||
|
1|"")
|
||||||
|
protocol=udp
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
PROTOCOL=tcp
|
protocol=tcp
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
echo
|
echo
|
||||||
echo "What port do you want OpenVPN listening to?"
|
echo "What port do you want OpenVPN listening to?"
|
||||||
read -p "Port: " -e -i 1194 PORT
|
read -p "Port [1194]: " port
|
||||||
|
until [[ -z "$port" || "$port" =~ ^[0-9]+$ && "$port" -le 65535 ]]; do
|
||||||
|
echo "$port: invalid selection."
|
||||||
|
read -p "Port [1194]: " port
|
||||||
|
done
|
||||||
|
[[ -z "$port" ]] && port="1194"
|
||||||
echo
|
echo
|
||||||
echo "Which DNS do you want to use with the VPN?"
|
echo "Which DNS do you want to use with the VPN?"
|
||||||
echo " 1) Current system resolvers"
|
echo " 1) Current system resolvers"
|
||||||
@ -220,21 +259,27 @@ else
|
|||||||
echo " 3) Google"
|
echo " 3) Google"
|
||||||
echo " 4) OpenDNS"
|
echo " 4) OpenDNS"
|
||||||
echo " 5) Verisign"
|
echo " 5) Verisign"
|
||||||
read -p "DNS [1-5]: " -e -i 1 DNS
|
read -p "DNS [1]: " dns
|
||||||
|
until [[ -z "$dns" || "$dns" =~ ^[1-5]$ ]]; do
|
||||||
|
echo "$dns: invalid selection."
|
||||||
|
read -p "DNS [1]: " dns
|
||||||
|
done
|
||||||
echo
|
echo
|
||||||
echo "Finally, tell me your name for the client certificate."
|
echo "Finally, tell me a name for the client certificate."
|
||||||
echo "Please, use one word only, no special characters."
|
read -p "Client name [client]: " unsanitized_client
|
||||||
read -p "Client name: " -e -i client CLIENT
|
# Allow a limited set of characters to avoid conflicts
|
||||||
|
client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
|
||||||
|
[[ -z "$client" ]] && client="client"
|
||||||
echo
|
echo
|
||||||
echo "Okay, that was all I needed. We are ready to set up your OpenVPN server now."
|
echo "Okay, that was all I needed. We are ready to set up your OpenVPN server now."
|
||||||
read -n1 -r -p "Press any key to continue..."
|
read -n1 -r -p "Press any key to continue..."
|
||||||
# If running inside a container, disable LimitNPROC to prevent conflicts
|
# If running inside a container, disable LimitNPROC to prevent conflicts
|
||||||
if systemd-detect-virt -cq; then
|
if systemd-detect-virt -cq; then
|
||||||
mkdir /etc/systemd/system/openvpn-server@server.service.d/ 2>/dev/null
|
mkdir /etc/systemd/system/openvpn-server@server.service.d/ 2>/dev/null
|
||||||
echo '[Service]
|
echo "[Service]
|
||||||
LimitNPROC=infinity' > /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf
|
LimitNPROC=infinity" > /etc/systemd/system/openvpn-server@server.service.d/disable-limitnproc.conf
|
||||||
fi
|
fi
|
||||||
if [[ "$OS" = 'debian' ]]; then
|
if [[ "$os" = "debian" ]]; then
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install openvpn iptables openssl ca-certificates -y
|
apt-get install openvpn iptables openssl ca-certificates -y
|
||||||
else
|
else
|
||||||
@ -243,8 +288,8 @@ LimitNPROC=infinity' > /etc/systemd/system/openvpn-server@server.service.d/disab
|
|||||||
yum install openvpn iptables openssl ca-certificates -y
|
yum install openvpn iptables openssl ca-certificates -y
|
||||||
fi
|
fi
|
||||||
# Get easy-rsa
|
# Get easy-rsa
|
||||||
EASYRSAURL='https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.5/EasyRSA-nix-3.0.5.tgz'
|
easy_rsa_url='https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.5/EasyRSA-nix-3.0.5.tgz'
|
||||||
wget -O ~/easyrsa.tgz "$EASYRSAURL" 2>/dev/null || curl -Lo ~/easyrsa.tgz "$EASYRSAURL"
|
wget -O ~/easyrsa.tgz "$easy_rsa_url" 2>/dev/null || curl -Lo ~/easyrsa.tgz "$easy_rsa_url"
|
||||||
tar xzf ~/easyrsa.tgz -C ~/
|
tar xzf ~/easyrsa.tgz -C ~/
|
||||||
mv ~/EasyRSA-3.0.5/ /etc/openvpn/server/
|
mv ~/EasyRSA-3.0.5/ /etc/openvpn/server/
|
||||||
mv /etc/openvpn/server/EasyRSA-3.0.5/ /etc/openvpn/server/easy-rsa/
|
mv /etc/openvpn/server/EasyRSA-3.0.5/ /etc/openvpn/server/easy-rsa/
|
||||||
@ -255,14 +300,14 @@ LimitNPROC=infinity' > /etc/systemd/system/openvpn-server@server.service.d/disab
|
|||||||
./easyrsa init-pki
|
./easyrsa init-pki
|
||||||
./easyrsa --batch build-ca nopass
|
./easyrsa --batch build-ca nopass
|
||||||
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-server-full server nopass
|
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-server-full server nopass
|
||||||
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full $CLIENT nopass
|
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full "$client" nopass
|
||||||
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
|
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
|
||||||
# Move the stuff we need
|
# Move the stuff we need
|
||||||
cp pki/ca.crt pki/private/ca.key pki/issued/server.crt pki/private/server.key pki/crl.pem /etc/openvpn/server
|
cp pki/ca.crt pki/private/ca.key pki/issued/server.crt pki/private/server.key pki/crl.pem /etc/openvpn/server
|
||||||
# CRL is read with each client connection, when OpenVPN is dropped to nobody
|
# CRL is read with each client connection, when OpenVPN is dropped to nobody
|
||||||
chown nobody:$GROUPNAME /etc/openvpn/server/crl.pem
|
chown nobody:"$group_name" /etc/openvpn/server/crl.pem
|
||||||
# Generate key for tls-auth
|
# Generate key for tls-crypt
|
||||||
openvpn --genkey --secret /etc/openvpn/server/ta.key
|
openvpn --genkey --secret /etc/openvpn/server/tc.key
|
||||||
# Create the DH parameters file using the predefined ffdhe2048 group
|
# Create the DH parameters file using the predefined ffdhe2048 group
|
||||||
echo '-----BEGIN DH PARAMETERS-----
|
echo '-----BEGIN DH PARAMETERS-----
|
||||||
MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
|
MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
|
||||||
@ -273,33 +318,32 @@ YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
|
|||||||
ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
|
ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
|
||||||
-----END DH PARAMETERS-----' > /etc/openvpn/server/dh.pem
|
-----END DH PARAMETERS-----' > /etc/openvpn/server/dh.pem
|
||||||
# Generate server.conf
|
# Generate server.conf
|
||||||
echo "port $PORT
|
echo "local $ip
|
||||||
proto $PROTOCOL
|
port $port
|
||||||
|
proto $protocol
|
||||||
dev tun
|
dev tun
|
||||||
sndbuf 0
|
|
||||||
rcvbuf 0
|
|
||||||
ca ca.crt
|
ca ca.crt
|
||||||
cert server.crt
|
cert server.crt
|
||||||
key server.key
|
key server.key
|
||||||
dh dh.pem
|
dh dh.pem
|
||||||
auth SHA512
|
auth SHA512
|
||||||
tls-auth ta.key 0
|
tls-crypt tc.key
|
||||||
topology subnet
|
topology subnet
|
||||||
server 10.8.0.0 255.255.255.0
|
server 10.8.0.0 255.255.255.0
|
||||||
ifconfig-pool-persist ipp.txt" > /etc/openvpn/server/server.conf
|
ifconfig-pool-persist ipp.txt" > /etc/openvpn/server/server.conf
|
||||||
echo 'push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server/server.conf
|
echo 'push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server/server.conf
|
||||||
# DNS
|
# DNS
|
||||||
case $DNS in
|
case "$dns" in
|
||||||
1)
|
1|"")
|
||||||
# Locate the proper resolv.conf
|
# Locate the proper resolv.conf
|
||||||
# Needed for systems running systemd-resolved
|
# Needed for systems running systemd-resolved
|
||||||
if grep -q "127.0.0.53" "/etc/resolv.conf"; then
|
if grep -q "127.0.0.53" "/etc/resolv.conf"; then
|
||||||
RESOLVCONF='/run/systemd/resolve/resolv.conf'
|
resolv_conf="/run/systemd/resolve/resolv.conf"
|
||||||
else
|
else
|
||||||
RESOLVCONF='/etc/resolv.conf'
|
resolv_conf="/etc/resolv.conf"
|
||||||
fi
|
fi
|
||||||
# Obtain the resolvers from resolv.conf and use them for OpenVPN
|
# Obtain the resolvers from resolv.conf and use them for OpenVPN
|
||||||
grep -v '#' $RESOLVCONF | grep 'nameserver' | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | while read line; do
|
grep -v '#' "$resolv_conf" | grep nameserver | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | while read line; do
|
||||||
echo "push \"dhcp-option DNS $line\"" >> /etc/openvpn/server/server.conf
|
echo "push \"dhcp-option DNS $line\"" >> /etc/openvpn/server/server.conf
|
||||||
done
|
done
|
||||||
;;
|
;;
|
||||||
@ -323,12 +367,15 @@ ifconfig-pool-persist ipp.txt" > /etc/openvpn/server/server.conf
|
|||||||
echo "keepalive 10 120
|
echo "keepalive 10 120
|
||||||
cipher AES-256-CBC
|
cipher AES-256-CBC
|
||||||
user nobody
|
user nobody
|
||||||
group $GROUPNAME
|
group $group_name
|
||||||
persist-key
|
persist-key
|
||||||
persist-tun
|
persist-tun
|
||||||
status openvpn-status.log
|
status openvpn-status.log
|
||||||
verb 3
|
verb 3
|
||||||
crl-verify crl.pem" >> /etc/openvpn/server/server.conf
|
crl-verify crl.pem" >> /etc/openvpn/server/server.conf
|
||||||
|
if [[ "$protocol" = "udp" ]]; then
|
||||||
|
echo "explicit-exit-notify" >> /etc/openvpn/server/server.conf
|
||||||
|
fi
|
||||||
# Enable net.ipv4.ip_forward for the system
|
# Enable net.ipv4.ip_forward for the system
|
||||||
echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/30-openvpn-forward.conf
|
echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/30-openvpn-forward.conf
|
||||||
# Enable without waiting for a reboot or service restart
|
# Enable without waiting for a reboot or service restart
|
||||||
@ -338,25 +385,25 @@ crl-verify crl.pem" >> /etc/openvpn/server/server.conf
|
|||||||
# reload.
|
# reload.
|
||||||
# We don't use --add-service=openvpn because that would only work with
|
# We don't use --add-service=openvpn because that would only work with
|
||||||
# the default port and protocol.
|
# the default port and protocol.
|
||||||
firewall-cmd --add-port=$PORT/$PROTOCOL
|
firewall-cmd --add-port="$port"/"$protocol"
|
||||||
firewall-cmd --zone=trusted --add-source=10.8.0.0/24
|
firewall-cmd --zone=trusted --add-source=10.8.0.0/24
|
||||||
firewall-cmd --permanent --add-port=$PORT/$PROTOCOL
|
firewall-cmd --permanent --add-port="$port"/"$protocol"
|
||||||
firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24
|
firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24
|
||||||
# Set NAT for the VPN subnet
|
# Set NAT for the VPN subnet
|
||||||
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
|
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"
|
||||||
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
|
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"
|
||||||
else
|
else
|
||||||
# Create a service to set up persistent iptables rules
|
# Create a service to set up persistent iptables rules
|
||||||
echo "[Unit]
|
echo "[Unit]
|
||||||
Before=network.target
|
Before=network.target
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
ExecStart=/sbin/iptables -t nat -A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP
|
ExecStart=/sbin/iptables -t nat -A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $ip
|
||||||
ExecStart=/sbin/iptables -I INPUT -p $PROTOCOL --dport $PORT -j ACCEPT
|
ExecStart=/sbin/iptables -I INPUT -p $protocol --dport $port -j ACCEPT
|
||||||
ExecStart=/sbin/iptables -I FORWARD -s 10.8.0.0/24 -j ACCEPT
|
ExecStart=/sbin/iptables -I FORWARD -s 10.8.0.0/24 -j ACCEPT
|
||||||
ExecStart=/sbin/iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
|
ExecStart=/sbin/iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||||
ExecStop=/sbin/iptables -t nat -D POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP
|
ExecStop=/sbin/iptables -t nat -D POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $ip
|
||||||
ExecStop=/sbin/iptables -D INPUT -p $PROTOCOL --dport $PORT -j ACCEPT
|
ExecStop=/sbin/iptables -D INPUT -p $protocol --dport $port -j ACCEPT
|
||||||
ExecStop=/sbin/iptables -D FORWARD -s 10.8.0.0/24 -j ACCEPT
|
ExecStop=/sbin/iptables -D FORWARD -s 10.8.0.0/24 -j ACCEPT
|
||||||
ExecStop=/sbin/iptables -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
|
ExecStop=/sbin/iptables -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||||
RemainAfterExit=yes
|
RemainAfterExit=yes
|
||||||
@ -365,7 +412,7 @@ WantedBy=multi-user.target" > /etc/systemd/system/openvpn-iptables.service
|
|||||||
systemctl enable --now openvpn-iptables.service
|
systemctl enable --now openvpn-iptables.service
|
||||||
fi
|
fi
|
||||||
# If SELinux is enabled and a custom port was selected, we need this
|
# If SELinux is enabled and a custom port was selected, we need this
|
||||||
if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$PORT" != '1194' ]]; then
|
if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$port" != 1194 ]]; then
|
||||||
# Install semanage if not already present
|
# Install semanage if not already present
|
||||||
if ! hash semanage 2>/dev/null; then
|
if ! hash semanage 2>/dev/null; then
|
||||||
if grep -qs "CentOS Linux release 7" "/etc/centos-release"; then
|
if grep -qs "CentOS Linux release 7" "/etc/centos-release"; then
|
||||||
@ -374,21 +421,17 @@ WantedBy=multi-user.target" > /etc/systemd/system/openvpn-iptables.service
|
|||||||
yum install policycoreutils-python-utils -y
|
yum install policycoreutils-python-utils -y
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
semanage port -a -t openvpn_port_t -p $PROTOCOL $PORT
|
semanage port -a -t openvpn_port_t -p "$protocol" "$port"
|
||||||
fi
|
fi
|
||||||
# And finally, enable and start the OpenVPN service
|
|
||||||
systemctl enable --now openvpn-server@server.service
|
|
||||||
# If the server is behind a NAT, use the correct IP address
|
# If the server is behind a NAT, use the correct IP address
|
||||||
if [[ "$PUBLICIP" != "" ]]; then
|
if [[ "$public_ip" != "" ]]; then
|
||||||
IP=$PUBLICIP
|
ip="$public_ip"
|
||||||
fi
|
fi
|
||||||
# client-common.txt is created so we have a template to add further users later
|
# client-common.txt is created so we have a template to add further users later
|
||||||
echo "client
|
echo "client
|
||||||
dev tun
|
dev tun
|
||||||
proto $PROTOCOL
|
proto $protocol
|
||||||
sndbuf 0
|
remote $ip $port
|
||||||
rcvbuf 0
|
|
||||||
remote $IP $PORT
|
|
||||||
resolv-retry infinite
|
resolv-retry infinite
|
||||||
nobind
|
nobind
|
||||||
persist-key
|
persist-key
|
||||||
@ -396,14 +439,16 @@ persist-tun
|
|||||||
remote-cert-tls server
|
remote-cert-tls server
|
||||||
auth SHA512
|
auth SHA512
|
||||||
cipher AES-256-CBC
|
cipher AES-256-CBC
|
||||||
setenv opt block-outside-dns
|
ignore-unknown-option block-outside-dns
|
||||||
key-direction 1
|
block-outside-dns
|
||||||
verb 3" > /etc/openvpn/server/client-common.txt
|
verb 3" > /etc/openvpn/server/client-common.txt
|
||||||
|
# Enable and start the OpenVPN service
|
||||||
|
systemctl enable --now openvpn-server@server.service
|
||||||
# Generates the custom client.ovpn
|
# Generates the custom client.ovpn
|
||||||
newclient "$CLIENT"
|
new_client "$client"
|
||||||
echo
|
echo
|
||||||
echo "Finished!"
|
echo "Finished!"
|
||||||
echo
|
echo
|
||||||
echo "Your client configuration is available at:" ~/"$CLIENT.ovpn"
|
echo "Your client configuration is available at:" ~/"$client.ovpn"
|
||||||
echo "If you want to add more clients, you simply need to run this script again!"
|
echo "If you want to add more clients, just run this script again!"
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user