227 lines
6.8 KiB
Bash
227 lines
6.8 KiB
Bash
#!/bin/bash
|
|
# Install using: sudo su -c "bash <(wget -qO- /url/to/install-openvpn-server.sh)"
|
|
|
|
# Make sure script is ran as root
|
|
if [[ $EUID -ne 0 ]]; then
|
|
exec sudo /bin/bash "$0" "$@"
|
|
fi
|
|
# Helper functions
|
|
add_iptables_rule() {
|
|
local RULE="$1"
|
|
local TABLE="filter" # Default table is filter
|
|
if [[ "$RULE" =~ -t[[:space:]]+(nat|mangle|raw|filter) ]]; then
|
|
TABLE="${BASH_REMATCH[1]}"
|
|
RULE="${RULE/-t ${BASH_REMATCH[1]}/}" # Remove "-t <table>" from RULE
|
|
fi
|
|
local RULE_ACTION=$(echo "$RULE" | awk '{print $1}')
|
|
local RULE_REST=$(echo "$RULE" | cut -d' ' -f2-)
|
|
if iptables-save -t "$TABLE" | grep -Fq -- "$RULE_REST"; then
|
|
echo "Rule already exists in table $TABLE, skipping: -t $TABLE $RULE"
|
|
else
|
|
echo "Adding iptables rule to table $TABLE: -t $TABLE $RULE"
|
|
iptables -t "$TABLE" $RULE
|
|
fi
|
|
}
|
|
|
|
# Setup script
|
|
read -e -p "Enter lan NIC: " -i $(ip route | grep default | sed -e 's/^.*dev.//' -e 's/.proto.*//') NIC_NAME
|
|
read -e -p "Enter VPN subnet: " -i "172.19.100" VPN_SUBNET
|
|
read -e -p "Enter LAN subnet: " -i "192.168.0" LAN_SUBNET
|
|
read -e -p "Enter VPN public hostname: " -i "home.myspace.nu" VPN_PUBLIC_HOST
|
|
read -e -p "Enter VPN public portnumber: " -i "1194" VPN_PUBLIC_PORT
|
|
|
|
if [ $(dpkg-query -W -f='${Status}' openvpn 2>/dev/null | grep -c "ok installed") -eq 0 ]; then
|
|
echo "Installing OpenVPN..."
|
|
apt install openvpn easy-rsa -y
|
|
fi
|
|
if [ ! -d /etc/openvpn/easy-rsa ]; then
|
|
echo "Setting up Certificate Authority"
|
|
make-cadir /etc/openvpn/easy-rsa
|
|
cd /etc/openvpn/easy-rsa
|
|
./easyrsa init-pki
|
|
./easyrsa build-ca
|
|
./easyrsa gen-req myservername nopass
|
|
./easyrsa gen-dh
|
|
./easyrsa sign-req server myservername
|
|
cp pki/dh.pem pki/ca.crt pki/issued/myservername.crt pki/private/myservername.key /etc/openvpn/
|
|
fi
|
|
if [ ! -d /var/log/openvpn ]; then
|
|
mkdir -p /var/log/openvpn
|
|
fi
|
|
if [ ! -d /etc/openvpn/ccd ]; then
|
|
mkdir -p /etc/openvpn/ccd
|
|
fi
|
|
if ufw status | grep -q "Status: active"; then
|
|
echo Adding firewall rules...
|
|
ufw allow $VPN_PUBLIC_PORT/udp
|
|
ufw allow OpenSSH
|
|
ufw enable
|
|
ufw status verbose
|
|
echo You might need to enable NAT / MASQUERADE forwarding in /etc/ufw/before.rules
|
|
systemctl restart ufw
|
|
fi
|
|
|
|
if [ ! -f /etc/openvpn/myserver.conf ] || [[ " $@ " == *" --force "* ]]; then
|
|
read -n 1 -p "Do you want to use username and password for login (y/N)? " answer
|
|
if [[ ! -z "$answer" && "${answer^^}"=="Y" ]]; then
|
|
EXTRA_CONFIG=$(cat <<-END
|
|
script-security 2 # must be at least 2
|
|
auth-user-pass-verify /etc/openvpn/auth-script.sh via-file
|
|
username-as-common-name # without this openvpn will use cn in the certificate as username
|
|
duplicate-cn # you may need this if everyone is using same certificate
|
|
verify-client-cert require
|
|
END
|
|
)
|
|
fi
|
|
|
|
tee /etc/openvpn/myserver.conf > /dev/null <<EOL
|
|
#public-host $VPN_PUBLIC_HOST
|
|
port $VPN_PUBLIC_PORT
|
|
proto udp
|
|
dev tun
|
|
|
|
ca ca.crt
|
|
cert myservername.crt
|
|
key myservername.key
|
|
dh dh.pem
|
|
|
|
server $VPN_SUBNET.0 255.255.255.0 nopool
|
|
ifconfig-pool-persist /var/log/openvpn/ipp.txt
|
|
client-config-dir /etc/openvpn/ccd
|
|
topology subnet
|
|
ifconfig-pool $VPN_SUBNET.2 $VPN_SUBNET.126
|
|
push "route $LAN_SUBNET.0 255.255.255.0"
|
|
|
|
$EXTRA_CONFIG
|
|
|
|
keepalive 10 120
|
|
tls-auth ta.key 0
|
|
cipher AES-256-CBC
|
|
persist-key
|
|
persist-tun
|
|
status /var/log/openvpn/openvpn-status.log
|
|
verb 3
|
|
explicit-exit-notify 1
|
|
EOL
|
|
fi
|
|
if [ ! -f /etc/openvpn/ta.key ]; then
|
|
openvpn --genkey secret /etc/openvpn/ta.key
|
|
fi
|
|
|
|
sed -i -e 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' /etc/sysctl.conf
|
|
sudo sysctl -p /etc/sysctl.conf
|
|
systemctl start openvpn@myserver
|
|
|
|
echo Settings up NAT rules...
|
|
add_iptables_rule "-t nat -A POSTROUTING -s $VPN_SUBNET.0/24 -o $NIC_NAME -j MASQUERADE"
|
|
add_iptables_rule "-A FORWARD -i tun0 -o $NIC_NAME -j ACCEPT"
|
|
add_iptables_rule "-A FORWARD -i $NIC_NAME -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT"
|
|
apt install iptables-persistent -y
|
|
netfilter-persistent save
|
|
|
|
# Settings up helper scripts using Heredoc 'EOF'
|
|
cat << 'EOF' > /usr/local/bin/add-openvpn-client.sh
|
|
#!/bin/bash
|
|
# Make sure script is ran as root
|
|
if [[ $EUID -ne 0 ]]; then
|
|
exec sudo /bin/bash "$0" "$@"
|
|
fi
|
|
|
|
DIR=$(pwd)
|
|
for i in {1..255}; do
|
|
CLIENT_NAME="client$i"
|
|
if [ ! -f "/etc/openvpn/easy-rsa/pki/issued/$CLIENT_NAME.crt" ]; then
|
|
break
|
|
fi
|
|
done
|
|
VPN_SUBNET=$(grep -E '^server ' "/etc/openvpn/myserver.conf" | awk '{print $2}')
|
|
VPN_PUBLIC_HOST=$(grep -E '^#public-host ' "/etc/openvpn/myserver.conf" | awk '{print $2}')
|
|
VPN_PUBLIC_PORT=$(grep -E '^port ' "/etc/openvpn/myserver.conf" | awk '{print $2}')
|
|
echo "Adding VPN client to $VPN_PUBLIC_HOST:$VPN_PUBLIC_PORT"
|
|
read -e -p "Enter client name: " -i "$CLIENT_NAME" CLIENT_NAME
|
|
if [ -f "/etc/openvpn/easy-rsa/pki/issued/$CLIENT_NAME.crt" ]; then
|
|
echo Client $CLIENT_NAME already exists...
|
|
exit 1
|
|
fi
|
|
if grep -q "^auth-user-pass-verify" "/etc/openvpn/myserver.conf"; then
|
|
read -e -p "Enter username: " -i "$CLIENT_USERNAME" CLIENT_USERNAME
|
|
if grep -q "^$CLIENT_USERNAME" "/etc/openvpn/credentials"; then
|
|
echo "Username $CLIENT_USERNAME already exists"
|
|
exit 1
|
|
fi
|
|
read -e -p "Enter password: " -i "$CLIENT_PASSWORD" CLIENT_PASSWORD
|
|
CLIENT_PASSWORD_HASH=$(echo -n "$CLIENT_PASSWORD" | sha256sum | awk '{print $1}')
|
|
echo "$CLIENT_USERNAME:$CLIENT_PASSWORD_HASH:$CLIENT_NAME" >> "/etc/openvpn/credentials"
|
|
EXTRA_CONFIG = "auth-user-pass"
|
|
fi
|
|
read -e -p "Use static IP for this client? VPN subnet is $VPN_SUBNET (Leave empty for dynamic): " -i "" CLIENT_IP
|
|
if [ ! -z "${CLIENT_IP}" ]; then
|
|
echo Setting IP...
|
|
cat > "/etc/openvpn/ccd/$CLIENT_NAME" <<EOL
|
|
ifconfig-push $CLIENT_IP 255.255.255.0
|
|
EOL
|
|
fi
|
|
|
|
cd /etc/openvpn/easy-rsa
|
|
./easyrsa gen-req $CLIENT_NAME nopass
|
|
./easyrsa sign-req client $CLIENT_NAME
|
|
|
|
CA_CERT=$(cat "/etc/openvpn/ca.crt")
|
|
CLIENT_CERT=$(cat "/etc/openvpn/easy-rsa/pki/issued/$CLIENT_NAME.crt")
|
|
CLIENT_KEY=$(cat "/etc/openvpn/easy-rsa/pki/private/$CLIENT_NAME.key")
|
|
TA_KEY=$(cat "/etc/openvpn/ta.key")
|
|
|
|
cd "$DIR"
|
|
cat > $CLIENT_NAME.conf <<EOL
|
|
dev tun
|
|
persist-tun
|
|
persist-key
|
|
cipher AES-256-CBC
|
|
ncp-ciphers AES-256-GCM:AES-128-GCM
|
|
auth SHA1
|
|
tls-client
|
|
client
|
|
resolv-retry infinite
|
|
remote $VPN_PUBLIC_HOST $VPN_PUBLIC_PORT udp
|
|
remote-cert-tls server
|
|
float
|
|
verb 3
|
|
$EXTRA_CONFIG
|
|
|
|
<ca>
|
|
$CA_CERT
|
|
</ca>
|
|
<cert>
|
|
$CLIENT_CERT
|
|
</cert>
|
|
<key>
|
|
$CLIENT_KEY
|
|
</key>
|
|
key-direction 1
|
|
<tls-auth>
|
|
$TA_KEY
|
|
</tls-auth>
|
|
EOL
|
|
EOF
|
|
chmod +755 /usr/local/bin/add-openvpn-client.sh
|
|
|
|
cat << 'EOF' > /usr/local/bin/remove-iptable-dups.sh
|
|
#!/bin/bash
|
|
iptables-save | awk '!seen[$0]++ || /^(\*|COMMIT)/' | iptables-restore
|
|
EOF
|
|
chmod +755 /usr/local/bin/remove-iptable-dups.sh
|
|
|
|
cat << 'EOF' > /etc/openvpn/auth-script.sh
|
|
#!/bin/bash
|
|
readarray -t lines < $1
|
|
username=${lines[0]}
|
|
password=${lines[1]}
|
|
password_hash=$(echo -n "$password" | sha256sum | awk '{print $1}')
|
|
if grep -q "^$username:$password_hash:" "/etc/openvpn/credentials"; then
|
|
exit 0 # Authentication success
|
|
else
|
|
exit 1 # Authentication failed
|
|
fi
|
|
EOF
|
|
chmod +755 /etc/openvpn/auth-script.sh
|