2024-08-24 21:05:07 +02:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
|
|
## CONSTANTS ##
|
|
|
|
readonly DATA_DIR="/etc/openvpn-data"
|
|
|
|
readonly EASYRSA_DIR="${DATA_DIR}/easyrsa"
|
|
|
|
readonly DATA_SERVER_DIR="${DATA_DIR}/server"
|
|
|
|
readonly DATA_CLIENT_DIR="${DATA_DIR}/client"
|
|
|
|
|
|
|
|
|
|
|
|
## HANDLE EXIT SIGNALS ##
|
|
|
|
trap trap_exit EXIT SIGINT SIGTERM
|
|
|
|
trap_exit(){
|
|
|
|
if [[ "${openvpn_pid:+x}" ]]; then
|
|
|
|
kill -- $openvpn_pid 2> /dev/null || true
|
|
|
|
q=0
|
|
|
|
while proc_running $openvpn_pid; do
|
|
|
|
q=$(( q + 1 ))
|
|
|
|
snore 1
|
|
|
|
if [[ "$q" -ge 15 ]]; then
|
|
|
|
log_warn "Sending kill to OpenVPN"
|
|
|
|
kill -s KILL -- $openvpn_pid 2> /dev/null || true
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
exit 0
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# LIB: Efficient sleep (does not create a new process).
|
|
|
|
#
|
|
|
|
snore(){
|
|
|
|
local IFS
|
|
|
|
[[ -n "${_snore_fd:-}" ]] || exec {_snore_fd}<> <(:)
|
|
|
|
read ${1:+-t "$1"} -u $_snore_fd || true
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# HELPER: Check whether given pid is running.
|
|
|
|
#
|
|
|
|
# @param $1 Process ID.
|
|
|
|
#
|
|
|
|
# @exit 0: Process is running
|
|
|
|
# 1: Process is not running.
|
|
|
|
#
|
|
|
|
proc_running(){
|
|
|
|
# try reading state
|
|
|
|
local state_path="/proc/$1/stat"
|
|
|
|
[[ ! -f "$state_path" ]] && return 1
|
|
|
|
local state=$(cat "$state_path" | cut -d ' ' -f3)
|
|
|
|
|
|
|
|
# parse state
|
|
|
|
case "$state" in
|
|
|
|
R|S|D|Z|W|W|P|I) return 0;;
|
|
|
|
*) return 1;;
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# HELPER: Initialize iptables rules.
|
|
|
|
#
|
|
|
|
iptables_init(){
|
|
|
|
/sbin/iptables -t nat -I POSTROUTING -s 192.168.35.0/24 ! -d 192.168.35.0/24 -j MASQUERADE
|
|
|
|
/sbin/iptables -I INPUT -i tun0 -j ACCEPT
|
|
|
|
/sbin/iptables -I INPUT -p udp --dport 1194 -j ACCEPT
|
|
|
|
/sbin/iptables -I INPUT -p tcp --dport 1194 -j ACCEPT
|
|
|
|
/sbin/iptables -I FORWARD -s 192.168.35.0/24 -j ACCEPT
|
|
|
|
/sbin/iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# HELPER: Set up easyrsa.
|
|
|
|
#
|
|
|
|
easyrsa_init(){
|
|
|
|
## MAYBE CREATE VARS FILE ##
|
|
|
|
if [[ ! -f "${EASYRSA_DIR}/vars" ]]; then
|
|
|
|
touch "${EASYRSA_DIR}/vars"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# HELPER: Set up server keys.
|
|
|
|
#
|
|
|
|
easyrsa_server_keys_create(){
|
|
|
|
## IGNORE IF EXISTING ##
|
|
|
|
[[ -d "${EASYRSA_DIR}/pki" ]] && return 0
|
|
|
|
|
|
|
|
|
|
|
|
## SET UP CA AND SERVER KEYS (EASYRSA) ##
|
|
|
|
local prev_pwd="$PWD" && cd "$EASYRSA_DIR"
|
|
|
|
|
|
|
|
# new pki
|
|
|
|
/usr/bin/easyrsa --batch init-pki
|
|
|
|
|
|
|
|
# create ca
|
|
|
|
/usr/bin/easyrsa --batch --days=7300 build-ca nopass
|
|
|
|
|
|
|
|
# generate server keys
|
|
|
|
/usr/bin/easyrsa --batch --days=7300 build-server-full server nopass
|
|
|
|
|
|
|
|
# generate crl
|
|
|
|
/usr/bin/easyrsa --batch --days=7300 gen-crl
|
|
|
|
chown nobody:nobody pki/crl.pem
|
|
|
|
|
|
|
|
# restore pwd
|
|
|
|
cd "$prev_pwd"
|
|
|
|
|
|
|
|
# create symlinks
|
|
|
|
ln -s ${EASYRSA_DIR}/pki/{ca.crt,private/ca.key,issued/server.crt,private/server.key,crl.pem} "${DATA_SERVER_DIR}"
|
|
|
|
|
|
|
|
|
|
|
|
## OTHER KEYS ##
|
|
|
|
# dh parameters
|
|
|
|
openssl dhparam -out "${DATA_SERVER_DIR}/dh2048.pem" 2048
|
|
|
|
|
|
|
|
# tls-crypt key
|
|
|
|
openvpn --genkey secret "${DATA_SERVER_DIR}/tls-crypt.key"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# HELPER: Set up openvpn server config file.
|
|
|
|
#
|
|
|
|
openvpn_config_init(){
|
|
|
|
## IGNORE IF EXISTING ##
|
|
|
|
[[ -f "${DATA_SERVER_DIR}/server.conf" ]] && return 0
|
|
|
|
|
|
|
|
|
|
|
|
## WRITE SERVER CONFIG ##
|
|
|
|
echo "port 1194
|
|
|
|
proto udp
|
|
|
|
server 192.168.35.0 255.255.255.0
|
|
|
|
dev tun
|
|
|
|
user nobody
|
|
|
|
group nogroup
|
|
|
|
topology subnet
|
|
|
|
|
|
|
|
ca ca.crt
|
|
|
|
cert server.crt
|
|
|
|
key server.key
|
|
|
|
dh dh2048.pem
|
|
|
|
crl-verify crl.pem
|
|
|
|
tls-crypt tls-crypt.key
|
|
|
|
auth SHA512
|
|
|
|
|
|
|
|
client-config-dir ${DATA_CLIENT_DIR}
|
|
|
|
ifconfig-pool-persist ipp.txt
|
2024-08-24 22:08:57 +02:00
|
|
|
keepalive 300 1500
|
2024-08-24 21:05:07 +02:00
|
|
|
persist-key
|
|
|
|
persist-tun
|
|
|
|
|
|
|
|
push \"dhcp-option DNS 1.1.1.1\"
|
|
|
|
push \"dhcp-option DNS 1.0.0.1\"
|
|
|
|
push \"redirect-gateway def1 bypass-dhcp\"
|
|
|
|
push \"block-outside-dns\"
|
|
|
|
|
|
|
|
verb 3" > "${DATA_SERVER_DIR}/server.conf"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## SET UP USED DIRECTORIES ##
|
|
|
|
mkdir -p "$DATA_DIR"
|
|
|
|
mkdir -p "$EASYRSA_DIR"
|
|
|
|
mkdir -p "$DATA_SERVER_DIR"
|
|
|
|
mkdir -p "$DATA_CLIENT_DIR"
|
|
|
|
|
|
|
|
|
|
|
|
## SET UP TUN DEVICE ##
|
|
|
|
mkdir -p /dev/net
|
|
|
|
[[ ! -c /dev/net/tun ]] && mknod /dev/net/tun c 10 200
|
|
|
|
|
|
|
|
|
|
|
|
## SET UP FW AND ROUTING ##
|
|
|
|
iptables_init
|
|
|
|
|
|
|
|
|
|
|
|
## INITIALIZE CONFIG ##
|
|
|
|
# set up easyrsa
|
|
|
|
easyrsa_init
|
|
|
|
|
|
|
|
# server keys
|
|
|
|
easyrsa_server_keys_create
|
|
|
|
|
|
|
|
# server config
|
|
|
|
openvpn_config_init
|
|
|
|
|
|
|
|
|
|
|
|
## RUN OPENVPN SERVER ##
|
|
|
|
/usr/sbin/openvpn --cd "${DATA_SERVER_DIR}" --config "${DATA_SERVER_DIR}/server.conf" & openvpn_pid=$!
|
|
|
|
wait $openvpn_pid
|