From 44c995df8e9cdd018872cbba79bddb3164849de5 Mon Sep 17 00:00:00 2001 From: Stanislas Date: Fri, 12 Dec 2025 22:09:18 +0100 Subject: [PATCH] feat: migrate to OpenVPN 2.4+ directory structure and improve distro compatibility (#1364) ## Summary Migrates OpenVPN configuration to use the modern OpenVPN 2.4+ directory structure and improves compatibility across different Linux distributions. Close https://github.com/angristan/openvpn-install/issues/1307, close https://github.com/angristan/openvpn-install/issues/788, close https://github.com/angristan/openvpn-install/issues/605, close https://github.com/angristan/openvpn-install/pull/653, close https://github.com/angristan/openvpn-install/issues/1214 ### Directory Structure Changes - All server files now in `/etc/openvpn/server/` instead of `/etc/openvpn/` - Uses `openvpn-server@server.service` consistently across all distros - `server.conf` uses relative paths for portability ### Distro-Specific User/Group Handling Different distros configure OpenVPN differently: | Distro | User | Group | systemd handles user? | |--------|------|-------|----------------------| | Debian/Ubuntu | nobody | nogroup | No | | Fedora/RHEL/Amazon | openvpn | openvpn | No | | Arch | openvpn | network | **Yes** (via `User=` in service) | The script now: 1. Detects if an `openvpn` user exists and uses appropriate group 2. Checks if systemd service already has `User=` directive 3. Skips `user`/`group` in config when systemd handles it (avoids "double privilege drop" error on Arch) 4. Sets file ownership with `chown -R` for non-root OpenVPN users ### Other Changes - Updated FAQ.md with new paths - Added systemd service file validation in tests - Added CRL reload verification in tests --- FAQ.md | 8 +- openvpn-install.sh | 321 +++++++++++++++++++++----------------- test/server-entrypoint.sh | 131 +++++++++++----- 3 files changed, 273 insertions(+), 187 deletions(-) diff --git a/FAQ.md b/FAQ.md index 12dc709..f05bfdb 100644 --- a/FAQ.md +++ b/FAQ.md @@ -71,7 +71,7 @@ down /usr/share/openvpn/contrib/pull-resolv-conf/client.down - AES CBC - tls-auth -If your client is <2.3.3, remove `tls-version-min 1.2` from your `/etc/openvpn/server.conf` and `.ovpn` files. +If your client is <2.3.3, remove `tls-version-min 1.2` from your `/etc/openvpn/server/server.conf` and `.ovpn` files. --- @@ -117,7 +117,7 @@ Sysctl options are at `/etc/sysctl.d/99-openvpn.conf` **Q:** How can I access computers the OpenVPN server's remote LAN? -**A:** Add a route with the subnet of the remote network to `/etc/openvpn/server.conf` and restart OpenVPN. Example: `push "route 192.168.1.0 255.255.255.0"` if the server's LAN is `192.168.1.0/24` +**A:** Add a route with the subnet of the remote network to `/etc/openvpn/server/server.conf` and restart OpenVPN. Example: `push "route 192.168.1.0 255.255.255.0"` if the server's LAN is `192.168.1.0/24` --- @@ -145,13 +145,13 @@ done < users.txt **Q:** How do I change the default `.ovpn` file created for future clients? -**A:** You can edit the template out of which `.ovpn` files are created by editing `/etc/openvpn/client-template.txt` +**A:** You can edit the template out of which `.ovpn` files are created by editing `/etc/openvpn/server/client-template.txt` --- **Q:** For my clients - I want to set my internal network to pass through the VPN and the rest to go through my internet? -**A:** You would need to edit the `.ovpn` file. You can edit the template out of which those files are created by editing `/etc/openvpn/client-template.txt` file and adding +**A:** You would need to edit the `.ovpn` file. You can edit the template out of which those files are created by editing `/etc/openvpn/server/client-template.txt` file and adding ```sh route-nopull diff --git a/openvpn-install.sh b/openvpn-install.sh index c625ee6..a84bb06 100755 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -970,7 +970,7 @@ function installOpenVPN() { # If OpenVPN isn't installed yet, install it. This script is more-or-less # idempotent on multiple runs, but will only install OpenVPN from upstream # the first time. - if [[ ! -e /etc/openvpn/server.conf ]]; then + if [[ ! -e /etc/openvpn/server/server.conf ]]; then log_header "Installing OpenVPN" # Setup official OpenVPN repository for latest versions @@ -1015,21 +1015,45 @@ function installOpenVPN() { log_info "Data Channel Offload (DCO) is not available (requires OpenVPN 2.6+ and kernel support)" fi + # Create the server directory (OpenVPN 2.4+ directory structure) + run_cmd "Creating server directory" mkdir -p /etc/openvpn/server + # An old version of easy-rsa was available by default in some openvpn packages - if [[ -d /etc/openvpn/easy-rsa/ ]]; then - run_cmd "Removing old Easy-RSA" rm -rf /etc/openvpn/easy-rsa/ + if [[ -d /etc/openvpn/server/easy-rsa/ ]]; then + run_cmd "Removing old Easy-RSA" rm -rf /etc/openvpn/server/easy-rsa/ fi fi - # Find out if the machine uses nogroup or nobody for the permissionless group - if grep -qs "^nogroup:" /etc/group; then - NOGROUP=nogroup + # Determine which user/group OpenVPN should run as + # - Fedora/RHEL/Amazon create 'openvpn' user with 'openvpn' group + # - Arch creates 'openvpn' user with 'network' group + # - Debian/Ubuntu/openSUSE don't create a dedicated user, use 'nobody' + # + # Also check if the systemd service file already handles user/group switching. + # If so, we shouldn't add user/group to config (would cause double privilege drop). + SYSTEMD_HANDLES_USER=false + for service_file in /usr/lib/systemd/system/openvpn-server@.service /lib/systemd/system/openvpn-server@.service; do + if [[ -f "$service_file" ]] && grep -q "^User=" "$service_file"; then + SYSTEMD_HANDLES_USER=true + break + fi + done + + if id openvpn &>/dev/null; then + OPENVPN_USER=openvpn + # Get the openvpn user's primary group (e.g., 'openvpn' on Fedora, 'network' on Arch) + OPENVPN_GROUP=$(id -gn openvpn 2>/dev/null || echo openvpn) else - NOGROUP=nobody + OPENVPN_USER=nobody + if grep -qs "^nogroup:" /etc/group; then + OPENVPN_GROUP=nogroup + else + OPENVPN_GROUP=nobody + fi fi # Install the latest version of easy-rsa from source, if not already installed. - if [[ ! -d /etc/openvpn/easy-rsa/ ]]; then + if [[ ! -d /etc/openvpn/server/easy-rsa/ ]]; then run_cmd "Downloading Easy-RSA v${EASYRSA_VERSION}" curl -fL --retry 5 -o ~/easy-rsa.tgz "https://github.com/OpenVPN/easy-rsa/releases/download/v${EASYRSA_VERSION}/EasyRSA-${EASYRSA_VERSION}.tgz" log_info "Verifying Easy-RSA checksum..." CHECKSUM_OUTPUT=$(echo "${EASYRSA_SHA256} $HOME/easy-rsa.tgz" | sha256sum -c 2>&1) || { @@ -1038,11 +1062,11 @@ function installOpenVPN() { log_fatal "SHA256 checksum verification failed for easy-rsa download!" } _log_to_file "[CHECKSUM] $CHECKSUM_OUTPUT" - run_cmd "Creating Easy-RSA directory" mkdir -p /etc/openvpn/easy-rsa - run_cmd "Extracting Easy-RSA" tar xzf ~/easy-rsa.tgz --strip-components=1 --no-same-owner --directory /etc/openvpn/easy-rsa + run_cmd "Creating Easy-RSA directory" mkdir -p /etc/openvpn/server/easy-rsa + run_cmd "Extracting Easy-RSA" tar xzf ~/easy-rsa.tgz --strip-components=1 --no-same-owner --directory /etc/openvpn/server/easy-rsa run_cmd "Cleaning up archive" rm -f ~/easy-rsa.tgz - cd /etc/openvpn/easy-rsa/ || return + cd /etc/openvpn/server/easy-rsa/ || return case $CERT_TYPE in 1) echo "set_var EASYRSA_ALGO ec" >vars @@ -1081,55 +1105,58 @@ function installOpenVPN() { case $TLS_SIG in 1) # Generate tls-crypt key - run_cmd "Generating tls-crypt key" openvpn --genkey --secret /etc/openvpn/tls-crypt.key + run_cmd "Generating tls-crypt key" openvpn --genkey --secret /etc/openvpn/server/tls-crypt.key ;; 2) # Generate tls-auth key - run_cmd "Generating tls-auth key" openvpn --genkey --secret /etc/openvpn/tls-auth.key + run_cmd "Generating tls-auth key" openvpn --genkey --secret /etc/openvpn/server/tls-auth.key ;; esac else # If easy-rsa is already installed, grab the generated SERVER_NAME # for client configs - cd /etc/openvpn/easy-rsa/ || return + cd /etc/openvpn/server/easy-rsa/ || return SERVER_NAME=$(cat SERVER_NAME_GENERATED) fi # Move all the generated files log_info "Copying certificates..." - run_cmd "Copying certificates to /etc/openvpn" 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 + run_cmd "Copying certificates to /etc/openvpn/server" cp pki/ca.crt pki/private/ca.key "pki/issued/$SERVER_NAME.crt" "pki/private/$SERVER_NAME.key" /etc/openvpn/server/easy-rsa/pki/crl.pem /etc/openvpn/server if [[ $DH_TYPE == "2" ]]; then - run_cmd "Copying DH parameters" cp dh.pem /etc/openvpn + run_cmd "Copying DH parameters" cp dh.pem /etc/openvpn/server fi # Make cert revocation list readable for non-root - run_cmd "Setting CRL permissions" chmod 644 /etc/openvpn/crl.pem + run_cmd "Setting CRL permissions" chmod 644 /etc/openvpn/server/crl.pem # Generate server.conf log_info "Generating server configuration..." - echo "port $PORT" >/etc/openvpn/server.conf + echo "port $PORT" >/etc/openvpn/server/server.conf if [[ $IPV6_SUPPORT == 'n' ]]; then - echo "proto $PROTOCOL" >>/etc/openvpn/server.conf + echo "proto $PROTOCOL" >>/etc/openvpn/server/server.conf elif [[ $IPV6_SUPPORT == 'y' ]]; then - echo "proto ${PROTOCOL}6" >>/etc/openvpn/server.conf + echo "proto ${PROTOCOL}6" >>/etc/openvpn/server/server.conf fi if [[ $MULTI_CLIENT == "y" ]]; then - echo "duplicate-cn" >>/etc/openvpn/server.conf + echo "duplicate-cn" >>/etc/openvpn/server/server.conf fi - echo "dev tun -user nobody -group $NOGROUP -persist-key + echo "dev tun" >>/etc/openvpn/server/server.conf + # Only add user/group if systemd doesn't handle it (avoids double privilege drop) + if [[ $SYSTEMD_HANDLES_USER == "false" ]]; then + echo "user $OPENVPN_USER +group $OPENVPN_GROUP" >>/etc/openvpn/server/server.conf + fi + echo "persist-key persist-tun keepalive 10 120 topology subnet -server 10.8.0.0 255.255.255.0" >>/etc/openvpn/server.conf +server 10.8.0.0 255.255.255.0" >>/etc/openvpn/server/server.conf # ifconfig-pool-persist is incompatible with duplicate-cn if [[ $MULTI_CLIENT != "y" ]]; then - echo "ifconfig-pool-persist ipp.txt" >>/etc/openvpn/server.conf + echo "ifconfig-pool-persist ipp.txt" >>/etc/openvpn/server/server.conf fi # DNS resolvers @@ -1146,64 +1173,64 @@ server 10.8.0.0 255.255.255.0" >>/etc/openvpn/server.conf sed -ne 's/^nameserver[[:space:]]\+\([^[:space:]]\+\).*$/\1/p' $RESOLVCONF | while read -r line; do # Copy, if it's a IPv4 |or| if IPv6 is enabled, IPv4/IPv6 does not matter if [[ $line =~ ^[0-9.]*$ ]] || [[ $IPV6_SUPPORT == 'y' ]]; then - echo "push \"dhcp-option DNS $line\"" >>/etc/openvpn/server.conf + echo "push \"dhcp-option DNS $line\"" >>/etc/openvpn/server/server.conf fi done ;; 2) # Self-hosted DNS resolver (Unbound) - echo 'push "dhcp-option DNS 10.8.0.1"' >>/etc/openvpn/server.conf + echo 'push "dhcp-option DNS 10.8.0.1"' >>/etc/openvpn/server/server.conf if [[ $IPV6_SUPPORT == 'y' ]]; then - echo 'push "dhcp-option DNS fd42:42:42:42::1"' >>/etc/openvpn/server.conf + echo 'push "dhcp-option DNS fd42:42:42:42::1"' >>/etc/openvpn/server/server.conf fi ;; 3) # Cloudflare - echo 'push "dhcp-option DNS 1.0.0.1"' >>/etc/openvpn/server.conf - echo 'push "dhcp-option DNS 1.1.1.1"' >>/etc/openvpn/server.conf + echo 'push "dhcp-option DNS 1.0.0.1"' >>/etc/openvpn/server/server.conf + echo 'push "dhcp-option DNS 1.1.1.1"' >>/etc/openvpn/server/server.conf ;; 4) # Quad9 - echo 'push "dhcp-option DNS 9.9.9.9"' >>/etc/openvpn/server.conf - echo 'push "dhcp-option DNS 149.112.112.112"' >>/etc/openvpn/server.conf + echo 'push "dhcp-option DNS 9.9.9.9"' >>/etc/openvpn/server/server.conf + echo 'push "dhcp-option DNS 149.112.112.112"' >>/etc/openvpn/server/server.conf ;; 5) # Quad9 uncensored - echo 'push "dhcp-option DNS 9.9.9.10"' >>/etc/openvpn/server.conf - echo 'push "dhcp-option DNS 149.112.112.10"' >>/etc/openvpn/server.conf + echo 'push "dhcp-option DNS 9.9.9.10"' >>/etc/openvpn/server/server.conf + echo 'push "dhcp-option DNS 149.112.112.10"' >>/etc/openvpn/server/server.conf ;; 6) # FDN - echo 'push "dhcp-option DNS 80.67.169.40"' >>/etc/openvpn/server.conf - echo 'push "dhcp-option DNS 80.67.169.12"' >>/etc/openvpn/server.conf + echo 'push "dhcp-option DNS 80.67.169.40"' >>/etc/openvpn/server/server.conf + echo 'push "dhcp-option DNS 80.67.169.12"' >>/etc/openvpn/server/server.conf ;; 7) # DNS.WATCH - echo 'push "dhcp-option DNS 84.200.69.80"' >>/etc/openvpn/server.conf - echo 'push "dhcp-option DNS 84.200.70.40"' >>/etc/openvpn/server.conf + echo 'push "dhcp-option DNS 84.200.69.80"' >>/etc/openvpn/server/server.conf + echo 'push "dhcp-option DNS 84.200.70.40"' >>/etc/openvpn/server/server.conf ;; 8) # OpenDNS - echo 'push "dhcp-option DNS 208.67.222.222"' >>/etc/openvpn/server.conf - echo 'push "dhcp-option DNS 208.67.220.220"' >>/etc/openvpn/server.conf + echo 'push "dhcp-option DNS 208.67.222.222"' >>/etc/openvpn/server/server.conf + echo 'push "dhcp-option DNS 208.67.220.220"' >>/etc/openvpn/server/server.conf ;; 9) # Google - echo 'push "dhcp-option DNS 8.8.8.8"' >>/etc/openvpn/server.conf - echo 'push "dhcp-option DNS 8.8.4.4"' >>/etc/openvpn/server.conf + echo 'push "dhcp-option DNS 8.8.8.8"' >>/etc/openvpn/server/server.conf + echo 'push "dhcp-option DNS 8.8.4.4"' >>/etc/openvpn/server/server.conf ;; 10) # Yandex Basic - echo 'push "dhcp-option DNS 77.88.8.8"' >>/etc/openvpn/server.conf - echo 'push "dhcp-option DNS 77.88.8.1"' >>/etc/openvpn/server.conf + echo 'push "dhcp-option DNS 77.88.8.8"' >>/etc/openvpn/server/server.conf + echo 'push "dhcp-option DNS 77.88.8.1"' >>/etc/openvpn/server/server.conf ;; 11) # AdGuard DNS - echo 'push "dhcp-option DNS 94.140.14.14"' >>/etc/openvpn/server.conf - echo 'push "dhcp-option DNS 94.140.15.15"' >>/etc/openvpn/server.conf + echo 'push "dhcp-option DNS 94.140.14.14"' >>/etc/openvpn/server/server.conf + echo 'push "dhcp-option DNS 94.140.15.15"' >>/etc/openvpn/server/server.conf ;; 12) # NextDNS - echo 'push "dhcp-option DNS 45.90.28.167"' >>/etc/openvpn/server.conf - echo 'push "dhcp-option DNS 45.90.30.167"' >>/etc/openvpn/server.conf + echo 'push "dhcp-option DNS 45.90.28.167"' >>/etc/openvpn/server/server.conf + echo 'push "dhcp-option DNS 45.90.30.167"' >>/etc/openvpn/server/server.conf ;; 13) # Custom DNS - echo "push \"dhcp-option DNS $DNS1\"" >>/etc/openvpn/server.conf + echo "push \"dhcp-option DNS $DNS1\"" >>/etc/openvpn/server/server.conf if [[ $DNS2 != "" ]]; then - echo "push \"dhcp-option DNS $DNS2\"" >>/etc/openvpn/server.conf + echo "push \"dhcp-option DNS $DNS2\"" >>/etc/openvpn/server/server.conf fi ;; esac - echo 'push "redirect-gateway def1 bypass-dhcp"' >>/etc/openvpn/server.conf + echo 'push "redirect-gateway def1 bypass-dhcp"' >>/etc/openvpn/server/server.conf # IPv6 network settings if needed if [[ $IPV6_SUPPORT == 'y' ]]; then @@ -1211,26 +1238,26 @@ server 10.8.0.0 255.255.255.0" >>/etc/openvpn/server.conf tun-ipv6 push tun-ipv6 push "route-ipv6 2000::/3" -push "redirect-gateway ipv6"' >>/etc/openvpn/server.conf +push "redirect-gateway ipv6"' >>/etc/openvpn/server/server.conf fi if [[ $COMPRESSION_ENABLED == "y" ]]; then - echo "compress $COMPRESSION_ALG" >>/etc/openvpn/server.conf + echo "compress $COMPRESSION_ALG" >>/etc/openvpn/server/server.conf fi if [[ $DH_TYPE == "1" ]]; then - echo "dh none" >>/etc/openvpn/server.conf - echo "ecdh-curve $DH_CURVE" >>/etc/openvpn/server.conf + echo "dh none" >>/etc/openvpn/server/server.conf + echo "ecdh-curve $DH_CURVE" >>/etc/openvpn/server/server.conf elif [[ $DH_TYPE == "2" ]]; then - echo "dh dh.pem" >>/etc/openvpn/server.conf + echo "dh dh.pem" >>/etc/openvpn/server/server.conf fi case $TLS_SIG in 1) - echo "tls-crypt tls-crypt.key" >>/etc/openvpn/server.conf + echo "tls-crypt tls-crypt.key" >>/etc/openvpn/server/server.conf ;; 2) - echo "tls-auth tls-auth.key 0" >>/etc/openvpn/server.conf + echo "tls-auth tls-auth.key 0" >>/etc/openvpn/server/server.conf ;; esac @@ -1247,15 +1274,23 @@ tls-server tls-version-min 1.2 remote-cert-tls client tls-cipher $CC_CIPHER -client-config-dir /etc/openvpn/ccd +client-config-dir ccd status /var/log/openvpn/status.log -verb 3" >>/etc/openvpn/server.conf +verb 3" >>/etc/openvpn/server/server.conf # Create client-config-dir dir - run_cmd "Creating client config directory" mkdir -p /etc/openvpn/ccd + run_cmd "Creating client config directory" mkdir -p /etc/openvpn/server/ccd # Create log dir run_cmd "Creating log directory" mkdir -p /var/log/openvpn + # On distros that use a dedicated OpenVPN user (not "nobody"), e.g., Fedora, RHEL, Arch, + # set ownership so OpenVPN can read config/certs and write to log directory + if [[ $OPENVPN_USER != "nobody" ]]; then + log_info "Setting ownership for OpenVPN user..." + chown -R "$OPENVPN_USER:$OPENVPN_GROUP" /etc/openvpn/server + chown "$OPENVPN_USER:$OPENVPN_GROUP" /var/log/openvpn + fi + # Enable routing log_info "Enabling IP forwarding..." run_cmd "Creating sysctl.d directory" mkdir -p /etc/sysctl.d @@ -1276,33 +1311,41 @@ verb 3" >>/etc/openvpn/server.conf fi # Finally, restart and enable OpenVPN + # OpenVPN 2.4+ uses openvpn-server@.service with config in /etc/openvpn/server/ log_info "Configuring OpenVPN service..." - if [[ $OS == 'arch' || $OS == 'fedora' || $OS == 'centos' || $OS == 'oracle' || $OS == 'amzn2023' ]]; then - # Don't modify package-provided service - run_cmd "Copying OpenVPN service file" cp /usr/lib/systemd/system/openvpn-server@.service /etc/systemd/system/openvpn-server@.service - # Workaround to fix OpenVPN service on OpenVZ - run_cmd "Patching service file (LimitNPROC)" sed -i 's|LimitNPROC|#LimitNPROC|' /etc/systemd/system/openvpn-server@.service - # Another workaround to keep using /etc/openvpn/ - run_cmd "Patching service file (paths)" sed -i 's|/etc/openvpn/server|/etc/openvpn|' /etc/systemd/system/openvpn-server@.service - - run_cmd "Reloading systemd" systemctl daemon-reload - run_cmd "Enabling OpenVPN service" systemctl enable openvpn-server@server - run_cmd "Starting OpenVPN service" systemctl restart openvpn-server@server + # Find the service file (location and name vary by distro) + # Modern distros: openvpn-server@.service in /usr/lib/systemd/system/ or /lib/systemd/system/ + # openSUSE: openvpn@.service (old-style) that we need to adapt + if [[ -f /usr/lib/systemd/system/openvpn-server@.service ]]; then + SERVICE_SOURCE="/usr/lib/systemd/system/openvpn-server@.service" + elif [[ -f /lib/systemd/system/openvpn-server@.service ]]; then + SERVICE_SOURCE="/lib/systemd/system/openvpn-server@.service" + elif [[ -f /usr/lib/systemd/system/openvpn@.service ]]; then + # openSUSE uses old-style service, we'll create our own openvpn-server@.service + SERVICE_SOURCE="/usr/lib/systemd/system/openvpn@.service" + elif [[ -f /lib/systemd/system/openvpn@.service ]]; then + SERVICE_SOURCE="/lib/systemd/system/openvpn@.service" else - # Don't modify package-provided service - run_cmd "Copying OpenVPN service file" cp /lib/systemd/system/openvpn\@.service /etc/systemd/system/openvpn\@.service - - # Workaround to fix OpenVPN service on OpenVZ - run_cmd "Patching service file (LimitNPROC)" sed -i 's|LimitNPROC|#LimitNPROC|' /etc/systemd/system/openvpn\@.service - # Another workaround to keep using /etc/openvpn/ - run_cmd "Patching service file (paths)" sed -i 's|/etc/openvpn/server|/etc/openvpn|' /etc/systemd/system/openvpn\@.service - - run_cmd "Reloading systemd" systemctl daemon-reload - run_cmd "Enabling OpenVPN service" systemctl enable openvpn@server - run_cmd "Starting OpenVPN service" systemctl restart openvpn@server + log_fatal "Could not find openvpn-server@.service or openvpn@.service file" fi + # Don't modify package-provided service, copy to /etc/systemd/system/ + run_cmd "Copying OpenVPN service file" cp "$SERVICE_SOURCE" /etc/systemd/system/openvpn-server@.service + + # Workaround to fix OpenVPN service on OpenVZ + run_cmd "Patching service file (LimitNPROC)" sed -i 's|LimitNPROC|#LimitNPROC|' /etc/systemd/system/openvpn-server@.service + + # Ensure the service uses /etc/openvpn/server/ as working directory + # This is needed for openSUSE which uses old-style paths by default + if grep -q "cd /etc/openvpn/" /etc/systemd/system/openvpn-server@.service; then + run_cmd "Patching service file (paths)" sed -i 's|/etc/openvpn/|/etc/openvpn/server/|g' /etc/systemd/system/openvpn-server@.service + fi + + run_cmd "Reloading systemd" systemctl daemon-reload + run_cmd "Enabling OpenVPN service" systemctl enable openvpn-server@server + run_cmd "Starting OpenVPN service" systemctl restart openvpn-server@server + if [[ $DNS == 2 ]]; then installUnbound fi @@ -1373,12 +1416,12 @@ WantedBy=multi-user.target" >/etc/systemd/system/iptables-openvpn.service # client-template.txt is created so we have a template to add further users later log_info "Creating client template..." - echo "client" >/etc/openvpn/client-template.txt + echo "client" >/etc/openvpn/server/client-template.txt if [[ $PROTOCOL == 'udp' ]]; then - echo "proto udp" >>/etc/openvpn/client-template.txt - echo "explicit-exit-notify" >>/etc/openvpn/client-template.txt + echo "proto udp" >>/etc/openvpn/server/client-template.txt + echo "explicit-exit-notify" >>/etc/openvpn/server/client-template.txt elif [[ $PROTOCOL == 'tcp' ]]; then - echo "proto tcp-client" >>/etc/openvpn/client-template.txt + echo "proto tcp-client" >>/etc/openvpn/server/client-template.txt fi echo "remote $IP $PORT dev tun @@ -1399,10 +1442,10 @@ tls-version-min 1.2 tls-cipher $CC_CIPHER ignore-unknown-option block-outside-dns setenv opt block-outside-dns # Prevent Windows 10 DNS leak -verb 3" >>/etc/openvpn/client-template.txt +verb 3" >>/etc/openvpn/server/client-template.txt if [[ $COMPRESSION_ENABLED == "y" ]]; then - echo "compress $COMPRESSION_ALG" >>/etc/openvpn/client-template.txt + echo "compress $COMPRESSION_ALG" >>/etc/openvpn/server/client-template.txt fi # Generate the custom client.ovpn @@ -1431,9 +1474,9 @@ function getHomeDir() { function regenerateCRL() { export EASYRSA_CRL_DAYS=$DEFAULT_CRL_VALIDITY_DURATION_DAYS run_cmd "Regenerating CRL" ./easyrsa gen-crl - run_cmd "Removing old CRL" rm -f /etc/openvpn/crl.pem - run_cmd "Copying new CRL" cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem - run_cmd "Setting CRL permissions" chmod 644 /etc/openvpn/crl.pem + run_cmd "Removing old CRL" rm -f /etc/openvpn/server/crl.pem + run_cmd "Copying new CRL" cp /etc/openvpn/server/easy-rsa/pki/crl.pem /etc/openvpn/server/crl.pem + run_cmd "Setting CRL permissions" chmod 644 /etc/openvpn/server/crl.pem } # Helper function to generate .ovpn client config file @@ -1443,37 +1486,37 @@ function generateClientConfig() { # Determine if we use tls-auth or tls-crypt local tls_sig="" - if grep -qs "^tls-crypt" /etc/openvpn/server.conf; then + if grep -qs "^tls-crypt" /etc/openvpn/server/server.conf; then tls_sig="1" - elif grep -qs "^tls-auth" /etc/openvpn/server.conf; then + elif grep -qs "^tls-auth" /etc/openvpn/server/server.conf; then tls_sig="2" fi # Generate the custom client.ovpn - run_cmd "Creating client config" cp /etc/openvpn/client-template.txt "$home_dir/$client.ovpn" + run_cmd "Creating client config" cp /etc/openvpn/server/client-template.txt "$home_dir/$client.ovpn" { echo "" - cat "/etc/openvpn/easy-rsa/pki/ca.crt" + cat "/etc/openvpn/server/easy-rsa/pki/ca.crt" echo "" echo "" - awk '/BEGIN/,/END CERTIFICATE/' "/etc/openvpn/easy-rsa/pki/issued/$client.crt" + awk '/BEGIN/,/END CERTIFICATE/' "/etc/openvpn/server/easy-rsa/pki/issued/$client.crt" echo "" echo "" - cat "/etc/openvpn/easy-rsa/pki/private/$client.key" + cat "/etc/openvpn/server/easy-rsa/pki/private/$client.key" echo "" case $tls_sig in 1) echo "" - cat /etc/openvpn/tls-crypt.key + cat /etc/openvpn/server/tls-crypt.key echo "" ;; 2) echo "key-direction 1" echo "" - cat /etc/openvpn/tls-auth.key + cat /etc/openvpn/server/tls-auth.key echo "" ;; esac @@ -1490,7 +1533,7 @@ function selectClient() { local show_expiry="${1:-false}" local client_number - NUMBEROFCLIENTS=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -c "^V") + NUMBEROFCLIENTS=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -c "^V") if [[ $NUMBEROFCLIENTS == '0' ]]; then log_fatal "You have no existing clients!" fi @@ -1498,16 +1541,16 @@ function selectClient() { if [[ $show_expiry == "true" ]]; then local i=1 while read -r client; do - local client_cert="/etc/openvpn/easy-rsa/pki/issued/$client.crt" + local client_cert="/etc/openvpn/server/easy-rsa/pki/issued/$client.crt" local days days=$(getDaysUntilExpiry "$client_cert") local expiry expiry=$(formatExpiry "$days") echo " $i) $client $expiry" ((i++)) - done < <(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2) + done < <(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2) else - tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') ' + tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') ' fi until [[ ${CLIENTNUMBER:-$client_number} -ge 1 && ${CLIENTNUMBER:-$client_number} -le $NUMBEROFCLIENTS ]]; do @@ -1518,7 +1561,7 @@ function selectClient() { fi done CLIENTNUMBER="${CLIENTNUMBER:-$client_number}" - CLIENT=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p) + CLIENT=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p) } function newClient() { @@ -1548,12 +1591,12 @@ function newClient() { read -rp "Select an option [1-2]: " -e -i 1 PASS done - CLIENTEXISTS=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -E "^V" | grep -c -E "/CN=$CLIENT\$") + CLIENTEXISTS=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -E "^V" | grep -c -E "/CN=$CLIENT\$") if [[ $CLIENTEXISTS != '0' ]]; then log_error "The specified client CN was already found in easy-rsa, please choose another name." exit else - cd /etc/openvpn/easy-rsa/ || return + cd /etc/openvpn/server/easy-rsa/ || return log_info "Generating client certificate..." export EASYRSA_CERT_EXPIRE=$CLIENT_CERT_DURATION_DAYS case $PASS in @@ -1584,14 +1627,14 @@ function revokeClient() { log_prompt "Select the existing client certificate you want to revoke" selectClient - cd /etc/openvpn/easy-rsa/ || return + cd /etc/openvpn/server/easy-rsa/ || return log_info "Revoking certificate for $CLIENT..." run_cmd "Revoking certificate" ./easyrsa --batch revoke-issued "$CLIENT" regenerateCRL run_cmd "Removing client config from /home" find /home/ -maxdepth 2 -name "$CLIENT.ovpn" -delete run_cmd "Removing client config from /root" rm -f "/root/$CLIENT.ovpn" - run_cmd "Removing IP assignment" sed -i "/^$CLIENT,.*/d" /etc/openvpn/ipp.txt - run_cmd "Backing up index" cp /etc/openvpn/easy-rsa/pki/index.txt{,.bk} + run_cmd "Removing IP assignment" sed -i "/^$CLIENT,.*/d" /etc/openvpn/server/ipp.txt + run_cmd "Backing up index" cp /etc/openvpn/server/easy-rsa/pki/index.txt{,.bk} log_success "Certificate for client $CLIENT revoked." } @@ -1614,11 +1657,11 @@ function renewClient() { client_cert_duration_days=$CLIENT_CERT_DURATION_DAYS fi - cd /etc/openvpn/easy-rsa/ || return + cd /etc/openvpn/server/easy-rsa/ || return log_info "Renewing certificate for $CLIENT..." # Backup the old certificate before renewal - run_cmd "Backing up old certificate" cp "/etc/openvpn/easy-rsa/pki/issued/$CLIENT.crt" "/etc/openvpn/easy-rsa/pki/issued/$CLIENT.crt.bak" + run_cmd "Backing up old certificate" cp "/etc/openvpn/server/easy-rsa/pki/issued/$CLIENT.crt" "/etc/openvpn/server/easy-rsa/pki/issued/$CLIENT.crt.bak" # Renew the certificate (keeps the same private key) export EASYRSA_CERT_EXPIRE=$client_cert_duration_days @@ -1645,10 +1688,10 @@ function renewServer() { log_header "Renew Server Certificate" - # Get the server name from the config - server_name=$(grep '^cert ' /etc/openvpn/server.conf | cut -d ' ' -f 2 | sed 's/\.crt$//') + # Get the server name from the config (extract basename since path may be relative) + server_name=$(basename "$(grep '^cert ' /etc/openvpn/server/server.conf | cut -d ' ' -f 2)" .crt) if [[ -z "$server_name" ]]; then - log_fatal "Could not determine server certificate name from /etc/openvpn/server.conf" + log_fatal "Could not determine server certificate name from /etc/openvpn/server/server.conf" fi log_prompt "This will renew the server certificate: $server_name" @@ -1672,11 +1715,11 @@ function renewServer() { server_cert_duration_days=$SERVER_CERT_DURATION_DAYS fi - cd /etc/openvpn/easy-rsa/ || return + cd /etc/openvpn/server/easy-rsa/ || return log_info "Renewing server certificate..." # Backup the old certificate before renewal - run_cmd "Backing up old certificate" cp "/etc/openvpn/easy-rsa/pki/issued/$server_name.crt" "/etc/openvpn/easy-rsa/pki/issued/$server_name.crt.bak" + run_cmd "Backing up old certificate" cp "/etc/openvpn/server/easy-rsa/pki/issued/$server_name.crt" "/etc/openvpn/server/easy-rsa/pki/issued/$server_name.crt.bak" # Renew the certificate (keeps the same private key) export EASYRSA_CERT_EXPIRE=$server_cert_duration_days @@ -1688,18 +1731,12 @@ function renewServer() { # Regenerate the CRL regenerateCRL - # Copy the new certificate to /etc/openvpn/ - run_cmd "Copying new certificate" cp "/etc/openvpn/easy-rsa/pki/issued/$server_name.crt" /etc/openvpn/ + # Copy the new certificate to /etc/openvpn/server/ + run_cmd "Copying new certificate" cp "/etc/openvpn/server/easy-rsa/pki/issued/$server_name.crt" /etc/openvpn/server/ # Restart OpenVPN log_info "Restarting OpenVPN service..." - if [[ $OS =~ (fedora|arch|centos|oracle) ]]; then - run_cmd "Restarting OpenVPN" systemctl restart openvpn-server@server - elif [[ $OS == "ubuntu" ]] && [[ $VERSION_ID == "16.04" ]]; then - run_cmd "Restarting OpenVPN" systemctl restart openvpn - else - run_cmd "Restarting OpenVPN" systemctl restart openvpn@server - fi + run_cmd "Restarting OpenVPN" systemctl restart openvpn-server@server log_success "Server certificate renewed successfully and is valid for $server_cert_duration_days days." } @@ -1743,12 +1780,12 @@ function renewMenu() { log_header "Certificate Renewal" - # Get server certificate expiry for menu display - server_name=$(grep '^cert ' /etc/openvpn/server.conf | cut -d ' ' -f 2 | sed 's/\.crt$//') + # Get server certificate expiry for menu display (extract basename since path may be relative) + server_name=$(basename "$(grep '^cert ' /etc/openvpn/server/server.conf | cut -d ' ' -f 2)" .crt) if [[ -z "$server_name" ]]; then server_expiry="(unknown expiry)" else - server_cert="/etc/openvpn/easy-rsa/pki/issued/$server_name.crt" + server_cert="/etc/openvpn/server/easy-rsa/pki/issued/$server_name.crt" server_days=$(getDaysUntilExpiry "$server_cert") server_expiry=$(formatExpiry "$server_days") fi @@ -1819,23 +1856,15 @@ function removeOpenVPN() { read -rp "Do you really want to remove OpenVPN? [y/n]: " -e -i n REMOVE if [[ $REMOVE == 'y' ]]; then # Get OpenVPN port from the configuration - PORT=$(grep '^port ' /etc/openvpn/server.conf | cut -d " " -f 2) - PROTOCOL=$(grep '^proto ' /etc/openvpn/server.conf | cut -d " " -f 2) + PORT=$(grep '^port ' /etc/openvpn/server/server.conf | cut -d " " -f 2) + PROTOCOL=$(grep '^proto ' /etc/openvpn/server/server.conf | cut -d " " -f 2) # Stop OpenVPN log_info "Stopping OpenVPN service..." - if [[ $OS =~ (fedora|arch|centos|oracle) ]]; then - run_cmd "Disabling OpenVPN service" systemctl disable openvpn-server@server - run_cmd "Stopping OpenVPN service" systemctl stop openvpn-server@server - # Remove customised service - run_cmd "Removing service file" rm /etc/systemd/system/openvpn-server@.service - else - # Debian, Ubuntu, openSUSE use openvpn@server - run_cmd "Disabling OpenVPN service" systemctl disable openvpn@server - run_cmd "Stopping OpenVPN service" systemctl stop openvpn@server - # Remove customised service - run_cmd "Removing service file" rm /etc/systemd/system/openvpn\@.service - fi + run_cmd "Disabling OpenVPN service" systemctl disable openvpn-server@server + run_cmd "Stopping OpenVPN service" systemctl stop openvpn-server@server + # Remove customised service + run_cmd "Removing service file" rm -f /etc/systemd/system/openvpn-server@.service # Remove the iptables rules related to the script log_info "Removing iptables rules..." @@ -1946,7 +1975,7 @@ function manageMenu() { initialCheck # Check if OpenVPN is already installed -if [[ -e /etc/openvpn/server.conf ]]; then +if [[ -e /etc/openvpn/server/server.conf ]]; then manageMenu else installOpenVPN diff --git a/test/server-entrypoint.sh b/test/server-entrypoint.sh index 133f3c2..934447b 100755 --- a/test/server-entrypoint.sh +++ b/test/server-entrypoint.sh @@ -65,12 +65,12 @@ fi echo "Verifying installation..." MISSING_FILES=0 for f in \ - /etc/openvpn/server.conf \ - /etc/openvpn/ca.crt \ - /etc/openvpn/ca.key \ - /etc/openvpn/tls-crypt.key \ - /etc/openvpn/crl.pem \ - /etc/openvpn/easy-rsa/pki/ca.crt \ + /etc/openvpn/server/server.conf \ + /etc/openvpn/server/ca.crt \ + /etc/openvpn/server/ca.key \ + /etc/openvpn/server/tls-crypt.key \ + /etc/openvpn/server/crl.pem \ + /etc/openvpn/server/easy-rsa/pki/ca.crt \ /etc/iptables/add-openvpn-rules.sh \ /root/testclient.ovpn; do if [ ! -f "$f" ]; then @@ -85,9 +85,66 @@ if [ $MISSING_FILES -gt 0 ]; then fi echo "All required files present" + +# ===================================================== +# Verify systemd service file configuration +# ===================================================== +echo "" +echo "=== Verifying systemd service configuration ===" + +# Check that the correct service file was created +SERVICE_FILE="/etc/systemd/system/openvpn-server@.service" +if [ -f "$SERVICE_FILE" ]; then + echo "PASS: openvpn-server@.service exists at $SERVICE_FILE" +else + echo "FAIL: openvpn-server@.service not found at $SERVICE_FILE" + echo "Contents of /etc/systemd/system/:" + find /etc/systemd/system/ -maxdepth 1 -name '*openvpn*' -ls 2>/dev/null || echo "No openvpn service files found" + exit 1 +fi + +# Verify the service file points to /etc/openvpn/server/ (not patched back to /etc/openvpn/) +if grep -q "/etc/openvpn/server" "$SERVICE_FILE"; then + echo "PASS: Service file uses correct path /etc/openvpn/server/" +else + echo "FAIL: Service file does not reference /etc/openvpn/server/" + echo "Service file contents:" + cat "$SERVICE_FILE" + exit 1 +fi + +# Verify the service file syntax is valid (if systemd-analyze is available) +if command -v systemd-analyze >/dev/null 2>&1; then + echo "Validating service file syntax..." + if systemd-analyze verify "$SERVICE_FILE" 2>&1 | tee /tmp/service-verify.log; then + echo "PASS: Service file syntax is valid" + else + # systemd-analyze verify may return non-zero for warnings, check for actual errors + if grep -qi "error" /tmp/service-verify.log; then + echo "FAIL: Service file has syntax errors" + cat /tmp/service-verify.log + exit 1 + else + echo "PASS: Service file syntax is valid (warnings only)" + fi + fi +else + echo "SKIP: systemd-analyze not available, skipping syntax validation" +fi + +# Verify the old service file pattern (openvpn@.service) was NOT created +OLD_SERVICE_FILE="/etc/systemd/system/openvpn@.service" +if [ -f "$OLD_SERVICE_FILE" ]; then + echo "FAIL: Legacy openvpn@.service was created (should use openvpn-server@.service)" + exit 1 +else + echo "PASS: Legacy openvpn@.service not present (correct)" +fi + +echo "=== systemd service configuration verified ===" echo "" echo "Server config:" -cat /etc/openvpn/server.conf +cat /etc/openvpn/server/server.conf # Copy client config to shared volume cp /root/testclient.ovpn /shared/client.ovpn @@ -102,7 +159,7 @@ echo "" echo "=== Testing Certificate Renewal ===" # Get the original certificate serial number for comparison -ORIG_CERT_SERIAL=$(openssl x509 -in /etc/openvpn/easy-rsa/pki/issued/testclient.crt -noout -serial | cut -d= -f2) +ORIG_CERT_SERIAL=$(openssl x509 -in /etc/openvpn/server/easy-rsa/pki/issued/testclient.crt -noout -serial | cut -d= -f2) echo "Original client certificate serial: $ORIG_CERT_SERIAL" # Test client certificate renewal using the script @@ -120,7 +177,7 @@ else fi # Verify new certificate has different serial -NEW_CERT_SERIAL=$(openssl x509 -in /etc/openvpn/easy-rsa/pki/issued/testclient.crt -noout -serial | cut -d= -f2) +NEW_CERT_SERIAL=$(openssl x509 -in /etc/openvpn/server/easy-rsa/pki/issued/testclient.crt -noout -serial | cut -d= -f2) echo "New client certificate serial: $NEW_CERT_SERIAL" if [ "$ORIG_CERT_SERIAL" != "$NEW_CERT_SERIAL" ]; then echo "PASS: Certificate serial changed (renewal created new cert)" @@ -131,8 +188,8 @@ fi # Verify renewed certificate has correct validity period # The default is 3650 days, so the cert should be valid for ~10 years from now -CLIENT_CERT_NOT_AFTER=$(openssl x509 -in /etc/openvpn/easy-rsa/pki/issued/testclient.crt -noout -enddate | cut -d= -f2) -CLIENT_CERT_NOT_BEFORE=$(openssl x509 -in /etc/openvpn/easy-rsa/pki/issued/testclient.crt -noout -startdate | cut -d= -f2) +CLIENT_CERT_NOT_AFTER=$(openssl x509 -in /etc/openvpn/server/easy-rsa/pki/issued/testclient.crt -noout -enddate | cut -d= -f2) +CLIENT_CERT_NOT_BEFORE=$(openssl x509 -in /etc/openvpn/server/easy-rsa/pki/issued/testclient.crt -noout -startdate | cut -d= -f2) echo "Client certificate valid from: $CLIENT_CERT_NOT_BEFORE" echo "Client certificate valid until: $CLIENT_CERT_NOT_AFTER" @@ -159,7 +216,7 @@ else fi # Verify CRL was updated -if [ -f /etc/openvpn/crl.pem ]; then +if [ -f /etc/openvpn/server/crl.pem ]; then echo "PASS: CRL file exists" else echo "FAIL: CRL file missing after renewal" @@ -179,9 +236,9 @@ echo "=== Client Certificate Renewal Tests PASSED ===" echo "" echo "=== Testing Server Certificate Renewal ===" -# Get server certificate name and original serial -SERVER_NAME=$(grep '^cert ' /etc/openvpn/server.conf | cut -d ' ' -f 2 | sed 's/\.crt$//') -ORIG_SERVER_SERIAL=$(openssl x509 -in "/etc/openvpn/easy-rsa/pki/issued/$SERVER_NAME.crt" -noout -serial | cut -d= -f2) +# Get server certificate name and original serial (extract basename since path may be relative) +SERVER_NAME=$(basename "$(grep '^cert ' /etc/openvpn/server/server.conf | cut -d ' ' -f 2)" .crt) +ORIG_SERVER_SERIAL=$(openssl x509 -in "/etc/openvpn/server/easy-rsa/pki/issued/$SERVER_NAME.crt" -noout -serial | cut -d= -f2) echo "Server certificate: $SERVER_NAME" echo "Original server certificate serial: $ORIG_SERVER_SERIAL" @@ -200,7 +257,7 @@ else fi # Verify new certificate has different serial -NEW_SERVER_SERIAL=$(openssl x509 -in "/etc/openvpn/easy-rsa/pki/issued/$SERVER_NAME.crt" -noout -serial | cut -d= -f2) +NEW_SERVER_SERIAL=$(openssl x509 -in "/etc/openvpn/server/easy-rsa/pki/issued/$SERVER_NAME.crt" -noout -serial | cut -d= -f2) echo "New server certificate serial: $NEW_SERVER_SERIAL" if [ "$ORIG_SERVER_SERIAL" != "$NEW_SERVER_SERIAL" ]; then echo "PASS: Server certificate serial changed (renewal created new cert)" @@ -210,8 +267,8 @@ else fi # Verify renewed server certificate has correct validity period -SERVER_CERT_NOT_AFTER=$(openssl x509 -in "/etc/openvpn/easy-rsa/pki/issued/$SERVER_NAME.crt" -noout -enddate | cut -d= -f2) -SERVER_CERT_NOT_BEFORE=$(openssl x509 -in "/etc/openvpn/easy-rsa/pki/issued/$SERVER_NAME.crt" -noout -startdate | cut -d= -f2) +SERVER_CERT_NOT_AFTER=$(openssl x509 -in "/etc/openvpn/server/easy-rsa/pki/issued/$SERVER_NAME.crt" -noout -enddate | cut -d= -f2) +SERVER_CERT_NOT_BEFORE=$(openssl x509 -in "/etc/openvpn/server/easy-rsa/pki/issued/$SERVER_NAME.crt" -noout -startdate | cut -d= -f2) echo "Server certificate valid from: $SERVER_CERT_NOT_BEFORE" echo "Server certificate valid until: $SERVER_CERT_NOT_AFTER" @@ -227,17 +284,17 @@ else exit 1 fi -# Verify the new certificate was copied to /etc/openvpn/ -if [ -f "/etc/openvpn/$SERVER_NAME.crt" ]; then - DEPLOYED_SERIAL=$(openssl x509 -in "/etc/openvpn/$SERVER_NAME.crt" -noout -serial | cut -d= -f2) +# Verify the new certificate was copied to /etc/openvpn/server/ +if [ -f "/etc/openvpn/server/$SERVER_NAME.crt" ]; then + DEPLOYED_SERIAL=$(openssl x509 -in "/etc/openvpn/server/$SERVER_NAME.crt" -noout -serial | cut -d= -f2) if [ "$NEW_SERVER_SERIAL" = "$DEPLOYED_SERIAL" ]; then - echo "PASS: New server certificate deployed to /etc/openvpn/" + echo "PASS: New server certificate deployed to /etc/openvpn/server/" else echo "FAIL: Deployed certificate doesn't match renewed certificate" exit 1 fi else - echo "FAIL: Server certificate not found in /etc/openvpn/" + echo "FAIL: Server certificate not found in /etc/openvpn/server/" exit 1 fi @@ -309,11 +366,11 @@ else fi # Verify OpenVPN pushes correct DNS -if grep -q 'push "dhcp-option DNS 10.8.0.1"' /etc/openvpn/server.conf; then +if grep -q 'push "dhcp-option DNS 10.8.0.1"' /etc/openvpn/server/server.conf; then echo "PASS: OpenVPN configured to push Unbound DNS" else echo "FAIL: OpenVPN not configured to push Unbound DNS" - grep "dhcp-option DNS" /etc/openvpn/server.conf || echo "No DNS push found" + grep "dhcp-option DNS" /etc/openvpn/server/server.conf || echo "No DNS push found" exit 1 fi @@ -346,9 +403,9 @@ if [ "$(cat /proc/sys/net/ipv4/ip_forward)" != "1" ]; then } fi -# Start OpenVPN in background (run from /etc/openvpn so relative paths work) -cd /etc/openvpn -openvpn --config /etc/openvpn/server.conf --log /var/log/openvpn-server.log & +# Start OpenVPN in background (run from /etc/openvpn/server so relative paths work) +cd /etc/openvpn/server +openvpn --config /etc/openvpn/server/server.conf --log /var/log/openvpn-server.log & OPENVPN_PID=$! # Wait for OpenVPN to start @@ -453,10 +510,10 @@ echo "Revoking certificate for '$REVOKE_CLIENT'..." REVOKE_OUTPUT="/tmp/revoke-output.log" # MENU_OPTION=2 is revoke, CLIENTNUMBER is dynamically determined from index.txt # We need to find the client number for revoketest -REVOKE_CLIENT_NUM=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | grep -n "CN=$REVOKE_CLIENT\$" | cut -d: -f1) +REVOKE_CLIENT_NUM=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep "^V" | grep -n "CN=$REVOKE_CLIENT\$" | cut -d: -f1) if [ -z "$REVOKE_CLIENT_NUM" ]; then echo "ERROR: Could not find client number for '$REVOKE_CLIENT'" - cat /etc/openvpn/easy-rsa/pki/index.txt + cat /etc/openvpn/server/easy-rsa/pki/index.txt exit 1 fi echo "Revoke client number: $REVOKE_CLIENT_NUM" @@ -471,11 +528,11 @@ else fi # Verify certificate is marked as revoked in index.txt -if tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -q "^R.*CN=$REVOKE_CLIENT\$"; then +if tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -q "^R.*CN=$REVOKE_CLIENT\$"; then echo "PASS: Certificate marked as revoked in index.txt" else echo "FAIL: Certificate not marked as revoked" - cat /etc/openvpn/easy-rsa/pki/index.txt + cat /etc/openvpn/server/easy-rsa/pki/index.txt exit 1 fi @@ -520,23 +577,23 @@ else fi # Verify the new certificate is valid (V) in index.txt -if tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -q "^V.*CN=$REVOKE_CLIENT\$"; then +if tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -q "^V.*CN=$REVOKE_CLIENT\$"; then echo "PASS: New certificate is valid in index.txt" else echo "FAIL: New certificate not marked as valid" - cat /etc/openvpn/easy-rsa/pki/index.txt + cat /etc/openvpn/server/easy-rsa/pki/index.txt exit 1 fi # Verify there's also a revoked entry (both should exist) -REVOKED_COUNT=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -c "^R.*CN=$REVOKE_CLIENT\$") -VALID_COUNT=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -c "^V.*CN=$REVOKE_CLIENT\$") +REVOKED_COUNT=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -c "^R.*CN=$REVOKE_CLIENT\$") +VALID_COUNT=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -c "^V.*CN=$REVOKE_CLIENT\$") echo "Certificates for '$REVOKE_CLIENT': $REVOKED_COUNT revoked, $VALID_COUNT valid" if [ "$REVOKED_COUNT" -ge 1 ] && [ "$VALID_COUNT" -eq 1 ]; then echo "PASS: Both revoked and new valid certificate entries exist" else echo "FAIL: Unexpected certificate state" - cat /etc/openvpn/easy-rsa/pki/index.txt + cat /etc/openvpn/server/easy-rsa/pki/index.txt exit 1 fi