From 944447e31da5fad8fcf727163996f73de6552e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20L=2E=20H=2E-F?= Date: Tue, 7 Feb 2023 18:45:19 +0100 Subject: [PATCH] First upload --- add-client-openvpn.yaml | 14 +++ ansible.cfg | 8 ++ bash/add-client-openvpn.sh | 35 ++++++++ bash/install-openvpn.sh | 156 ++++++++++++++++++++++++++++++++++ bash/revoke-client-openvpn.sh | 19 +++++ install-openvpn.yaml | 5 ++ inventory.ini | 2 + revoke-client-openvpn.yaml | 9 ++ 8 files changed, 248 insertions(+) create mode 100644 add-client-openvpn.yaml create mode 100644 ansible.cfg create mode 100644 bash/add-client-openvpn.sh create mode 100644 bash/install-openvpn.sh create mode 100644 bash/revoke-client-openvpn.sh create mode 100644 install-openvpn.yaml create mode 100644 inventory.ini create mode 100644 revoke-client-openvpn.yaml diff --git a/add-client-openvpn.yaml b/add-client-openvpn.yaml new file mode 100644 index 0000000..e67333a --- /dev/null +++ b/add-client-openvpn.yaml @@ -0,0 +1,14 @@ +- name: Add OpenVPN client + hosts: clubelec_ovh_vm2 + vars_prompt: + - name: client + prompt: Name of the OpenVPN client + private: false + tasks: + - name: Create an .ovpn file for the user + script: ./bash/add-client-openvpn.sh {{ client }} + - name: Retrive .ovpn file + fetch: + src: ./{{ client }}.ovpn + dest: ./{{ client }}.ovpn + flat: yes \ No newline at end of file diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..83ca37a --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,8 @@ +[defaults] +inventory = ./inventory.ini + +[privilege_escalation] +become=True +become_method=sudo +become_ask_pass=True +become_user=root \ No newline at end of file diff --git a/bash/add-client-openvpn.sh b/bash/add-client-openvpn.sh new file mode 100644 index 0000000..a03f265 --- /dev/null +++ b/bash/add-client-openvpn.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Get username +USER=$1 + +# Get current folder +FOLDER=$(pwd) + +# Add user +USEREXISTS=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -c -E "/CN=$USER\$") +if [[ $USEREXISTS == '1' ]]; then + exit 0 +else + cd /etc/openvpn/easy-rsa/ || return + ./easyrsa --batch build-client-full "$USER" nopass +fi + +cd "$FOLDER" || exit + +# Generate client file +cp /etc/openvpn/client-template.txt "$FOLDER/$USER.ovpn" +{ + echo "" + cat "/etc/openvpn/easy-rsa/pki/ca.crt" + echo "" + echo "" + awk '/BEGIN/,/END CERTIFICATE/' "/etc/openvpn/easy-rsa/pki/issued/$USER.crt" + echo "" + echo "" + cat "/etc/openvpn/easy-rsa/pki/private/$USER.key" + echo "" + echo "" + cat /etc/openvpn/tls-crypt.key + echo "" +} >>"$FOLDER/$USER.ovpn" diff --git a/bash/install-openvpn.sh b/bash/install-openvpn.sh new file mode 100644 index 0000000..94b76ab --- /dev/null +++ b/bash/install-openvpn.sh @@ -0,0 +1,156 @@ +#!/bin/bash + +IP=$(curl -s https://ifconfig.me) +PORT=443 +PROTOCOL=tcp + +# Get the "public" interface from the default route +NIC=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1) + +# Install OpenVPN +apt-get install -y openvpn wget curl + +# Install the latest version of easy-rsa from source +wget -O ~/easy-rsa.tgz https://github.com/OpenVPN/easy-rsa/releases/download/v3.1.2/EasyRSA-3.1.2.tgz +mkdir -p /etc/openvpn/easy-rsa +tar xzf ~/easy-rsa.tgz --strip-components=1 --no-same-owner --directory /etc/openvpn/easy-rsa +rm -f ~/easy-rsa.tgz +cd /etc/openvpn/easy-rsa/ || return +echo "set_var EASYRSA_ALGO ec" >/etc/openvpn/easy-rsa/pki/vars +echo "set_var EASYRSA_CURVE prime256v1" >>/etc/openvpn/easy-rsa/pki/vars + +# Generate a random, alphanumeric identifier of 16 characters for CN and one for server name +SERVER_CN="cn_$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)" +SERVER_NAME="server_$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)" + +# Create the PKI, set up the CA, the DH params and the server certificate +./easyrsa init-pki +./easyrsa --batch --req-cn="$SERVER_CN" build-ca nopass +./easyrsa --batch build-server-full "$SERVER_NAME" nopass +EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl +openvpn --genkey --secret /etc/openvpn/tls-crypt.key + +# Move all the generated files +cp pki/ca.crt pki/private/ca.key "pki/issued/$SERVER_NAME.crt" "pki/private/$SERVER_NAME.key" /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn + +# Make cert revocation list readable for non-root +chmod 644 /etc/openvpn/crl.pem + +# Generate server.conf +echo "port $PORT" >/etc/openvpn/server.conf +echo "proto $PROTOCOL" >>/etc/openvpn/server.conf +echo "dev tun +user nobody +group nogroup +persist-key +persist-tun +keepalive 10 120 +topology subnet +server 10.8.0.0 255.255.255.0 +ifconfig-pool-persist ipp.txt" >>/etc/openvpn/server.conf +sed -ne 's/^nameserver[[:space:]]\+\([^[:space:]]\+\).*$/\1/p' '/etc/resolv.conf' | while read -r line; do + echo "push \"dhcp-option DNS $line\"" >>/etc/openvpn/server.conf +done +echo "push \"redirect-gateway def1 bypass-dhcp\" +dh none +ecdh-curve prime256v1 +tls-crypt tls-crypt.key +crl-verify crl.pem +ca ca.crt +cert $SERVER_NAME.crt +key $SERVER_NAME.key +auth SHA256 +cipher AES-128-GCM +ncp-ciphers AES-128-GCM +tls-server +tls-version-min 1.2 +tls-cipher TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 +client-config-dir /etc/openvpn/ccd +status /var/log/openvpn/status.log +verb 3" >>/etc/openvpn/server.conf + +# Create client-config-dir dir +mkdir -p /etc/openvpn/ccd + +# Create log dir +mkdir -p /var/log/openvpn + +# Enable routing +echo 'net.ipv4.ip_forward=1' >/etc/sysctl.d/99-openvpn.conf + +# Apply sysctl rules +sysctl --system + +# Don't modify package-provided service +cp /lib/systemd/system/openvpn\@.service /etc/systemd/system/openvpn\@.service + +# Workaround to fix OpenVPN service on OpenVZ +sed -i 's|LimitNPROC|#LimitNPROC|' /etc/systemd/system/openvpn\@.service + +# Another workaround to keep using /etc/openvpn/ +sed -i 's|/etc/openvpn/server|/etc/openvpn|' /etc/systemd/system/openvpn\@.service + +systemctl daemon-reload +systemctl enable openvpn@server +systemctl restart openvpn@server + +# Add iptables rules in two scripts +mkdir -p /opt/holepunch-openvpn-iptables + +# Script to add rules +echo "#!/bin/sh +iptables -t nat -I POSTROUTING 1 -s 10.8.0.0/24 -o $NIC -j MASQUERADE +iptables -I INPUT 1 -i tun0 -j ACCEPT +iptables -I FORWARD 1 -i $NIC -o tun0 -j ACCEPT +iptables -I FORWARD 1 -i tun0 -o $NIC -j ACCEPT +iptables -I INPUT 1 -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" >/opt/holepunch-openvpn-iptables/add-openvpn-rules.sh + +# Script to remove rules +echo "#!/bin/sh +iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o $NIC -j MASQUERADE +iptables -D INPUT -i tun0 -j ACCEPT +iptables -D FORWARD -i $NIC -o tun0 -j ACCEPT +iptables -D FORWARD -i tun0 -o $NIC -j ACCEPT +iptables -D INPUT -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT" >/opt/holepunch-openvpn-iptables/remove-openvpn-rules.sh + +chmod +x /opt/holepunch-openvpn-iptables/add-openvpn-rules.sh +chmod +x /opt/holepunch-openvpn-iptables/remove-openvpn-rules.sh + +# Handle the rules via a systemd script +echo "[Unit] +Description=iptables rules for OpenVPN +Before=network-online.target +Wants=network-online.target +[Service] +Type=oneshot +ExecStart=/opt/holepunch-openvpn-iptables/add-openvpn-rules.sh +ExecStop=/opt/holepunch-openvpn-iptables/remove-openvpn-rules.sh +RemainAfterExit=yes +[Install] +WantedBy=multi-user.target" >/etc/systemd/system/holepunch-openvpn-iptables.service + +# Enable service and apply rules +systemctl daemon-reload +systemctl enable holepunch-openvpn-iptables +systemctl start holepunch-openvpn-iptables + +# Generate a template for client +echo "client +proto tcp-client +remote $IP $PORT +dev tun +resolv-retry infinite +nobind +persist-key +persist-tun +remote-cert-tls server +verify-x509-name $SERVER_NAME name +auth SHA256 +auth-nocache +cipher AES-128-GCM +tls-client +tls-version-min 1.2 +tls-cipher TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 +ignore-unknown-option block-outside-dns +setenv opt block-outside-dns # Prevent Windows 10 DNS leak +verb 3" >>/etc/openvpn/client-template.txt diff --git a/bash/revoke-client-openvpn.sh b/bash/revoke-client-openvpn.sh new file mode 100644 index 0000000..1ad6b0f --- /dev/null +++ b/bash/revoke-client-openvpn.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Get username +USER=$1 + +# Get current folder +FOLDER=$(pwd) + +# Remove user +cd /etc/openvpn/easy-rsa/ || return +./easyrsa --batch revoke "$USER" +EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl +rm -f /etc/openvpn/crl.pem +cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem +chmod 644 /etc/openvpn/crl.pem +rm "$FOLDER/$USER.ovpn" +sed -i "/^$USER,.*/d" /etc/openvpn/ipp.txt +cp /etc/openvpn/easy-rsa/pki/index.txt{,.bk} +exit diff --git a/install-openvpn.yaml b/install-openvpn.yaml new file mode 100644 index 0000000..80e6b9a --- /dev/null +++ b/install-openvpn.yaml @@ -0,0 +1,5 @@ +- name: Install OpenVPN + hosts: clubelec_ovh_vm2 + tasks: + - name: Copy and execute bash script + script: ./bash/install-openvpn.sh \ No newline at end of file diff --git a/inventory.ini b/inventory.ini new file mode 100644 index 0000000..2c6005b --- /dev/null +++ b/inventory.ini @@ -0,0 +1,2 @@ +[clubelec_ovh_vm2] +clubelec-ovh-vm2 \ No newline at end of file diff --git a/revoke-client-openvpn.yaml b/revoke-client-openvpn.yaml new file mode 100644 index 0000000..4c366da --- /dev/null +++ b/revoke-client-openvpn.yaml @@ -0,0 +1,9 @@ +- name: Revoke OpenVPN client + hosts: clubelec_ovh_vm2 + vars_prompt: + - name: client + prompt: Name of the OpenVPN client to revoke + private: false + tasks: + - name: Revoke OpenVPN client + script: ./bash/revoke-client-openvpn.sh {{ client }} \ No newline at end of file