Created
July 1, 2019 14:03
-
-
Save kageru/dfdc0c35447b5987a1ef19434f51d74b to your computer and use it in GitHub Desktop.
Arch port of https://github.com/Nyr/openvpn-install
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# Original: https://github.com/Nyr/openvpn-install | |
# | |
# Copyright (c) 2013 Nyr. Released under the MIT License. | |
# Minor changes by kageru to make the script run on Arch. | |
if [[ "$EUID" -ne 0 ]]; then | |
echo "Sorry, you need to run this as root" | |
exit | |
fi | |
if [[ ! -e /dev/net/tun ]]; then | |
echo "The TUN device is not available | |
You need to enable TUN before running this script" | |
exit | |
fi | |
newclient () { | |
# Generates the custom client.ovpn | |
cp /etc/openvpn/server/client-common.txt ~/$1.ovpn | |
echo "<ca>" >> ~/$1.ovpn | |
cat /etc/openvpn/server/easy-rsa/pki/ca.crt >> ~/$1.ovpn | |
echo "</ca>" >> ~/$1.ovpn | |
echo "<cert>" >> ~/$1.ovpn | |
sed -ne '/BEGIN CERTIFICATE/,$ p' /etc/openvpn/server/easy-rsa/pki/issued/$1.crt >> ~/$1.ovpn | |
echo "</cert>" >> ~/$1.ovpn | |
echo "<key>" >> ~/$1.ovpn | |
cat /etc/openvpn/server/easy-rsa/pki/private/$1.key >> ~/$1.ovpn | |
echo "</key>" >> ~/$1.ovpn | |
echo "<tls-auth>" >> ~/$1.ovpn | |
sed -ne '/BEGIN OpenVPN Static key/,$ p' /etc/openvpn/server/ta.key >> ~/$1.ovpn | |
echo "</tls-auth>" >> ~/$1.ovpn | |
} | |
if [[ -e /etc/openvpn/server/server.conf ]]; then | |
while : | |
do | |
clear | |
echo "Looks like OpenVPN is already installed." | |
echo | |
echo "What do you want to do?" | |
echo " 1) Add a new user" | |
echo " 2) Revoke an existing user" | |
echo " 3) Remove OpenVPN" | |
echo " 4) Exit" | |
read -p "Select an option [1-4]: " option | |
case $option in | |
1) | |
echo | |
echo "Tell me a name for the client certificate." | |
echo "Please, use one word only, no special characters." | |
read -p "Client name: " -e CLIENT | |
cd /etc/openvpn/server/easy-rsa/ | |
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full $CLIENT nopass | |
# Generates the custom client.ovpn | |
newclient "$CLIENT" | |
echo | |
echo "Client $CLIENT added, configuration is available at:" ~/"$CLIENT.ovpn" | |
exit | |
;; | |
2) | |
# This option could be documented a bit better and maybe even be simplified | |
# ...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") | |
if [[ "$NUMBEROFCLIENTS" = '0' ]]; then | |
echo | |
echo "You have no existing clients!" | |
exit | |
fi | |
echo | |
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 ') ' | |
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/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p) | |
echo | |
read -p "Do you really want to revoke access for client $CLIENT? [y/N]: " -e REVOKE | |
if [[ "$REVOKE" = 'y' || "$REVOKE" = 'Y' ]]; then | |
cd /etc/openvpn/server/easy-rsa/ | |
./easyrsa --batch revoke $CLIENT | |
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl | |
rm -f pki/reqs/$CLIENT.req | |
rm -f pki/private/$CLIENT.key | |
rm -f pki/issued/$CLIENT.crt | |
rm -f /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 | |
chown nobody:nobody /etc/openvpn/server/crl.pem | |
echo | |
echo "Certificate for client $CLIENT revoked!" | |
else | |
echo | |
echo "Certificate revocation for client $CLIENT aborted!" | |
fi | |
exit | |
;; | |
3) | |
echo | |
read -p "Do you really want to remove OpenVPN? [y/N]: " -e REMOVE | |
if [[ "$REMOVE" = 'y' || "$REMOVE" = 'Y' ]]; 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 | |
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. | |
firewall-cmd --remove-port=$PORT/$PROTOCOL | |
firewall-cmd --zone=trusted --remove-source=10.8.0.0/24 | |
firewall-cmd --permanent --remove-port=$PORT/$PROTOCOL | |
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 --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 | |
systemctl disable --now openvpn-iptables.service | |
rm -f /etc/systemd/system/openvpn-iptables.service | |
fi | |
if sestatus 2>/dev/null | grep "Current mode" | grep -q "enforcing" && [[ "$PORT" != '1194' ]]; then | |
semanage port -d -t openvpn_port_t -p $PROTOCOL $PORT | |
fi | |
systemctl disable --now [email protected] | |
rm -rf /etc/openvpn/server | |
rm -f /etc/sysctl.d/30-openvpn-forward.conf | |
echo | |
echo "OpenVPN removed!" | |
else | |
echo | |
echo "Removal aborted!" | |
fi | |
exit | |
;; | |
4) exit;; | |
esac | |
done | |
else | |
clear | |
echo 'Welcome to this OpenVPN "road warrior" 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 "First, provide the IPv4 address of the network interface you want OpenVPN" | |
echo "listening to." | |
# Autodetect IP address and pre-fill for the user | |
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) | |
read -p "IP address: " -e -i $IP IP | |
# 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 | |
echo | |
echo "This server is behind NAT. What is the public IPv4 address or hostname?" | |
read -p "Public IP address / hostname: " -e PUBLICIP | |
fi | |
echo | |
echo "Which protocol do you want for OpenVPN connections?" | |
echo " 1) UDP (recommended)" | |
echo " 2) TCP" | |
read -p "Protocol [1-2]: " -e -i 1 PROTOCOL | |
case $PROTOCOL in | |
1) | |
PROTOCOL=udp | |
;; | |
2) | |
PROTOCOL=tcp | |
;; | |
esac | |
echo | |
echo "What port do you want OpenVPN listening to?" | |
read -p "Port: " -e -i 1194 PORT | |
echo | |
echo "Which DNS do you want to use with the VPN?" | |
echo " 1) Current system resolvers" | |
echo " 2) 1.1.1.1" | |
echo " 3) Google" | |
echo " 4) OpenDNS" | |
echo " 5) Verisign" | |
read -p "DNS [1-5]: " -e -i 1 DNS | |
echo | |
echo "Finally, tell me your name for the client certificate." | |
echo "Please, use one word only, no special characters." | |
read -p "Client name: " -e -i client CLIENT | |
echo | |
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..." | |
pacman -S openvpn iptables openssl ca-certificates --noconfirm | |
# Get easy-rsa | |
EASYRSAURL='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" | |
tar xzf ~/easyrsa.tgz -C ~/ | |
mv ~/EasyRSA-3.0.5/ /etc/openvpn/server/ | |
mv /etc/openvpn/server/EasyRSA-3.0.5/ /etc/openvpn/server/easy-rsa/ | |
chown -R root:root /etc/openvpn/server/easy-rsa/ | |
rm -f ~/easyrsa.tgz | |
cd /etc/openvpn/server/easy-rsa/ | |
# Create the PKI, set up the CA and the server and client certificates | |
./easyrsa init-pki | |
./easyrsa --batch build-ca nopass | |
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-server-full server nopass | |
EASYRSA_CERT_EXPIRE=3650 ./easyrsa build-client-full $CLIENT nopass | |
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl | |
# 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 | |
# CRL is read with each client connection, when OpenVPN is dropped to nobody | |
chown nobody:nobody /etc/openvpn/server/crl.pem | |
# Generate key for tls-auth | |
openvpn --genkey --secret /etc/openvpn/server/ta.key | |
# Create the DH parameters file using the predefined ffdhe2048 group | |
echo '-----BEGIN DH PARAMETERS----- | |
MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz | |
+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a | |
87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 | |
YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi | |
7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD | |
ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== | |
-----END DH PARAMETERS-----' > /etc/openvpn/server/dh.pem | |
# Generate server.conf | |
echo "port $PORT | |
proto $PROTOCOL | |
dev tun | |
sndbuf 0 | |
rcvbuf 0 | |
ca ca.crt | |
cert server.crt | |
key server.key | |
dh dh.pem | |
auth SHA512 | |
tls-auth ta.key 0 | |
topology subnet | |
server 10.8.0.0 255.255.255.0 | |
ifconfig-pool-persist ipp.txt" > /etc/openvpn/server/server.conf | |
echo 'push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server/server.conf | |
# DNS | |
case $DNS in | |
1) | |
# Locate the proper resolv.conf | |
# Needed for systems running systemd-resolved | |
if grep -q "127.0.0.53" "/etc/resolv.conf"; then | |
RESOLVCONF='/run/systemd/resolve/resolv.conf' | |
else | |
RESOLVCONF='/etc/resolv.conf' | |
fi | |
# 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 | |
echo "push \"dhcp-option DNS $line\"" >> /etc/openvpn/server/server.conf | |
done | |
;; | |
2) | |
echo 'push "dhcp-option DNS 1.1.1.1"' >> /etc/openvpn/server/server.conf | |
echo 'push "dhcp-option DNS 1.0.0.1"' >> /etc/openvpn/server/server.conf | |
;; | |
3) | |
echo 'push "dhcp-option DNS 8.8.8.8"' >> /etc/openvpn/server/server.conf | |
echo 'push "dhcp-option DNS 8.8.4.4"' >> /etc/openvpn/server/server.conf | |
;; | |
4) | |
echo 'push "dhcp-option DNS 208.67.222.222"' >> /etc/openvpn/server/server.conf | |
echo 'push "dhcp-option DNS 208.67.220.220"' >> /etc/openvpn/server/server.conf | |
;; | |
5) | |
echo 'push "dhcp-option DNS 64.6.64.6"' >> /etc/openvpn/server/server.conf | |
echo 'push "dhcp-option DNS 64.6.65.6"' >> /etc/openvpn/server/server.conf | |
;; | |
esac | |
echo "keepalive 10 120 | |
cipher AES-256-CBC | |
user nobody | |
group nobody | |
persist-key | |
persist-tun | |
status openvpn-status.log | |
verb 3 | |
crl-verify crl.pem" >> /etc/openvpn/server/server.conf | |
# Enable net.ipv4.ip_forward for the system | |
echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/30-openvpn-forward.conf | |
# Enable without waiting for a reboot or service restart | |
echo 1 > /proc/sys/net/ipv4/ip_forward | |
if pgrep firewalld; then | |
# Using both permanent and not permanent rules to avoid a firewalld | |
# reload. | |
# We don't use --add-service=openvpn because that would only work with | |
# the default port and protocol. | |
firewall-cmd --add-port=$PORT/$PROTOCOL | |
firewall-cmd --zone=trusted --add-source=10.8.0.0/24 | |
firewall-cmd --permanent --add-port=$PORT/$PROTOCOL | |
firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24 | |
# 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 --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 | |
# Create a service to set up persistent iptables rules | |
echo "[Unit] | |
Before=network.target | |
[Service] | |
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 -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 -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 -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 -m state --state RELATED,ESTABLISHED -j ACCEPT | |
RemainAfterExit=yes | |
[Install] | |
WantedBy=multi-user.target" > /etc/systemd/system/openvpn-iptables.service | |
systemctl enable --now openvpn-iptables.service | |
fi | |
# 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 | |
# Install semanage if not already present | |
if ! hash semanage 2>/dev/null; then | |
if grep -qs "CentOS Linux release 7" "/etc/centos-release"; then | |
yum install policycoreutils-python -y | |
else | |
yum install policycoreutils-python-utils -y | |
fi | |
fi | |
semanage port -a -t openvpn_port_t -p $PROTOCOL $PORT | |
fi | |
# And finally, enable and start the OpenVPN service | |
systemctl enable --now [email protected] | |
# If the server is behind a NAT, use the correct IP address | |
if [[ "$PUBLICIP" != "" ]]; then | |
IP=$PUBLICIP | |
fi | |
# client-common.txt is created so we have a template to add further users later | |
echo "client | |
dev tun | |
proto $PROTOCOL | |
sndbuf 0 | |
rcvbuf 0 | |
remote $IP $PORT | |
resolv-retry infinite | |
nobind | |
persist-key | |
persist-tun | |
remote-cert-tls server | |
auth SHA512 | |
cipher AES-256-CBC | |
setenv opt block-outside-dns | |
key-direction 1 | |
verb 3" > /etc/openvpn/server/client-common.txt | |
# Generates the custom client.ovpn | |
newclient "$CLIENT" | |
echo | |
echo "Finished!" | |
echo | |
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!" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment