Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#!/bin/bash
# Very secure OpenVPN server installer for CentOS
if [[ "$EUID" -ne 0 ]]; then
echo "Sorry, you need to run this as root"
exit 1
fi
if [[ ! -e /dev/net/tun ]]; then
echo "TUN is not available"
exit 2
fi
if [[ -e /etc/centos-release ]]; then
OS=centos
RCLOCAL='/etc/rc.d/rc.local'
SYSCTL='/etc/sysctl.conf'
# Needed for CentOS 7
chmod +x /etc/rc.d/rc.local
else
echo "Looks like you aren't running this installer on a CentOS system"
exit 4
fi
newclient () {
# Where to write the custom client.ovpn?
if [ -e /home/$1 ]; then # if $1 is a user name
homeDir="/home/$1"
elif [ ${SUDO_USER} ]; then # if not, use SUDO_USER
homeDir="/home/${SUDO_USER}"
else # if not SUDO_USER, use /root
homeDir="/root"
fi
# Generates the custom client.ovpn
cp /etc/openvpn/client-template.txt $homeDir/$1.ovpn
echo "<ca>" >> $homeDir/$1.ovpn
cat /etc/openvpn/easy-rsa/keys/ca.crt >> $homeDir/$1.ovpn
echo "</ca>" >> $homeDir/$1.ovpn
echo "<cert>" >> $homeDir/$1.ovpn
cat /etc/openvpn/easy-rsa/keys/$1.crt >> $homeDir/$1.ovpn
echo "</cert>" >> $homeDir/$1.ovpn
echo "<key>" >> $homeDir/$1.ovpn
cat /etc/openvpn/easy-rsa/keys/$1.key >> $homeDir/$1.ovpn
echo "</key>" >> $homeDir/$1.ovpn
echo "key-direction 1" >> $homeDir/$1.ovpn
echo "<tls-auth>" >> $homeDir/$1.ovpn
cat /etc/openvpn/tls-auth.key >> $homeDir/$1.ovpn
echo "</tls-auth>" >> $homeDir/$1.ovpn
}
# Try to get our IP from the system and fallback to the Internet.
# I do this to make the script compatible with NATed servers (LowEndSpirit/Scaleway)
# and to avoid getting an IPv6.
IP=$(ip addr | grep 'inet' | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -o -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1)
if [[ "$IP" = "" ]]; then
IP=$(curl -s https://api.ipify.org)
fi
# Get Internet network interface with default route
NIC=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)')
if [[ -e /etc/openvpn/server.conf ]]; then
while :
do
clear
echo "OpenVPN-install (github.com/Angristan/OpenVPN-install)"
echo ""
echo "Looks like OpenVPN is already installed"
echo ""
echo "What do you want to do?"
echo " 1) Add a cert for a new user"
echo " 2) Revoke existing user cert"
echo " 3) Exit"
read -p "Select an option [1-3]: " option
case $option in
1)
echo ""
echo "Tell me a name for the client cert"
echo "Please, use one word only, no special characters"
read -p "Client name: " -e -i client CLIENT
{
cd /etc/openvpn/easy-rsa/
source ./vars
./build-key --batch $CLIENT
newclient "$CLIENT"
} &> /dev/null
echo ""
echo "Client $CLIENT added, certs available at $homeDir/$CLIENT.ovpn"
exit
;;
2)
NUMBEROFCLIENTS=$(tail -n +2 /etc/openvpn/easy-rsa/keys/index.txt | grep -c "^V")
if [[ "$NUMBEROFCLIENTS" = '0' ]]; then
echo ""
echo "You have no existing clients!"
exit 5
fi
echo ""
echo "Select the existing client certificate you want to revoke"
tail -n +2 /etc/openvpn/easy-rsa/keys/index.txt | grep "^V" | cut -d '=' -f 7 | cut -f1 -d"/" | nl -s ') '
if [[ "$NUMBEROFCLIENTS" = '1' ]]; then
read -p "Select one client [1]: " CLIENTNUMBER
else
read -p "Select one client [1-$NUMBEROFCLIENTS]: " CLIENTNUMBER
fi
{
CLIENT=$(tail -n +2 /etc/openvpn/easy-rsa/keys/index.txt | grep "^V" | cut -d '=' -f 7 | cut -f1 -d"/" | sed -n "$CLIENTNUMBER"P )
cd /etc/openvpn/easy-rsa/
./revoke-full $CLIENT
rm -rf keys/$CLIENT.key
rm -rf keys/$CLIENT.crt
rm -rf /etc/openvpn/crl.pem
cp /etc/openvpn/easy-rsa/keys/crl.pem /etc/openvpn/crl.pem
chmod 644 /etc/openvpn/crl.pem
} &> /dev/null
echo ""
echo "Certificate for client $CLIENT revoked"
echo "Exiting..."
exit
;;
3) exit;;
esac
done
else
clear
echo "Welcome to the secure OpenVPN installer"
echo ""
# OpenVPN setup and first user creation
echo "I need to ask you a few questions before starting the setup"
echo "You can leave the default options and just press enter if you are ok with them"
echo ""
echo "I need to know the IPv4 address of the network interface you want OpenVPN listening to."
echo "If your server is running behind a NAT, (e.g. LowEndSpirit, Scaleway) leave the IP address as it is. (local/private IP)"
echo "Otherwise, it should be your public IPv4 address."
read -p "IP address: " -e -i $IP IP
echo ""
echo "What port do you want for OpenVPN?"
read -p "Port: " -e -i 1194 PORT
echo ""
echo "What protocol do you want for OpenVPN?"
echo "Unless UDP is blocked, you should not use TCP (unnecessarily slower)"
while [[ $PROTOCOL != "UDP" && $PROTOCOL != "TCP" ]]; do
read -p "Protocol [UDP/TCP]: " -e -i UDP PROTOCOL
done
echo ""
echo "What DNS do you want to use with the VPN?"
echo " 1) Current system resolvers (in /etc/resolv.conf)"
echo " 2) DNS.WATCH (Germany)"
echo " 3) OpenDNS (Anycast: worldwide)"
echo " 4) Custom (Specify Later)"
while [[ $DNS != "1" && $DNS != "2" && $DNS != "3" && $DNS != "4" ]]; do
read -p "DNS [1-4]: " -e -i 1 DNS
done
if [[ $DNS = "4" ]]; then
echo ""
echo "Please specify custom DNS:"
read -p "Custom DNS 1: " -e DNS1
read -p "Custom DNS 2: " -e DNS2
fi
CIPHER="cipher AES-256-CBC"
DH_KEY_SIZE="4096"
RSA_KEY_SIZE="4096"
echo ""
echo "Which infos do you want i use for certificates?"
read -p "Country Code: " -e -i CC COUNTRY
read -p "Province: " -e -i "Your Province" PROVINCE
read -p "City: " -e -i YourCity CITY
read -p "Organization: " -e -i YourOrg ORG
read -p "Email: " -e -i ca@yourorg.org EMAIL
read -p "Organizational Unit: " -e -i "Security Team" OU
read -p "Key Name: " -e -i server KEYNAME
echo ""
echo "Finally, tell me a name for the client certificate and configuration"
while [[ $CLIENT = "" ]]; do
echo "Please, use one word only, no special characters"
read -p "Client name: " -e -i client CLIENT
done
echo ""
echo "Okay, that was all I needed. We are ready to setup your OpenVPN server now"
read -n1 -r -p "Press any key to continue..."
# Install packages
yum install epel-release -y
yum install openvpn easy-rsa openssl wget ca-certificates curl -y
# Find out if the machine uses nogroup or nobody for the permissionless group
if grep -qs "^nogroup:" /etc/group; then
NOGROUP=nogroup
else
NOGROUP=nobody
fi
mkdir /etc/openvpn/easy-rsa
cp -rf /usr/share/easy-rsa/2.0/* /etc/openvpn/easy-rsa
cd /etc/openvpn/easy-rsa
rm -f vars
echo "
export EASY_RSA=\"\`pwd\`\"
export OPENSSL=\"openssl\"
export PKCS11TOOL=\"pkcs11-tool\"
export GREP=\"grep\"
export KEY_CONFIG=\"\`\$EASY_RSA/whichopensslcnf \$EASY_RSA\`\"
export KEY_DIR=\"\$EASY_RSA/keys\"
export PKCS11_MODULE_PATH=\"dummy\"
export PKCS11_PIN=\"dummy\"
export KEY_SIZE=$RSA_KEY_SIZE
export CA_EXPIRE=3650
export KEY_EXPIRE=3650
export KEY_COUNTRY=\"$COUNTRY\"
export KEY_PROVINCE=\"$PROVINCE\"
export KEY_CITY=\"$CITY\"
export KEY_ORG=\"$ORG\"
export KEY_EMAIL=\"$EMAIL\"
export KEY_OU=\"$OU\"
export KEY_NAME=\"$KEYNAME\"
" >> /etc/openvpn/easy-rsa/vars
source ./vars
./clean-all
./build-ca --batch
./build-key-server --batch server
./build-dh --batch
{
./build-key --batch autorevoked
./revoke-full autorevoked
} &> /dev/null
rm -rf keys/autorevoked.key
rm -rf keys/autorevoked.crt
./build-key --batch $CLIENT
# generate tls-auth key
openvpn --genkey --secret /etc/openvpn/tls-auth.key
# Move all the generated files
cd /etc/openvpn/easy-rsa/keys
cp dh$RSA_KEY_SIZE.pem ca.crt server.crt server.key crl.pem /etc/openvpn
# Make cert revocation list readable for non-root
chmod 644 /etc/openvpn/crl.pem
# Generate server.conf
echo "port $PORT" > /etc/openvpn/server.conf
if [[ "$PROTOCOL" = 'UDP' ]]; then
echo "proto udp" >> /etc/openvpn/server.conf
elif [[ "$PROTOCOL" = 'TCP' ]]; then
echo "proto tcp" >> /etc/openvpn/server.conf
fi
echo "dev tun
user nobody
group $NOGROUP
persist-key
persist-tun
keepalive 10 120
topology subnet
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt" >> /etc/openvpn/server.conf
# DNS resolvers
case $DNS in
1)
# Obtain the resolvers from resolv.conf and use them for OpenVPN
grep -v '#' /etc/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.conf
done
;;
2) #DNS.WATCH
echo 'push "dhcp-option DNS 84.200.69.80"' >> /etc/openvpn/server.conf
echo 'push "dhcp-option DNS 84.200.70.40"' >> /etc/openvpn/server.conf
;;
3) #OpenDNS
echo 'push "dhcp-option DNS 208.67.222.222"' >> /etc/openvpn/server.conf
echo 'push "dhcp-option DNS 208.67.220.220"' >> /etc/openvpn/server.conf
;;
4) #Custom
echo "push \"dhcp-option DNS $DNS1\"" >> /etc/openvpn/server.conf
if [[ $DNS2 != "" ]]; then
echo "push \"dhcp-option DNS $DNS2\"" >> /etc/openvpn/server.conf
fi
;;
esac
echo 'push "redirect-gateway def1 bypass-dhcp" '>> /etc/openvpn/server.conf
echo "crl-verify crl.pem
ca ca.crt
cert server.crt
key server.key
tls-auth tls-auth.key 0
dh dh$RSA_KEY_SIZE.pem
auth SHA256
$CIPHER
tls-server
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384
status openvpn.log
verb 4" >> /etc/openvpn/server.conf
# Create the sysctl configuration file if needed (mainly for Arch Linux)
if [[ ! -e $SYSCTL ]]; then
touch $SYSCTL
fi
# Enable net.ipv4.ip_forward for the system
sed -i '/\<net.ipv4.ip_forward\>/c\net.ipv4.ip_forward=1' $SYSCTL
if ! grep -q "\<net.ipv4.ip_forward\>" $SYSCTL; then
echo 'net.ipv4.ip_forward=1' >> $SYSCTL
fi
# Avoid an unneeded reboot
echo 1 > /proc/sys/net/ipv4/ip_forward
chmod +x $RCLOCAL
# Set NAT for the VPN subnet
if firewall-cmd --state | grep "running"; then
systemctl unmask firewalld
systemctl enable firewalld
systemctl start firewalld
fi
if [[ "$PROTOCOL" = 'UDP' && "$PORT" = '1194' ]]; then
firewall-cmd --permanent --zone=public --add-service=openvpn
elif [[ "$PROTOCOL" = 'UDP' && "$PORT" != '1194' ]]; then
firewall-cmd --permanent --zone=public --add-port=$PORT/udp
elif [[ "$PROTOCOL" = 'TCP' ]]; then
firewall-cmd --permanent --zone=public --add-port=$PORT/tcp
fi
firewall-cmd --permanent --zone=public --add-masquerade
firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24
firewall-cmd --reload
# If SELinux is enabled and a custom port was selected, we need this
if hash sestatus 2>/dev/null; then
if sestatus | grep "Current mode" | grep -qs "enforcing"; then
if [[ "$PORT" != '1194' ]]; then
# semanage isn't available in CentOS 6 by default
if ! hash semanage 2>/dev/null; then
yum install policycoreutils-python -y
fi
if [[ "$PROTOCOL" = 'UDP' ]]; then
semanage port -a -t openvpn_port_t -p udp $PORT
elif [[ "$PROTOCOL" = 'TCP' ]]; then
semanage port -a -t openvpn_port_t -p tcp $PORT
fi
fi
fi
fi
# And finally, restart OpenVPN
if pgrep systemd-journal; then
systemctl restart openvpn@server.service
systemctl enable openvpn@server.service
else
service openvpn restart
chkconfig openvpn on
fi
# Try to detect a NATed connection and ask about it to potential LowEndSpirit/Scaleway users
EXTERNALIP=$(curl -s https://api.ipify.org)
if [[ "$IP" != "$EXTERNALIP" ]]; then
echo ""
echo "Looks like your server is behind a NAT!"
echo ""
echo "If your server is NATed I need to know the address that can be used to access it from outside."
echo "If that's not the case, just ignore this and leave the next field blank"
read -p "External IP or domain name: " -e USEREXTERNALIP
if [[ "$USEREXTERNALIP" != "" ]]; then
IP=$USEREXTERNALIP
fi
fi
# client-template.txt is created so we have a template to add further users later
echo "client" > /etc/openvpn/client-template.txt
if [[ "$PROTOCOL" = 'UDP' ]]; then
echo "proto udp" >> /etc/openvpn/client-template.txt
elif [[ "$PROTOCOL" = 'TCP' ]]; then
echo "proto tcp-client" >> /etc/openvpn/client-template.txt
fi
echo "remote $IP $PORT
dev tun
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
auth SHA256
$CIPHER
tls-client
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384
setenv opt block-outside-dns
verb 3" >> /etc/openvpn/client-template.txt
# Generate the custom client.ovpn
newclient "$CLIENT"
echo ""
echo "Finished!"
echo ""
echo "Your client config is available at $homeDir/$CLIENT.ovpn"
echo "If you want to add more clients, you simply have to run this script another time!"
fi
exit 0;
@phonicmouse
Copy link
Author

A bash script to install and manage a very secure OpenVPN installation on a CentOS system.

Based on the work of @angristan (openvpn-install.sh) and tuned by @phonicmouse.

@phonicmouse
Copy link
Author

phonicmouse commented Aug 20, 2017

Upcoming features:

  • IPv6 Support
  • Bind Installer
  • Multi Port Support (Multi Server)
  • GitHub Repository

For more info follow this link: https://git.piratenet.work/phonicmouse/OpenVPN-Manager

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment