Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env bash
- # Installs OpenVPN server on CentOS 7
- # Check yo' privilege
- [[ $(id -u) != 0 ]] && echo 'You must run this script as root!' && exit 1
- ################################################################################
- ################################## VARIABLES ###################################
- ################################################################################
- # User-modifiable variables
- ADDRESS=192.168.139.106
- PORT=1194
- DNS=192.168.139.104
- SUBNET=192.168.139.128
- MASK=255.255.255.128
- IFACE='eth0'
- # Script static variables
- CLIENT_TAR='/tmp/openvpn-client.tar.gz'
- EASY_RSA='/etc/openvpn/.easy-rsa'
- KEYS_DIR='/etc/openvpn/keys'
- ################################################################################
- ################################## UTILITIES ###################################
- ################################################################################
- # Provides pretty colourful output with timestamps
- output() {
- local LABEL='OpenVPN'
- local TIMESTAMP=$(date +%H:%M)
- local COLOUR='\033[34m' # Blue
- local RESET='\033[0m' # Standard
- case $1 in
- ERROR) local COLOUR='\033[31m' ;; # Red
- SUCCESS) local COLOUR='\033[32m' ;; # Green
- WARN) local COLOUR='\033[33m' ;; # Yellow
- esac
- while read LINE; do
- echo -e "${COLOUR}${LABEL} [${TIMESTAMP}]${RESET} ${LINE}"
- done
- }
- # Produces bold output
- say() {
- local BOLD=$(tput bold)
- local STD=$(tput sgr0)
- echo "${BOLD}$@${STD}"
- }
- # Creates a copy of $2 at $2.old
- backup() {
- [[ -z $1 ]] && echo 'backup() - No name variable set' | output ERROR
- [[ -z $2 ]] && echo 'backup() - No file variable set' | output ERROR
- local NAME=$1
- local FILE=$2
- if [[ -f $FILE ]]; then
- echo "Backing up previous ${NAME} file..." | output
- RESULT=$(cp -f ${FILE} ${FILE}.old 2>&1)
- if [[ $? != 0 ]]; then
- echo "Failed to backup previous ${FILE} file!" | output WARN
- echo $RESULT | output WARN
- else
- echo "${NAME} backup created successfully" | output
- fi
- fi
- }
- # Just a pretty way of creating here documents, with error handling and backing
- # up of the previous version.
- createfile() {
- [[ -z $1 ]] && echo 'createfile() - No name variable set' | output ERROR
- [[ -z $2 ]] && echo 'createfile() - No file variable set' | output ERROR
- local NAME=$1
- local FILE=$2
- backup "$NAME" "$FILE"
- echo "Creating ${NAME}..." | output
- while read -r LINE; do
- # Add each line of STDIN to $CONTENT, along with a line break
- local CONTENT+="${LINE}\n"
- done
- RESULT=$(echo -e ${CONTENT} > ${FILE} 2>&1)
- if [[ $? != 0 ]]; then
- echo "Failed to create ${NAME} file!" | output ERROR
- echo $RESULT | output ERROR
- exit 1
- else
- echo "${NAME} file created successfully" | output
- fi
- }
- # Checks that the previous command exited correctly and quits the script if not,
- # with a pretty error message. Optionally a second string can be provided to
- # print on success.
- onfail() {
- if [[ $? != 0 ]]; then
- echo $1 | output ERROR
- elif [[ ! -z $2 ]]; then
- echo $2 | output
- fi
- }
- ################################################################################
- ################################# INSTALLATION #################################
- ################################################################################
- say 'Installing RPM packages...' | output
- yum install -e 0 -y openvpn \
- easy-rsa \
- iptables \
- iptables-utils \
- iptables-services | output
- onfail 'Failed to install RPM packages!' 'RPM packages installed successfully'
- say 'Setting up Easy-RSA...' | output
- mkdir -p $EASY_RSA
- onfail "Failed to create Easy-RSA directory at ${EASY_RSA}"
- cp -rf /usr/share/easy-rsa/2.0/* $EASY_RSA/
- onfail "Unable to copy Easy-RSA to $EASY_RSA"
- cp -f $EASY_RSA/openssl-1.0.0.cnf $EASY_RSA/openssl.cnf
- onfail "Unable to create $EASY_RSA/openssl.cnf to force the OpenSSL version"
- restorecon -R $EASY_RSA
- onfail "Unable to set SELinux context labels for ${EASY_RSA}"
- ################################################################################
- ################################ CONFIGURATION #################################
- ################################################################################
- say 'Generating configuration files...' | output
- # This is the main configuration file for OpenVPN and provides the core
- # configuration parameters for running the service.
- createfile 'OpenVPN server configuration' '/etc/openvpn/server.conf' <<OPENVPN
- local $ADDRESS
- port $PORT
- proto udp
- dev tun
- comp-lzo
- topology subnet
- user nobody
- group nobody
- persist-key
- persist-tun
- ifconfig-pool-persist ipp.txt
- keepalive 10 120
- max-clients 100
- status openvpn-status.log
- log-append openvpn.log
- verb 3
- mute 20
- ca ${KEYS_DIR}/ca.crt
- cert ${KEYS_DIR}/server.crt
- key ${KEYS_DIR}/server.key
- dh ${KEYS_DIR}/dh2048.pem
- cipher AES-256-CBC
- duplicate-cn
- plugin /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn
- server ${SUBNET} ${MASK}
- push "route 192.168.139.0 255.255.255.128"
- push "dhcp-option DNS $DNS"
- OPENVPN
- # The PAM configuration file permits access through the VPN to users with local
- # POSIX accounts. Additional configuration can be added to only permit certain
- # groups or users to authenticate using this method.
- createfile 'OpenVPN PAM security configuration' '/etc/pam.d/openvpn' <<PAM
- auth required pam_unix.so shadow nodelay
- account required pam_unix.so
- PAM
- # This minimal firewall configuration permits only SSH and OpenVPN connections
- # as well as allowing SNAT connections through the VPN.
- createfile 'Firewall rules' '/etc/sysconfig/iptables' <<IPTABLES
- *nat
- :PREROUTING ACCEPT [0:0]
- :INPUT ACCEPT [0:0]
- :OUTPUT ACCEPT [0:0]
- :POSTROUTING ACCEPT [0:0]
- -A POSTROUTING -o $IFACE -j SNAT --to-source $ADDRESS
- -A POSTROUTING -o $IFACE -j SNAT --to-source $ADDRESS
- COMMIT
- *filter
- :INPUT ACCEPT [0:0]
- :FORWARD ACCEPT [0:0]
- :OUTPUT ACCEPT [0:0]
- -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
- -A INPUT -p icmp -j ACCEPT
- -A INPUT -i lo -j ACCEPT
- -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
- -A INPUT -i $IFACE -p udp -m state --state NEW -m udp --dport $PORT -j ACCEPT
- -A INPUT -j REJECT --reject-with icmp-host-prohibited
- COMMIT
- IPTABLES
- createfile 'Easy-RSA configuration' "${EASY_RSA}/vars" <<EASYRSA
- export EASY_RSA="$EASY_RSA"
- export OPENSSL="openssl"
- export PKCS11TOOL="pkcs11-tool"
- export GREP="grep"
- export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`
- export KEY_DIR="$KEYS_DIR"
- export PKCS11_MODULE_PATH="dummy"
- export PKCS11_PIN="dummy"
- export KEY_SIZE=2048
- export CA_EXPIRE=3650
- export KEY_EXPIRE=3650
- export KEY_COUNTRY="GB"
- export KEY_PROVINCE="DEVON"
- export KEY_CITY="PLYMOUTH"
- export KEY_ORG="Land Registry"
- export KEY_EMAIL="webops@digital.landregistry.gov.uk"
- export KEY_OU="IT Operations"
- export KEY_NAME="server"
- export KEY_CN="$(hostname)"
- EASYRSA
- createfile 'Client OpenVPN configuration' '/etc/openvpn/client.ovpn' <<CLIENT
- client
- dev tun
- proto udp
- remote $ADDRESS $PORT
- resolv-retry infinite
- remote-cert-tls server
- ns-cert-type server
- auth-nocache
- auth-user-pass
- nobind
- persist-key
- persist-tun
- comp-lzo
- verb 3
- ca ca.crt
- cert client.crt
- key client.key
- cipher AES-256-CBC
- CLIENT
- say 'Configuring kernel parameters...' | output
- createfile 'Kernel parameters' '/etc/sysctl.d/openvpn' <<KERNEL
- net.ipv4.ip_forward = 1
- net.ipv4.conf.default.rp_filter = 0
- net.ipv4.conf.all.send_redirects = 0
- net.ipv4.conf.all.accept_redirects = 0
- net.ipv4.conf.default.send_redirects = 0
- net.ipv4.conf.default.accept_source_route = 0
- net.ipv4.icmp_ignore_bogus_error_responses = 1
- KERNEL
- sysctl -p
- onfail 'Unable to set runtime parameters' 'Runtime parameters set'
- ################################################################################
- ################################### RUNTIME ####################################
- ################################################################################
- say 'Creating authentication certificates...' | output
- source $EASY_RSA/vars
- onfail "Failed to load Easy-RSA variables from ${EASY_RSA}/vars!"
- bash $EASY_RSA/clean-all | output
- onfail "Failed to clean up ${KEYS_DIR}!"
- echo 'Creating Diffie Hellman key... (this may take some time)' | output
- bash $EASY_RSA/build-dh 2>/dev/null | output
- onfail 'Failed to create Diffie Hellman key!'
- echo 'Creating Certificate Authority...' | output
- bash $EASY_RSA/build-ca --batch 2>/dev/null | output
- onfail 'Failed to create Certificate Authority!'
- echo 'Creating server-side certificate...' | output
- bash $EASY_RSA/build-key-server --batch server 2>/dev/null | output
- onfail 'Failed to create server certificate!'
- echo 'Creating client-side certificate...' | output
- KEY_NAME="client" bash $EASY_RSA/build-key --batch client 2>/dev/null | output
- onfail 'Failed to create client certificate!'
- restorecon -R ${KEYS_DIR}
- onfail "Unable to set SELinnux context labels for ${KEYS_DIR}"
- say 'Reconfiguring SystemD network services...' | output
- systemctl stop NetworkManager.service 2>&1 | output
- onfail 'Failed to stop NetworkManager.service!'
- systemctl stop firewalld.service 2>&1 | output
- onfail 'Failed to stop firewalld.service!'
- systemctl start iptables.service 2>&1 | output
- onfail 'Failed to start iptables.service'
- systemctl restart network.service 2>&1 | output
- onfail 'Failed to restart network.service'
- systemctl enable iptables.service >/dev/null 2>&1
- systemctl disable firewalld.service >/dev/null 2>&1
- systemctl disable NetworkManager.service >/dev/null 2>&1
- say 'Starting OpenVPN service...' | output
- systemctl stop openvpn@server.service 2>&1 | output
- systemctl start openvpn@server.service 2>&1 | output
- onfail 'Failed to start OpenVPN service'
- systemctl enable openvpn@server.service >/dev/null 2>&1
- say 'Packaging client configuration...' | output
- TMP_DIR="/tmp/$(openssl rand -hex 6)"
- mkdir -p $TMP_DIR
- onfail "Unable to create temporary directory at $TMP_DIR"
- cp $KEYS_DIR/{ca.crt,client.crt,client.key} $TMP_DIR
- onfail "Unable to copy necessary certificates to $TMP_DIR"
- cp /etc/openvpn/client.ovpn $TMP_DIR
- onfail "Unable to copy client configuration to $TMP_DIR"
- tar -C $TMP_DIR -caf $CLIENT_TAR .
- onfail "Unable to create compressed archive at $CLIENT_TAR"
- rm -rf $TMP_DIR
- echo "Client configuration can be found at $CLIENT_TAR" | output
- [[ -d '/vagrant' ]] && cp -f $CLIENT_TAR /vagrant
- say 'Installation complete!' | output SUCCESS
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement