#!/bin/bash# OpenVPN road warrior installer for Debian, Ubuntu and CentOS# This script will work on Debian, Ubuntu, CentOS and probably other distros# of the same families, although no support is offered for them. It isn't# bulletproof but it will probably work if you simply want to setup a VPN on# your Debian/Ubuntu/CentOS box. It has been designed to be as unobtrusive and# universal as possible.# Detect Debian users running the script with "sh" instead of bashifreadlink/proc/$$/exe|grep-qs"dash"; thenecho"This script needs to be run with bash, not sh"exit1fiif [[ "$EUID"-ne0 ]]; thenecho"Sorry, you need to run this as root"exit2fiif [[ !-e /dev/net/tun ]]; thenecho"The TUN device is not availableYou need to enable TUN before running this script"exit3fiifgrep-qs"CentOS release 5""/etc/redhat-release"; thenecho"CentOS 5 is too old and not supported"exit4fiif [[ -e /etc/debian_version ]]; thenOS=debianGROUPNAME=nogroupRCLOCAL='/etc/rc.local'elif [[ -e /etc/centos-release ||-e /etc/redhat-release ]]; thenOS=centosGROUPNAME=nobodyRCLOCAL='/etc/rc.d/rc.local'elseecho"Looks like you aren't running this installer on Debian, Ubuntu or CentOS"exit5finewclient () {# Generates the custom client.ovpncp/etc/openvpn/client-common.txt~/$1.ovpnecho"">>~/$1.ovpncat/etc/openvpn/easy-rsa/pki/ca.crt>>~/$1.ovpnecho"">>~/$1.ovpnecho"">>~/$1.ovpncat/etc/openvpn/easy-rsa/pki/issued/$1.crt>>~/$1.ovpnecho"">>~/$1.ovpnecho"">>~/$1.ovpncat/etc/openvpn/easy-rsa/pki/private/$1.key>>~/$1.ovpnecho"">>~/$1.ovpnecho"">>~/$1.ovpncat/etc/openvpn/ta.key>>~/$1.ovpnecho"">>~/$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.com)# 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"="" ]]; thenIP=$(wget-4qO-"http://whatismyip.akamai.com/")fiif [[ -e /etc/openvpn/server.conf ]]; thenwhile:doclearecho"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]: "optioncase$optionin 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-iclientCLIENTcd/etc/openvpn/easy-rsa/./easyrsabuild-client-full$CLIENTnopass# Generates the custom client.ovpnnewclient"$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 simplimplified# ...but what can I say, I want some sleep tooNUMBEROFCLIENTS=$(tail-n +2 /etc/openvpn/easy-rsa/pki/index.txt |grep-c"^V")if [[ "$NUMBEROFCLIENTS"='0' ]]; thenecho""echo"You have no existing clients!"exit6fiecho""echo"Select the existing client certificate you want to revoke"tail-n+2/etc/openvpn/easy-rsa/pki/index.txt|grep"^V"|cut-d'='-f2|nl-s') 'if [[ "$NUMBEROFCLIENTS"='1' ]]; thenread-p"Select one client [1]: "CLIENTNUMBERelseread-p"Select one client [1-$NUMBEROFCLIENTS]: "CLIENTNUMBERfiCLIENT=$(tail-n +2 /etc/openvpn/easy-rsa/pki/index.txt |grep"^V"|cut-d'='-f2|sed-n"$CLIENTNUMBER"p)cd/etc/openvpn/easy-rsa/./easyrsa--batchrevoke$CLIENTEASYRSA_CRL_DAYS=3650./easyrsagen-crlrm-rfpki/reqs/$CLIENT.reqrm-rfpki/private/$CLIENT.keyrm-rfpki/issued/$CLIENT.crtrm-rf/etc/openvpn/crl.pemcp/etc/openvpn/easy-rsa/pki/crl.pem/etc/openvpn/crl.pem# CRL is read with each client connection, when OpenVPN is dropped to nobodychownnobody:$GROUPNAME/etc/openvpn/crl.pemecho""echo"Certificate for client $CLIENT revoked"exit ;; 3) echo""read-p"Do you really want to remove OpenVPN? [y/n]: "-e-inREMOVEif [[ "$REMOVE"='y' ]]; thenPORT=$(grep'^port ' /etc/openvpn/server.conf |cut-d""-f2)PROTOCOL=$(grep'^proto ' /etc/openvpn/server.conf |cut-d""-f2)ifpgrepfirewalld; thenIP=$(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""-f10)# Using both permanent and not permanent rules to avoid a firewalld reload.firewall-cmd--zone=public--remove-port=$PORT/$PROTOCOLfirewall-cmd--zone=trusted--remove-source=10.8.0.0/24firewall-cmd--permanent--zone=public--remove-port=$PORT/$PROTOCOLfirewall-cmd--permanent--zone=trusted--remove-source=10.8.0.0/24firewall-cmd--direct--remove-ruleipv4natPOSTROUTING0-s10.8.0.0/24!-d10.8.0.0/24-jSNAT--to$IPfirewall-cmd--permanent--direct--remove-ruleipv4natPOSTROUTING0-s10.8.0.0/24!-d10.8.0.0/24-jSNAT--to$IPelseIP=$(grep'iptables -t nat -A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to '$RCLOCAL|cut-d""-f14)iptables-tnat-DPOSTROUTING-s10.8.0.0/24!-d10.8.0.0/24-jSNAT--to$IPsed-i'/iptables -t nat -A POSTROUTING -s 10.8.0.0\/24 ! -d 10.8.0.0\/24 -j SNAT --to /d'$RCLOCALifiptables-L-n|grep-qE'^ACCEPT'; theniptables-DINPUT-p$PROTOCOL--dport$PORT-jACCEPTiptables-DFORWARD-s10.8.0.0/24-jACCEPTiptables-DFORWARD-mstate--stateRELATED,ESTABLISHED-jACCEPTsed-i"/iptables -I INPUT -p $PROTOCOL --dport $PORT -j ACCEPT/d"$RCLOCALsed-i"/iptables -I FORWARD -s 10.8.0.0\/24 -j ACCEPT/d"$RCLOCALsed-i"/iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT/d"$RCLOCALfifiifhashsestatus2>/dev/null; thenifsestatus|grep"Current mode"|grep-qs"enforcing"; thenif [[ "$PORT"!='1194'||"$PROTOCOL"='tcp' ]]; thensemanageport-d-topenvpn_port_t-p$PROTOCOL$PORTfififiif [[ "$OS"='debian' ]]; thenapt-getremove--purge-yopenvpnelseyumremoveopenvpn-yfirm-rf/etc/openvpnecho""echo"OpenVPN removed!"elseecho""echo"Removal aborted!"fiexit ;; 4) exit;;esacdoneelseclearecho'Welcome to this quick OpenVPN "road warrior" installer'echo""# OpenVPN setup and first user creationecho"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 I need to know the IPv4 address of the network interface you want OpenVPN"echo"listening to."read-p"IP address: "-e-i$IPIPecho""echo"Which protocol do you want for OpenVPN connections?"echo" 1) UDP (recommended)"echo" 2) TCP"read-p"Protocol [1-2]: "-e-i1PROTOCOLcase$PROTOCOLin 1) PROTOCOL=udp ;; 2) PROTOCOL=tcp ;;esacecho""echo"What port do you want OpenVPN listening to?"read-p"Port: "-e-i1194PORTecho""echo"Which DNS do you want to use with the VPN?"echo" 1) Current system resolvers"echo" 2) Google"echo" 3) OpenDNS"echo" 4) NTT"echo" 5) Hurricane Electric"echo" 6) Verisign"read-p"DNS [1-6]: "-e-i1DNSecho""echo"Finally, tell me your name for the client certificate"echo"Please, use one word only, no special characters"read-p"Client name: "-e-iclientCLIENTecho""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..."if [[ "$OS"='debian' ]]; thenapt-getupdateapt-getinstallopenvpniptablesopensslca-certificates-yelse# Else, the distro is CentOSyuminstallepel-release-yyuminstallopenvpniptablesopensslwgetca-certificates-yfi# An old version of easy-rsa was available by default in some openvpn packagesif [[ -d /etc/openvpn/easy-rsa/ ]]; thenrm-rf/etc/openvpn/easy-rsa/fi# Get easy-rsawget-O~/EasyRSA-3.0.3.tgz"https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.3/EasyRSA-3.0.3.tgz"tarxzf~/EasyRSA-3.0.3.tgz-C~/# Temporal fix for issue #353, which is caused by OpenVPN/easy-rsa#135# Will be removed as soon as a new release of easy-rsa is availablesed-i's/\[\[/\[/g;s/\]\]/\]/g;s/==/=/g'~/EasyRSA-3.0.3/easyrsamv~/EasyRSA-3.0.3//etc/openvpn/mv/etc/openvpn/EasyRSA-3.0.3//etc/openvpn/easy-rsa/chown-Rroot:root/etc/openvpn/easy-rsa/rm-rf~/EasyRSA-3.0.3.tgzcd/etc/openvpn/easy-rsa/# Create the PKI, set up the CA, the DH params and the server + client certificates./easyrsainit-pki./easyrsa--batchbuild-canopass./easyrsagen-dh./easyrsabuild-server-fullservernopass./easyrsabuild-client-full$CLIENTnopassEASYRSA_CRL_DAYS=3650./easyrsagen-crl# Move the stuff we needcppki/ca.crtpki/private/ca.keypki/dh.pempki/issued/server.crtpki/private/server.keypki/crl.pem/etc/openvpn# CRL is read with each client connection, when OpenVPN is dropped to nobodychownnobody:$GROUPNAME/etc/openvpn/crl.pem# Generate key for tls-authopenvpn--genkey--secret/etc/openvpn/ta.key# Generate server.confecho"port $PORTproto $PROTOCOLdev tunsndbuf 0rcvbuf 0ca ca.crtcert server.crtkey server.keydh dh.pemauth SHA512tls-auth ta.key 0topology subnetserver 10.8.0.0 255.255.255.0ifconfig-pool-persist ipp.txt">/etc/openvpn/server.confecho'push "redirect-gateway def1 bypass-dhcp"'>>/etc/openvpn/server.conf# DNScase$DNSin 1) # Obtain the resolvers from resolv.conf and use them for OpenVPNgrep-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}'|whilereadline; doecho"push \"dhcp-option DNS $line\"">>/etc/openvpn/server.confdone ;; 2) echo'push "dhcp-option DNS 8.8.8.8"'>>/etc/openvpn/server.confecho'push "dhcp-option DNS 8.8.4.4"'>>/etc/openvpn/server.conf ;; 3)echo'push "dhcp-option DNS 208.67.222.222"'>>/etc/openvpn/server.confecho'push "dhcp-option DNS 208.67.220.220"'>>/etc/openvpn/server.conf ;; 4) echo'push "dhcp-option DNS 129.250.35.250"'>>/etc/openvpn/server.confecho'push "dhcp-option DNS 129.250.35.251"'>>/etc/openvpn/server.conf ;; 5) echo'push "dhcp-option DNS 74.82.42.42"'>>/etc/openvpn/server.conf ;; 6) echo'push "dhcp-option DNS 64.6.64.6"'>>/etc/openvpn/server.confecho'push "dhcp-option DNS 64.6.65.6"'>>/etc/openvpn/server.conf ;;esacecho"keepalive 10 120cipher AES-256-CBCcomp-lzouser nobodygroup $GROUPNAMEpersist-keypersist-tunstatus openvpn-status.logverb 3crl-verify crl.pem">>/etc/openvpn/server.conf# Enable net.ipv4.ip_forward for the systemsed-i'/\/c\net.ipv4.ip_forward=1'/etc/sysctl.confif!grep-q"\" /etc/sysctl.conf; then echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf fi # Avoid an unneeded reboot 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 --zone=public --add-port=$PORT/$PROTOCOL firewall-cmd --zone=trusted --add-source=10.8.0.0/24 firewall-cmd --permanent --zone=public --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 # Needed to use rc.local with some systemd distros if [[ "$OS" = 'debian' && ! -e $RCLOCAL ]]; then echo '#!/bin/sh -eexit 0' > $RCLOCAL fi chmod +x $RCLOCAL # Set NAT for the VPN subnet iptables -t nat -A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $IP sed -i "1a\iptables-tnat-APOSTROUTING-s10.8.0.0/24!-d10.8.0.0/24-jSNAT--to$IP"$RCLOCAL if iptables -L -n | grep -qE '^(REJECT|DROP)'; then # If iptables has at least one REJECT rule, we asume this is needed. # Not the best approach but I can't think of other and this shouldn't # cause problems. iptables -I INPUT -p $PROTOCOL --dport $PORT -j ACCEPT iptables -I FORWARD -s 10.8.0.0/24 -j ACCEPT iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT sed -i "1a\iptables-IINPUT-p$PROTOCOL--dport$PORT-jACCEPT"$RCLOCAL sed -i "1a\iptables-IFORWARD-s10.8.0.0/24-jACCEPT"$RCLOCAL sed -i "1a\iptables-IFORWARD-mstate--stateRELATED,ESTABLISHED-jACCEPT"$RCLOCAL fi fi # If SELinux is enabled and a custom port or TCP was selected, we need this if hash sestatus 2>/dev/null; then if sestatus | grep "Currentmode" | grep -qs "enforcing"; then if [[ "$PORT" != '1194' || "$PROTOCOL" = 'tcp' ]]; then # semanage isn't available in CentOS 6 by default if ! hash semanage 2>/dev/null; then yum install policycoreutils-python -y fi semanage port -a -t openvpn_port_t -p $PROTOCOL$PORT fi fi fi # And finally, restart OpenVPN if [[ "$OS" = 'debian' ]]; then # Little hack to check for systemd if pgrep systemd-journal; then systemctl restart [email protected] else /etc/init.d/openvpn restart fi else if pgrep systemd-journal; then systemctl restart [email protected] systemctl enable [email protected] else service openvpn restart chkconfig openvpn on fi fi # Try to detect a NATed connection and ask about it to potential LowEndSpirit users EXTERNALIP=$(wget-4qO-"http://whatismyip.akamai.com/") if [[ "$IP" != "$EXTERNALIP" ]]; then echo "" echo "LookslikeyourserverisbehindaNAT!" echo "" echo "IfyourserverisNATed (e.g. LowEndSpirit), I need to know the external IP" echo "If that's not the case, just ignore this and leave the next field blank" read -p "External IP: " -e USEREXTERNALIP if [[ "$USEREXTERNALIP" != "" ]]; then IP=$USEREXTERNALIP fi fi # client-common.txt is created so we have a template to add further users later echo "clientdev tunproto $PROTOCOLsndbuf 0rcvbuf 0remote $IP $PORTresolv-retry infinitenobindpersist-keypersist-tunremote-cert-tls serverauth SHA512cipher AES-256-CBCcomp-lzosetenv opt block-outside-dnskey-direction 1verb 3" > /etc/openvpn/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