mirror of
https://github.com/angristan/openvpn-install.git
synced 2025-12-19 02:07:02 +01:00
feat: add peer-fingerprint authentication mode (OpenVPN 2.6+) (#1437)
## Summary Implements support for OpenVPN's `--peer-fingerprint` option, enabling PKI-less authentication using SHA256 certificate fingerprints instead of a CA chain. Closes #1361 ## Changes - Add `--auth-mode` option (`pki` or `fingerprint`) for install command - Use Easy-RSA's `self-sign-server` and `self-sign-client` commands for fingerprint mode - Server stores client fingerprints in `<peer-fingerprint>` block in `server.conf` - Clients verify server using `peer-fingerprint` directive instead of CA - Revocation removes fingerprint from config and reloads OpenVPN (instant effect) - Version check ensures OpenVPN 2.6+ when fingerprint mode is selected ## Usage ```bash # Interactive mode prompts for auth mode choice # CLI mode ./openvpn-install.sh install --auth-mode fingerprint ``` ## Comparison | Aspect | PKI Mode | Fingerprint Mode | |--------|----------|------------------| | Server cert | CA-signed | Self-signed | | Client cert | CA-signed | Self-signed | | Revocation | CRL-based | Remove fingerprint | | OpenVPN | Any version | 2.6.0+ required | | Best for | Large deployments | Small/home setups |
This commit is contained in:
10
.github/workflows/docker-test.yml
vendored
10
.github/workflows/docker-test.yml
vendored
@@ -118,6 +118,15 @@ jobs:
|
||||
name: tls-crypt-v2
|
||||
sig: crypt-v2
|
||||
key_file: tls-crypt-v2.key
|
||||
# Test peer-fingerprint authentication mode (OpenVPN 2.6+)
|
||||
- os:
|
||||
name: ubuntu-24.04-fingerprint
|
||||
image: ubuntu:24.04
|
||||
auth_mode: fingerprint
|
||||
tls:
|
||||
name: tls-crypt-v2
|
||||
sig: crypt-v2
|
||||
key_file: tls-crypt-v2.key
|
||||
|
||||
name: ${{ matrix.os.name }}
|
||||
steps:
|
||||
@@ -166,6 +175,7 @@ jobs:
|
||||
-e TLS_SIG=${{ matrix.tls.sig }} \
|
||||
-e TLS_KEY_FILE=${{ matrix.tls.key_file }} \
|
||||
-e CLIENT_IPV6=${{ matrix.os.client_ipv6 && 'y' || 'n' }} \
|
||||
-e AUTH_MODE=${{ matrix.os.auth_mode || 'pki' }} \
|
||||
openvpn-server
|
||||
|
||||
- name: Wait for server installation and startup
|
||||
|
||||
41
README.md
41
README.md
@@ -62,6 +62,7 @@ That said, OpenVPN still makes sense when you need:
|
||||
- Randomised server certificate name
|
||||
- Choice to protect clients with a password (private key encryption)
|
||||
- Option to allow multiple devices to use the same client profile simultaneously (disables persistent IP addresses)
|
||||
- **Peer fingerprint authentication** (OpenVPN 2.6+): Simplified WireGuard-like authentication without a CA
|
||||
- Many other little things!
|
||||
|
||||
## Compatibility
|
||||
@@ -317,6 +318,7 @@ The `install` command supports many options for customization:
|
||||
- `--rsa-bits <2048|3072|4096>` - RSA key size (default: `2048`)
|
||||
- `--hmac <alg>` - HMAC algorithm (default: `SHA256`). Options: `SHA256`, `SHA384`, `SHA512`
|
||||
- `--tls-sig <mode>` - TLS mode (default: `crypt-v2`). Options: `crypt-v2`, `crypt`, `auth`
|
||||
- `--auth-mode <mode>` - Authentication mode (default: `pki`). Options: `pki` (CA-based), `fingerprint` (peer-fingerprint, requires OpenVPN 2.6+)
|
||||
- `--tls-version-min <1.2|1.3>` - Minimum TLS version (default: `1.2`)
|
||||
- `--tls-ciphersuites <list>` - TLS 1.3 cipher suites, colon-separated (default: `TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256`)
|
||||
- `--tls-groups <list>` - Key exchange groups, colon-separated (default: `X25519:prime256v1:secp384r1:secp521r1`)
|
||||
@@ -470,6 +472,45 @@ It defaults to ECDSA with `prime256v1`.
|
||||
|
||||
OpenVPN uses `SHA-256` as the signature hash by default, and so does the script. It provides no other choice as of now.
|
||||
|
||||
### Authentication Mode
|
||||
|
||||
The script supports two authentication modes:
|
||||
|
||||
#### PKI Mode (default)
|
||||
|
||||
Traditional Certificate Authority (CA) based authentication. The server and all clients have certificates signed by the same CA. Client revocation is handled via Certificate Revocation Lists (CRL).
|
||||
|
||||
This is the recommended mode for larger deployments where you need:
|
||||
|
||||
- Centralized certificate management
|
||||
- Standard CRL-based revocation
|
||||
- Compatibility with all OpenVPN versions
|
||||
|
||||
#### Peer Fingerprint Mode (OpenVPN 2.6+)
|
||||
|
||||
A simplified WireGuard-like authentication model using SHA256 certificate fingerprints instead of a CA chain. Each peer (server and clients) has a self-signed certificate, and peers authenticate each other by verifying fingerprints.
|
||||
|
||||
```bash
|
||||
# Install with fingerprint mode
|
||||
./openvpn-install.sh install --auth-mode fingerprint
|
||||
```
|
||||
|
||||
Benefits:
|
||||
|
||||
- Simpler setup: No CA infrastructure needed
|
||||
- Easier to understand: Similar to SSH's `known_hosts` model
|
||||
- Ideal for small setups: Home networks, labs, small teams
|
||||
|
||||
How it works:
|
||||
|
||||
1. Server generates a self-signed certificate and stores its fingerprint
|
||||
2. Each client generates a self-signed certificate
|
||||
3. Client fingerprints are added to the server's `<peer-fingerprint>` block
|
||||
4. Clients verify the server using the server's fingerprint
|
||||
5. Revocation removes the fingerprint from the server config (no CRL needed)
|
||||
|
||||
Trade-off: Revoking a client requires reloading OpenVPN (fingerprints are in server.conf). In PKI mode, the CRL file is re-read automatically on new connections.
|
||||
|
||||
### Data channel
|
||||
|
||||
> [!NOTE]
|
||||
|
||||
@@ -239,6 +239,8 @@ show_install_help() {
|
||||
(default: X25519:prime256v1:secp384r1:secp521r1)
|
||||
--hmac <alg> HMAC algorithm: SHA256, SHA384, SHA512 (default: SHA256)
|
||||
--tls-sig <mode> TLS mode: crypt-v2, crypt, auth (default: crypt-v2)
|
||||
--auth-mode <mode> Auth mode: pki, fingerprint (default: pki)
|
||||
fingerprint requires OpenVPN 2.6+
|
||||
--server-cert-days <n> Server cert validity in days (default: 3650)
|
||||
|
||||
Other Options:
|
||||
@@ -477,6 +479,9 @@ readonly TLS_VERSIONS=("1.2" "1.3")
|
||||
# TLS signature modes (use strings)
|
||||
readonly TLS_SIG_MODES=("crypt-v2" "crypt" "auth")
|
||||
|
||||
# Authentication modes: pki (CA-based) or fingerprint (peer-fingerprint, OpenVPN 2.6+)
|
||||
readonly AUTH_MODES=("pki" "fingerprint")
|
||||
|
||||
# HMAC algorithms
|
||||
readonly HMAC_ALGS=("SHA256" "SHA384" "SHA512")
|
||||
|
||||
@@ -516,6 +521,7 @@ set_installation_defaults() {
|
||||
TLS_GROUPS="${TLS_GROUPS:-X25519:prime256v1:secp384r1:secp521r1}"
|
||||
HMAC_ALG="${HMAC_ALG:-SHA256}"
|
||||
TLS_SIG="${TLS_SIG:-crypt-v2}"
|
||||
AUTH_MODE="${AUTH_MODE:-pki}"
|
||||
|
||||
# Derive CC_CIPHER from CERT_TYPE if not set
|
||||
if [[ -z $CC_CIPHER ]]; then
|
||||
@@ -536,6 +542,18 @@ set_installation_defaults() {
|
||||
# are computed in prepare_network_config() which is called after validation
|
||||
}
|
||||
|
||||
# Version comparison: returns 0 if version1 >= version2
|
||||
version_ge() {
|
||||
local ver1="$1" ver2="$2"
|
||||
# Use sort -V for version comparison
|
||||
[[ "$(printf '%s\n%s' "$ver1" "$ver2" | sort -V | head -n1)" == "$ver2" ]]
|
||||
}
|
||||
|
||||
# Get installed OpenVPN version (e.g., "2.6.12")
|
||||
get_openvpn_version() {
|
||||
openvpn --version 2>/dev/null | head -1 | awk '{print $2}'
|
||||
}
|
||||
|
||||
# Validation functions
|
||||
validate_port() {
|
||||
local port="$1"
|
||||
@@ -642,6 +660,21 @@ validate_configuration() {
|
||||
*) log_fatal "Invalid TLS signature mode: $TLS_SIG. Must be 'crypt-v2', 'crypt', or 'auth'." ;;
|
||||
esac
|
||||
|
||||
# Validate AUTH_MODE
|
||||
case "$AUTH_MODE" in
|
||||
pki | fingerprint) ;;
|
||||
*) log_fatal "Invalid auth mode: $AUTH_MODE. Must be 'pki' or 'fingerprint'." ;;
|
||||
esac
|
||||
|
||||
# Fingerprint mode requires OpenVPN 2.6+
|
||||
if [[ $AUTH_MODE == "fingerprint" ]]; then
|
||||
local openvpn_ver
|
||||
openvpn_ver=$(get_openvpn_version)
|
||||
if [[ -n "$openvpn_ver" ]] && ! version_ge "$openvpn_ver" "2.6.0"; then
|
||||
log_fatal "Fingerprint mode requires OpenVPN 2.6.0 or later. Installed version: $openvpn_ver"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Validate PORT
|
||||
if ! [[ "$PORT" =~ ^[0-9]+$ ]] || [[ "$PORT" -lt 1 ]] || [[ "$PORT" -gt 65535 ]]; then
|
||||
log_fatal "Invalid port: $PORT. Must be a number between 1 and 65535."
|
||||
@@ -1034,6 +1067,14 @@ cmd_install() {
|
||||
esac
|
||||
shift 2
|
||||
;;
|
||||
--auth-mode)
|
||||
[[ -z "${2:-}" ]] && log_fatal "--auth-mode requires an argument"
|
||||
case "$2" in
|
||||
pki | fingerprint) AUTH_MODE="$2" ;;
|
||||
*) log_fatal "Invalid auth mode: $2. Use 'pki' or 'fingerprint'." ;;
|
||||
esac
|
||||
shift 2
|
||||
;;
|
||||
--server-cert-days)
|
||||
[[ -z "${2:-}" ]] && log_fatal "--server-cert-days requires an argument"
|
||||
validate_positive_int "$2" "server-cert-days"
|
||||
@@ -1251,6 +1292,7 @@ cmd_client_add() {
|
||||
fi
|
||||
|
||||
newClient
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Handle client list command
|
||||
@@ -2336,6 +2378,30 @@ function installQuestions() {
|
||||
done
|
||||
fi
|
||||
log_menu ""
|
||||
log_prompt "Choose the authentication mode:"
|
||||
log_menu " 1) PKI (Certificate Authority) - Traditional CA-based authentication (recommended for larger setups)"
|
||||
log_menu " 2) Peer Fingerprint - Simplified WireGuard-like authentication using certificate fingerprints"
|
||||
log_menu " Note: Fingerprint mode requires OpenVPN 2.6+ and is ideal for small/home setups"
|
||||
local auth_mode_choice
|
||||
until [[ $auth_mode_choice =~ ^[1-2]$ ]]; do
|
||||
read -rp "Authentication mode [1-2]: " -e -i 1 auth_mode_choice
|
||||
done
|
||||
case $auth_mode_choice in
|
||||
1)
|
||||
AUTH_MODE="pki"
|
||||
;;
|
||||
2)
|
||||
AUTH_MODE="fingerprint"
|
||||
# Verify OpenVPN 2.6+ is available for fingerprint mode
|
||||
local openvpn_ver
|
||||
openvpn_ver=$(get_openvpn_version)
|
||||
if [[ -n "$openvpn_ver" ]] && ! version_ge "$openvpn_ver" "2.6.0"; then
|
||||
log_warn "OpenVPN $openvpn_ver detected. Fingerprint mode requires 2.6.0+."
|
||||
log_warn "OpenVPN 2.6+ will be installed during setup."
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
log_menu ""
|
||||
log_prompt "Do you want to customize encryption settings?"
|
||||
log_prompt "Unless you know what you're doing, you should stick with the default parameters provided by the script."
|
||||
log_prompt "Note that whatever you choose, all the choices presented in the script are safe (unlike OpenVPN's defaults)."
|
||||
@@ -2541,6 +2607,7 @@ function installOpenVPN() {
|
||||
log_info " DNS=$DNS"
|
||||
[[ -n $MTU ]] && log_info " MTU=$MTU"
|
||||
log_info " MULTI_CLIENT=$MULTI_CLIENT"
|
||||
log_info " AUTH_MODE=$AUTH_MODE"
|
||||
log_info " CLIENT=$CLIENT"
|
||||
log_info " CLIENT_CERT_DURATION_DAYS=$CLIENT_CERT_DURATION_DAYS"
|
||||
log_info " SERVER_CERT_DURATION_DAYS=$SERVER_CERT_DURATION_DAYS"
|
||||
@@ -2680,15 +2747,34 @@ function installOpenVPN() {
|
||||
# Create the PKI, set up the CA, the DH params and the server certificate
|
||||
log_info "Initializing PKI..."
|
||||
run_cmd_fatal "Initializing PKI" ./easyrsa init-pki
|
||||
export EASYRSA_CA_EXPIRE=$DEFAULT_CERT_VALIDITY_DURATION_DAYS
|
||||
log_info "Building CA..."
|
||||
run_cmd_fatal "Building CA" ./easyrsa --batch --req-cn="$SERVER_CN" build-ca nopass
|
||||
|
||||
export EASYRSA_CERT_EXPIRE=${SERVER_CERT_DURATION_DAYS:-$DEFAULT_CERT_VALIDITY_DURATION_DAYS}
|
||||
log_info "Building server certificate..."
|
||||
run_cmd_fatal "Building server certificate" ./easyrsa --batch build-server-full "$SERVER_NAME" nopass
|
||||
export EASYRSA_CRL_DAYS=$DEFAULT_CRL_VALIDITY_DURATION_DAYS
|
||||
run_cmd_fatal "Generating CRL" ./easyrsa gen-crl
|
||||
if [[ $AUTH_MODE == "pki" ]]; then
|
||||
# Traditional PKI mode with CA
|
||||
export EASYRSA_CA_EXPIRE=$DEFAULT_CERT_VALIDITY_DURATION_DAYS
|
||||
log_info "Building CA..."
|
||||
run_cmd_fatal "Building CA" ./easyrsa --batch --req-cn="$SERVER_CN" build-ca nopass
|
||||
|
||||
export EASYRSA_CERT_EXPIRE=${SERVER_CERT_DURATION_DAYS:-$DEFAULT_CERT_VALIDITY_DURATION_DAYS}
|
||||
log_info "Building server certificate..."
|
||||
run_cmd_fatal "Building server certificate" ./easyrsa --batch build-server-full "$SERVER_NAME" nopass
|
||||
export EASYRSA_CRL_DAYS=$DEFAULT_CRL_VALIDITY_DURATION_DAYS
|
||||
run_cmd_fatal "Generating CRL" ./easyrsa gen-crl
|
||||
else
|
||||
# Fingerprint mode with self-signed certificates (OpenVPN 2.6+)
|
||||
log_info "Building self-signed server certificate for fingerprint mode..."
|
||||
export EASYRSA_CERT_EXPIRE=${SERVER_CERT_DURATION_DAYS:-$DEFAULT_CERT_VALIDITY_DURATION_DAYS}
|
||||
run_cmd_fatal "Building self-signed server certificate" ./easyrsa --batch self-sign-server "$SERVER_NAME" nopass
|
||||
|
||||
# Extract and store server fingerprint
|
||||
SERVER_FINGERPRINT=$(openssl x509 -in "pki/issued/$SERVER_NAME.crt" -fingerprint -sha256 -noout | cut -d'=' -f2)
|
||||
if [[ -z $SERVER_FINGERPRINT ]]; then
|
||||
log_error "Failed to extract server certificate fingerprint"
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p /etc/openvpn/server
|
||||
echo "$SERVER_FINGERPRINT" >/etc/openvpn/server/server-fingerprint
|
||||
log_info "Server fingerprint: $SERVER_FINGERPRINT"
|
||||
fi
|
||||
|
||||
log_info "Generating TLS key..."
|
||||
case $TLS_SIG in
|
||||
@@ -2705,19 +2791,32 @@ function installOpenVPN() {
|
||||
run_cmd_fatal "Generating tls-auth key" openvpn --genkey secret /etc/openvpn/server/tls-auth.key
|
||||
;;
|
||||
esac
|
||||
# Store auth mode for later use
|
||||
echo "$AUTH_MODE" >AUTH_MODE_GENERATED
|
||||
else
|
||||
# If easy-rsa is already installed, grab the generated SERVER_NAME
|
||||
# for client configs
|
||||
cd /etc/openvpn/server/easy-rsa/ || return
|
||||
SERVER_NAME=$(cat SERVER_NAME_GENERATED)
|
||||
# Read stored auth mode
|
||||
if [[ -f AUTH_MODE_GENERATED ]]; then
|
||||
AUTH_MODE=$(cat AUTH_MODE_GENERATED)
|
||||
else
|
||||
# Default to pki for existing installations
|
||||
AUTH_MODE="pki"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Move all the generated files
|
||||
log_info "Copying certificates..."
|
||||
run_cmd_fatal "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
|
||||
|
||||
# Make cert revocation list readable for non-root
|
||||
run_cmd "Setting CRL permissions" chmod 644 /etc/openvpn/server/crl.pem
|
||||
if [[ $AUTH_MODE == "pki" ]]; then
|
||||
run_cmd_fatal "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
|
||||
# Make cert revocation list readable for non-root
|
||||
run_cmd "Setting CRL permissions" chmod 644 /etc/openvpn/server/crl.pem
|
||||
else
|
||||
# Fingerprint mode: only copy server cert and key (no CA or CRL)
|
||||
run_cmd_fatal "Copying certificates to /etc/openvpn/server" cp "pki/issued/$SERVER_NAME.crt" "pki/private/$SERVER_NAME.key" /etc/openvpn/server
|
||||
fi
|
||||
|
||||
# Generate server.conf
|
||||
log_info "Generating server configuration..."
|
||||
@@ -2931,9 +3030,13 @@ topology subnet" >>/etc/openvpn/server/server.conf
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "crl-verify crl.pem
|
||||
ca ca.crt
|
||||
cert $SERVER_NAME.crt
|
||||
# Common server config options
|
||||
# PKI mode adds crl-verify, ca, and remote-cert-tls
|
||||
# Fingerprint mode: <peer-fingerprint> block is added when first client is created
|
||||
{
|
||||
[[ $AUTH_MODE == "pki" ]] && echo "crl-verify crl.pem
|
||||
ca ca.crt"
|
||||
echo "cert $SERVER_NAME.crt
|
||||
key $SERVER_NAME.key
|
||||
auth $HMAC_ALG
|
||||
cipher $CIPHER
|
||||
@@ -2941,14 +3044,15 @@ ignore-unknown-option data-ciphers
|
||||
data-ciphers $CIPHER
|
||||
ncp-ciphers $CIPHER
|
||||
tls-server
|
||||
tls-version-min $TLS_VERSION_MIN
|
||||
remote-cert-tls client
|
||||
tls-cipher $CC_CIPHER
|
||||
tls-version-min $TLS_VERSION_MIN"
|
||||
[[ $AUTH_MODE == "pki" ]] && echo "remote-cert-tls client"
|
||||
echo "tls-cipher $CC_CIPHER
|
||||
tls-ciphersuites $TLS13_CIPHERSUITES
|
||||
client-config-dir ccd
|
||||
status /var/log/openvpn/status.log
|
||||
management /var/run/openvpn/server.sock unix
|
||||
verb 3" >>/etc/openvpn/server/server.conf
|
||||
verb 3"
|
||||
} >>/etc/openvpn/server/server.conf
|
||||
|
||||
# Create management socket directory
|
||||
run_cmd_fatal "Creating management socket directory" mkdir -p /var/run/openvpn
|
||||
@@ -3028,7 +3132,11 @@ verb 3" >>/etc/openvpn/server/server.conf
|
||||
|
||||
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
|
||||
# In fingerprint mode, delay service start until first client is created
|
||||
# (OpenVPN requires at least one fingerprint or a CA to start)
|
||||
if [[ $AUTH_MODE == "pki" ]]; then
|
||||
run_cmd "Starting OpenVPN service" systemctl restart openvpn-server@server
|
||||
fi
|
||||
|
||||
if [[ $DNS == "unbound" ]]; then
|
||||
installUnbound
|
||||
@@ -3207,15 +3315,19 @@ WantedBy=multi-user.target" >/etc/systemd/system/iptables-openvpn.service
|
||||
elif [[ $PROTOCOL == 'tcp6' ]]; then
|
||||
echo "proto tcp6-client" >>/etc/openvpn/server/client-template.txt
|
||||
fi
|
||||
echo "remote $IP $PORT
|
||||
# Common client template options
|
||||
# PKI mode adds remote-cert-tls and verify-x509-name
|
||||
# Fingerprint mode adds peer-fingerprint when generating client config
|
||||
{
|
||||
echo "remote $IP $PORT
|
||||
dev tun
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
remote-cert-tls server
|
||||
verify-x509-name $SERVER_NAME name
|
||||
auth $HMAC_ALG
|
||||
persist-tun"
|
||||
[[ $AUTH_MODE == "pki" ]] && echo "remote-cert-tls server
|
||||
verify-x509-name $SERVER_NAME name"
|
||||
echo "auth $HMAC_ALG
|
||||
auth-nocache
|
||||
cipher $CIPHER
|
||||
ignore-unknown-option data-ciphers
|
||||
@@ -3227,7 +3339,8 @@ tls-cipher $CC_CIPHER
|
||||
tls-ciphersuites $TLS13_CIPHERSUITES
|
||||
ignore-unknown-option block-outside-dns
|
||||
setenv opt block-outside-dns # Prevent Windows 10 DNS leak
|
||||
verb 3" >>/etc/openvpn/server/client-template.txt
|
||||
verb 3"
|
||||
} >>/etc/openvpn/server/client-template.txt
|
||||
|
||||
if [[ -n $MTU ]]; then
|
||||
echo "tun-mtu $MTU" >>/etc/openvpn/server/client-template.txt
|
||||
@@ -3235,10 +3348,18 @@ verb 3" >>/etc/openvpn/server/client-template.txt
|
||||
|
||||
# Generate the custom client.ovpn
|
||||
if [[ $NEW_CLIENT == "n" ]]; then
|
||||
log_info "No clients added. To add clients, simply run the script again."
|
||||
if [[ $AUTH_MODE == "fingerprint" ]]; then
|
||||
log_info "No clients added. OpenVPN will not start until you add at least one client."
|
||||
else
|
||||
log_info "No clients added. To add clients, simply run the script again."
|
||||
fi
|
||||
else
|
||||
log_info "Generating first client certificate..."
|
||||
newClient
|
||||
# In fingerprint mode, start service now that we have at least one fingerprint
|
||||
if [[ $AUTH_MODE == "fingerprint" ]]; then
|
||||
run_cmd "Starting OpenVPN service" systemctl restart openvpn-server@server
|
||||
fi
|
||||
log_success "If you want to add more clients, you simply need to run this script another time!"
|
||||
fi
|
||||
}
|
||||
@@ -3333,6 +3454,12 @@ function generateClientConfig() {
|
||||
local client="$1"
|
||||
local filepath="$2"
|
||||
|
||||
# Read auth mode
|
||||
local auth_mode="pki"
|
||||
if [[ -f /etc/openvpn/server/easy-rsa/AUTH_MODE_GENERATED ]]; then
|
||||
auth_mode=$(cat /etc/openvpn/server/easy-rsa/AUTH_MODE_GENERATED)
|
||||
fi
|
||||
|
||||
# Determine if we use tls-crypt-v2, tls-crypt, or tls-auth
|
||||
local tls_sig=""
|
||||
if grep -qs "^tls-crypt-v2" /etc/openvpn/server/server.conf; then
|
||||
@@ -3346,9 +3473,25 @@ function generateClientConfig() {
|
||||
# Generate the custom client.ovpn
|
||||
run_cmd "Creating client config" cp /etc/openvpn/server/client-template.txt "$filepath"
|
||||
{
|
||||
echo "<ca>"
|
||||
cat "/etc/openvpn/server/easy-rsa/pki/ca.crt"
|
||||
echo "</ca>"
|
||||
if [[ $auth_mode == "pki" ]]; then
|
||||
# PKI mode: include CA certificate
|
||||
echo "<ca>"
|
||||
cat "/etc/openvpn/server/easy-rsa/pki/ca.crt"
|
||||
echo "</ca>"
|
||||
else
|
||||
# Fingerprint mode: use server fingerprint instead of CA
|
||||
local server_fingerprint
|
||||
if [[ ! -f /etc/openvpn/server/server-fingerprint ]]; then
|
||||
log_error "Server fingerprint file not found"
|
||||
exit 1
|
||||
fi
|
||||
server_fingerprint=$(cat /etc/openvpn/server/server-fingerprint)
|
||||
if [[ -z $server_fingerprint ]]; then
|
||||
log_error "Server fingerprint is empty"
|
||||
exit 1
|
||||
fi
|
||||
echo "peer-fingerprint $server_fingerprint"
|
||||
fi
|
||||
|
||||
echo "<cert>"
|
||||
awk '/BEGIN/,/END CERTIFICATE/' "/etc/openvpn/server/easy-rsa/pki/issued/$client.crt"
|
||||
@@ -3677,45 +3820,96 @@ function newClient() {
|
||||
done
|
||||
fi
|
||||
|
||||
CLIENTEXISTS=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -E "^V" | grep -c -E "/CN=$CLIENT\$")
|
||||
cd /etc/openvpn/server/easy-rsa/ || return
|
||||
|
||||
# Read auth mode
|
||||
if [[ -f AUTH_MODE_GENERATED ]]; then
|
||||
AUTH_MODE=$(cat AUTH_MODE_GENERATED)
|
||||
else
|
||||
AUTH_MODE="pki"
|
||||
fi
|
||||
|
||||
# Check if client already exists
|
||||
if [[ -f pki/index.txt ]]; then
|
||||
CLIENTEXISTS=$(tail -n +2 /etc/openvpn/server/easy-rsa/pki/index.txt | grep -E "^V" | grep -c -E "/CN=$CLIENT\$")
|
||||
else
|
||||
CLIENTEXISTS=0
|
||||
fi
|
||||
|
||||
if [[ $CLIENTEXISTS != '0' ]]; then
|
||||
log_error "The specified client CN was already found in easy-rsa, please choose another name."
|
||||
exit 1
|
||||
else
|
||||
cd /etc/openvpn/server/easy-rsa/ || return
|
||||
log_info "Generating client certificate..."
|
||||
export EASYRSA_CERT_EXPIRE=$CLIENT_CERT_DURATION_DAYS
|
||||
case $PASS in
|
||||
1)
|
||||
run_cmd_fatal "Building client certificate" ./easyrsa --batch build-client-full "$CLIENT" nopass
|
||||
;;
|
||||
2)
|
||||
if [[ -z "$PASSPHRASE" ]]; then
|
||||
log_warn "You will be asked for the client password below"
|
||||
# Run directly (not via run_cmd) so password prompt is visible to user
|
||||
if ! ./easyrsa --batch build-client-full "$CLIENT"; then
|
||||
log_fatal "Building client certificate failed"
|
||||
fi
|
||||
else
|
||||
log_info "Using provided passphrase for client certificate"
|
||||
# Use env var to avoid exposing passphrase in install log
|
||||
export EASYRSA_PASSPHRASE="$PASSPHRASE"
|
||||
run_cmd_fatal "Building client certificate" ./easyrsa --batch --passin=env:EASYRSA_PASSPHRASE --passout=env:EASYRSA_PASSPHRASE build-client-full "$CLIENT"
|
||||
unset EASYRSA_PASSPHRASE
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
log_success "Client $CLIENT added and is valid for $CLIENT_CERT_DURATION_DAYS days."
|
||||
fi
|
||||
|
||||
log_info "Generating client certificate..."
|
||||
export EASYRSA_CERT_EXPIRE=$CLIENT_CERT_DURATION_DAYS
|
||||
|
||||
# Determine easyrsa command based on auth mode
|
||||
local easyrsa_cmd cert_desc
|
||||
if [[ $AUTH_MODE == "pki" ]]; then
|
||||
easyrsa_cmd="build-client-full"
|
||||
cert_desc="client certificate"
|
||||
else
|
||||
easyrsa_cmd="self-sign-client"
|
||||
cert_desc="self-signed client certificate"
|
||||
fi
|
||||
|
||||
case $PASS in
|
||||
1)
|
||||
run_cmd_fatal "Building $cert_desc" ./easyrsa --batch "$easyrsa_cmd" "$CLIENT" nopass
|
||||
;;
|
||||
2)
|
||||
if [[ -z "$PASSPHRASE" ]]; then
|
||||
log_warn "You will be asked for the client password below"
|
||||
if ! ./easyrsa --batch "$easyrsa_cmd" "$CLIENT"; then
|
||||
log_fatal "Building $cert_desc failed"
|
||||
fi
|
||||
else
|
||||
log_info "Using provided passphrase for client certificate"
|
||||
export EASYRSA_PASSPHRASE="$PASSPHRASE"
|
||||
run_cmd_fatal "Building $cert_desc" ./easyrsa --batch --passin=env:EASYRSA_PASSPHRASE --passout=env:EASYRSA_PASSPHRASE "$easyrsa_cmd" "$CLIENT"
|
||||
unset EASYRSA_PASSPHRASE
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Fingerprint mode: register client fingerprint with server
|
||||
if [[ $AUTH_MODE == "fingerprint" ]]; then
|
||||
CLIENT_FINGERPRINT=$(openssl x509 -in "pki/issued/$CLIENT.crt" -fingerprint -sha256 -noout | cut -d'=' -f2)
|
||||
if [[ -z $CLIENT_FINGERPRINT ]]; then
|
||||
log_error "Failed to extract client certificate fingerprint"
|
||||
exit 1
|
||||
fi
|
||||
log_info "Client fingerprint: $CLIENT_FINGERPRINT"
|
||||
|
||||
# Add fingerprint to server.conf's <peer-fingerprint> block
|
||||
# Create the block if this is the first client
|
||||
if ! grep -q '<peer-fingerprint>' /etc/openvpn/server/server.conf; then
|
||||
echo "# Client fingerprints are listed below
|
||||
<peer-fingerprint>
|
||||
# $CLIENT
|
||||
$CLIENT_FINGERPRINT
|
||||
</peer-fingerprint>" >>/etc/openvpn/server/server.conf
|
||||
else
|
||||
# Insert comment and fingerprint before closing tag
|
||||
sed -i "/<\/peer-fingerprint>/i # $CLIENT\n$CLIENT_FINGERPRINT" /etc/openvpn/server/server.conf
|
||||
fi
|
||||
|
||||
# Reload OpenVPN to pick up new fingerprint
|
||||
log_info "Reloading OpenVPN to apply new fingerprint..."
|
||||
if systemctl is-active --quiet openvpn-server@server; then
|
||||
systemctl reload openvpn-server@server 2>/dev/null || systemctl restart openvpn-server@server
|
||||
fi
|
||||
fi
|
||||
|
||||
log_success "Client $CLIENT added and is valid for $CLIENT_CERT_DURATION_DAYS days."
|
||||
|
||||
# Write the .ovpn config file with proper path and permissions
|
||||
writeClientConfig "$CLIENT"
|
||||
|
||||
log_menu ""
|
||||
log_success "The configuration file has been written to $GENERATED_CONFIG_PATH."
|
||||
log_info "Download the .ovpn file and import it in your OpenVPN client."
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
function revokeClient() {
|
||||
@@ -3724,13 +3918,45 @@ function revokeClient() {
|
||||
selectClient
|
||||
|
||||
cd /etc/openvpn/server/easy-rsa/ || return
|
||||
|
||||
# Read auth mode
|
||||
local auth_mode="pki"
|
||||
if [[ -f AUTH_MODE_GENERATED ]]; then
|
||||
auth_mode=$(cat AUTH_MODE_GENERATED)
|
||||
fi
|
||||
|
||||
log_info "Revoking certificate for $CLIENT..."
|
||||
run_cmd_fatal "Revoking certificate" ./easyrsa --batch revoke-issued "$CLIENT"
|
||||
regenerateCRL
|
||||
|
||||
if [[ $auth_mode == "pki" ]]; then
|
||||
# PKI mode: use Easy-RSA revocation and CRL
|
||||
run_cmd_fatal "Revoking certificate" ./easyrsa --batch revoke-issued "$CLIENT"
|
||||
regenerateCRL
|
||||
run_cmd "Backing up index" cp /etc/openvpn/server/easy-rsa/pki/index.txt{,.bk}
|
||||
else
|
||||
# Fingerprint mode: remove fingerprint from server.conf and delete cert files
|
||||
log_info "Removing client fingerprint from server configuration..."
|
||||
|
||||
# Remove comment line and fingerprint line below it from server.conf
|
||||
sed -i "/^# $CLIENT\$/{N;d;}" /etc/openvpn/server/server.conf
|
||||
|
||||
# Remove client certificate and key
|
||||
rm -f "pki/issued/$CLIENT.crt" "pki/private/$CLIENT.key"
|
||||
|
||||
# Mark as revoked in index.txt if it exists (for client listing)
|
||||
if [[ -f pki/index.txt ]]; then
|
||||
sed -i "s|^V\(.*\)/CN=$CLIENT\$|R\1/CN=$CLIENT|" pki/index.txt
|
||||
fi
|
||||
|
||||
# Reload OpenVPN to apply fingerprint removal
|
||||
log_info "Reloading OpenVPN to apply fingerprint removal..."
|
||||
if systemctl is-active --quiet openvpn-server@server; then
|
||||
systemctl reload openvpn-server@server 2>/dev/null || systemctl restart openvpn-server@server
|
||||
fi
|
||||
fi
|
||||
|
||||
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/server/ipp.txt
|
||||
run_cmd "Backing up index" cp /etc/openvpn/server/easy-rsa/pki/index.txt{,.bk}
|
||||
|
||||
# Disconnect the client if currently connected
|
||||
disconnectClient "$CLIENT"
|
||||
@@ -4102,6 +4328,7 @@ function manageMenu() {
|
||||
case $menu_option in
|
||||
1)
|
||||
newClient
|
||||
exit 0
|
||||
;;
|
||||
2)
|
||||
listClients
|
||||
|
||||
@@ -42,6 +42,10 @@ TLS_KEY_FILE="${TLS_KEY_FILE:-tls-crypt-v2.key}"
|
||||
TLS_VERSION_MIN="${TLS_VERSION_MIN:-1.2}"
|
||||
TLS13_CIPHERSUITES="${TLS13_CIPHERSUITES:-TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256}"
|
||||
|
||||
# Authentication mode configuration
|
||||
# AUTH_MODE: pki (default, CA-based) or fingerprint (peer-fingerprint, OpenVPN 2.6+)
|
||||
AUTH_MODE="${AUTH_MODE:-pki}"
|
||||
|
||||
# Build install command with CLI flags (using array for proper quoting)
|
||||
INSTALL_CMD=(/opt/openvpn-install.sh install)
|
||||
INSTALL_CMD+=(--endpoint openvpn-server)
|
||||
@@ -75,6 +79,12 @@ if [ "$TLS13_CIPHERSUITES" != "TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS
|
||||
echo "Testing TLS 1.3 ciphersuites: $TLS13_CIPHERSUITES"
|
||||
fi
|
||||
|
||||
# Add auth mode if non-default
|
||||
if [ "$AUTH_MODE" != "pki" ]; then
|
||||
INSTALL_CMD+=(--auth-mode "$AUTH_MODE")
|
||||
echo "Testing authentication mode: $AUTH_MODE"
|
||||
fi
|
||||
|
||||
echo "Running OpenVPN install script..."
|
||||
echo "Command: ${INSTALL_CMD[*]}"
|
||||
# Run in subshell because the script calls 'exit 0' after generating client config
|
||||
@@ -104,16 +114,26 @@ fi
|
||||
# Verify all expected files were created
|
||||
echo "Verifying installation..."
|
||||
MISSING_FILES=0
|
||||
# Build list of required files
|
||||
# Build list of required files based on auth mode
|
||||
REQUIRED_FILES=(
|
||||
/etc/openvpn/server/server.conf
|
||||
/etc/openvpn/server/ca.crt
|
||||
/etc/openvpn/server/ca.key
|
||||
"/etc/openvpn/server/$TLS_KEY_FILE"
|
||||
/etc/openvpn/server/crl.pem
|
||||
/etc/openvpn/server/easy-rsa/pki/ca.crt
|
||||
/root/testclient.ovpn
|
||||
)
|
||||
if [ "$AUTH_MODE" = "pki" ]; then
|
||||
# PKI mode requires CA and CRL files
|
||||
REQUIRED_FILES+=(
|
||||
/etc/openvpn/server/ca.crt
|
||||
/etc/openvpn/server/ca.key
|
||||
/etc/openvpn/server/crl.pem
|
||||
/etc/openvpn/server/easy-rsa/pki/ca.crt
|
||||
)
|
||||
else
|
||||
# Fingerprint mode requires server fingerprint file
|
||||
REQUIRED_FILES+=(
|
||||
/etc/openvpn/server/server-fingerprint
|
||||
)
|
||||
fi
|
||||
# Only check for iptables script if firewalld and nftables are not active
|
||||
if ! systemctl is-active --quiet firewalld && ! systemctl is-active --quiet nftables; then
|
||||
REQUIRED_FILES+=(/etc/iptables/add-openvpn-rules.sh)
|
||||
@@ -197,13 +217,16 @@ sed -i 's/^remote .*/remote openvpn-server 1194/' /shared/client.ovpn
|
||||
echo "Client config copied to /shared/client.ovpn"
|
||||
|
||||
# Write VPN network info to shared volume for client tests
|
||||
echo "VPN_SUBNET_IPV4=$VPN_SUBNET_IPV4" >/shared/vpn-config.env
|
||||
echo "VPN_GATEWAY=$VPN_GATEWAY" >>/shared/vpn-config.env
|
||||
echo "CLIENT_IPV6=$CLIENT_IPV6" >>/shared/vpn-config.env
|
||||
if [ "$CLIENT_IPV6" = "y" ]; then
|
||||
echo "VPN_SUBNET_IPV6=$VPN_SUBNET_IPV6" >>/shared/vpn-config.env
|
||||
echo "VPN_GATEWAY_IPV6=$VPN_GATEWAY_IPV6" >>/shared/vpn-config.env
|
||||
fi
|
||||
{
|
||||
echo "VPN_SUBNET_IPV4=$VPN_SUBNET_IPV4"
|
||||
echo "VPN_GATEWAY=$VPN_GATEWAY"
|
||||
echo "CLIENT_IPV6=$CLIENT_IPV6"
|
||||
echo "AUTH_MODE=$AUTH_MODE"
|
||||
if [ "$CLIENT_IPV6" = "y" ]; then
|
||||
echo "VPN_SUBNET_IPV6=$VPN_SUBNET_IPV6"
|
||||
echo "VPN_GATEWAY_IPV6=$VPN_GATEWAY_IPV6"
|
||||
fi
|
||||
} >/shared/vpn-config.env
|
||||
echo "VPN config written to /shared/vpn-config.env"
|
||||
|
||||
# =====================================================
|
||||
@@ -396,12 +419,14 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify CRL was updated
|
||||
if [ -f /etc/openvpn/server/crl.pem ]; then
|
||||
echo "PASS: CRL file exists"
|
||||
else
|
||||
echo "FAIL: CRL file missing after renewal"
|
||||
exit 1
|
||||
# Verify CRL was updated (PKI mode only)
|
||||
if [ "$AUTH_MODE" = "pki" ]; then
|
||||
if [ -f /etc/openvpn/server/crl.pem ]; then
|
||||
echo "PASS: CRL file exists"
|
||||
else
|
||||
echo "FAIL: CRL file missing after renewal"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Update shared client config with renewed certificate
|
||||
@@ -815,13 +840,25 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify certificate is marked as revoked in index.txt
|
||||
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"
|
||||
# Verify revocation was applied correctly
|
||||
if [ "$AUTH_MODE" = "pki" ]; then
|
||||
# PKI mode: verify certificate is marked as revoked in index.txt
|
||||
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/server/easy-rsa/pki/index.txt
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "FAIL: Certificate not marked as revoked"
|
||||
cat /etc/openvpn/server/easy-rsa/pki/index.txt
|
||||
exit 1
|
||||
# Fingerprint mode: verify fingerprint was removed from server.conf
|
||||
if ! grep -q "# $REVOKE_CLIENT\$" /etc/openvpn/server/server.conf; then
|
||||
echo "PASS: Client fingerprint removed from server.conf"
|
||||
else
|
||||
echo "FAIL: Client fingerprint still present in server.conf"
|
||||
grep "$REVOKE_CLIENT" /etc/openvpn/server/server.conf || true
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Wait for client to confirm it was disconnected by the revoke
|
||||
@@ -883,13 +920,26 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify certificate count (3 certs: testclient valid, testclient revoked from renewal, revoketest revoked)
|
||||
if grep -q "Found 3 client certificate(s)" "$LIST_OUTPUT"; then
|
||||
echo "PASS: List shows correct certificate count"
|
||||
# Verify certificate count (varies by auth mode)
|
||||
if [ "$AUTH_MODE" = "pki" ]; then
|
||||
# PKI mode: 3 certs (testclient valid, testclient revoked from renewal, revoketest revoked)
|
||||
if grep -q "Found 3 client certificate(s)" "$LIST_OUTPUT"; then
|
||||
echo "PASS: List shows correct certificate count"
|
||||
else
|
||||
echo "FAIL: List does not show correct certificate count"
|
||||
cat "$LIST_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "FAIL: List does not show correct certificate count"
|
||||
cat "$LIST_OUTPUT"
|
||||
exit 1
|
||||
# Fingerprint mode: 2 certs (testclient valid, revoketest revoked)
|
||||
# In fingerprint mode, renewal doesn't create a separate revoked entry
|
||||
if grep -q "Found [23] client certificate(s)" "$LIST_OUTPUT"; then
|
||||
echo "PASS: List shows correct certificate count for fingerprint mode"
|
||||
else
|
||||
echo "FAIL: List does not show correct certificate count"
|
||||
cat "$LIST_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Test JSON output
|
||||
@@ -906,14 +956,25 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify client count in JSON
|
||||
# Verify client count in JSON (varies by auth mode)
|
||||
JSON_CLIENT_COUNT=$(jq '.clients | length' "$LIST_JSON_OUTPUT")
|
||||
if [ "$JSON_CLIENT_COUNT" -eq 3 ]; then
|
||||
echo "PASS: Client list JSON has correct count ($JSON_CLIENT_COUNT)"
|
||||
if [ "$AUTH_MODE" = "pki" ]; then
|
||||
if [ "$JSON_CLIENT_COUNT" -eq 3 ]; then
|
||||
echo "PASS: Client list JSON has correct count ($JSON_CLIENT_COUNT)"
|
||||
else
|
||||
echo "FAIL: Client list JSON has wrong count: $JSON_CLIENT_COUNT (expected 3)"
|
||||
cat "$LIST_JSON_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "FAIL: Client list JSON has wrong count: $JSON_CLIENT_COUNT (expected 3)"
|
||||
cat "$LIST_JSON_OUTPUT"
|
||||
exit 1
|
||||
# Fingerprint mode may have fewer entries
|
||||
if [ "$JSON_CLIENT_COUNT" -ge 2 ] && [ "$JSON_CLIENT_COUNT" -le 3 ]; then
|
||||
echo "PASS: Client list JSON has correct count for fingerprint mode ($JSON_CLIENT_COUNT)"
|
||||
else
|
||||
echo "FAIL: Client list JSON has wrong count: $JSON_CLIENT_COUNT (expected 2-3)"
|
||||
cat "$LIST_JSON_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Verify valid client in JSON
|
||||
@@ -955,25 +1016,37 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify the new certificate is valid (V) in index.txt
|
||||
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/server/easy-rsa/pki/index.txt
|
||||
exit 1
|
||||
fi
|
||||
# Verify the new certificate is valid
|
||||
if [ "$AUTH_MODE" = "pki" ]; then
|
||||
# PKI mode: verify in index.txt
|
||||
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/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/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"
|
||||
# Verify there's also a revoked entry (both should exist)
|
||||
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/server/easy-rsa/pki/index.txt
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "FAIL: Unexpected certificate state"
|
||||
cat /etc/openvpn/server/easy-rsa/pki/index.txt
|
||||
exit 1
|
||||
# Fingerprint mode: verify fingerprint was added back to server.conf
|
||||
if grep -q "# $REVOKE_CLIENT\$" /etc/openvpn/server/server.conf; then
|
||||
echo "PASS: New client fingerprint added to server.conf"
|
||||
else
|
||||
echo "FAIL: New client fingerprint not found in server.conf"
|
||||
cat /etc/openvpn/server/server.conf | grep -A5 "<peer-fingerprint>" || true
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Copy the new config
|
||||
|
||||
Reference in New Issue
Block a user