mirror of
https://github.com/angristan/openvpn-install.git
synced 2025-12-15 16:37:03 +01:00
feat: add tls-crypt-v2 support with per-client keys (#1377)
## Summary - Add support for OpenVPN's `tls-crypt-v2` feature (per-client TLS keys) - Set `tls-crypt-v2` as the new recommended default - Add CI tests for all 3 TLS key types Closes #983 Closes #758 Closes https://github.com/angristan/openvpn-install/pull/1257 ## What is tls-crypt-v2? Unlike `tls-crypt` (shared key), `tls-crypt-v2` generates unique keys per client: - **Better security**: Compromised client keys don't affect other clients - **Easier management**: Individual client key revocation without regenerating server key - **Scalability**: Better suited for large deployments Requires OpenVPN 2.5+ (released 2020). ## Menu options ``` 1) tls-crypt-v2 (recommended): Encrypts control channel, unique key per client 2) tls-crypt: Encrypts control channel, shared key for all clients 3) tls-auth: Authenticates control channel, no encryption ```
This commit is contained in:
37
.github/workflows/docker-test.yml
vendored
37
.github/workflows/docker-test.yml
vendored
@@ -68,6 +68,27 @@ jobs:
|
||||
image: oraclelinux:10
|
||||
- name: amazonlinux-2023
|
||||
image: amazonlinux:2023
|
||||
# Default TLS settings (tls-crypt-v2)
|
||||
tls:
|
||||
- name: tls-crypt-v2
|
||||
sig: "1"
|
||||
key_file: tls-crypt-v2.key
|
||||
# Additional TLS types tested on Ubuntu 24.04 only
|
||||
include:
|
||||
- os:
|
||||
name: ubuntu-24.04-tls-crypt
|
||||
image: ubuntu:24.04
|
||||
tls:
|
||||
name: tls-crypt
|
||||
sig: "2"
|
||||
key_file: tls-crypt.key
|
||||
- os:
|
||||
name: ubuntu-24.04-tls-auth
|
||||
image: ubuntu:24.04
|
||||
tls:
|
||||
name: tls-auth
|
||||
sig: "3"
|
||||
key_file: tls-auth.key
|
||||
|
||||
name: ${{ matrix.os.name }}
|
||||
steps:
|
||||
@@ -110,6 +131,8 @@ jobs:
|
||||
--tmpfs /run \
|
||||
--tmpfs /run/lock \
|
||||
--stop-signal SIGRTMIN+3 \
|
||||
-e TLS_SIG=${{ matrix.tls.sig }} \
|
||||
-e TLS_KEY_FILE=${{ matrix.tls.key_file }} \
|
||||
openvpn-server
|
||||
|
||||
- name: Wait for server installation and startup
|
||||
@@ -151,8 +174,18 @@ jobs:
|
||||
sleep 5
|
||||
done
|
||||
|
||||
# Final verification
|
||||
if ! docker exec openvpn-server pgrep -f "openvpn.*server.conf" > /dev/null 2>&1; then
|
||||
# Final verification with retry (handles race condition during cert renewal restart)
|
||||
OPENVPN_STARTED=false
|
||||
for retry in {1..5}; do
|
||||
if docker exec openvpn-server pgrep -f "openvpn.*server.conf" > /dev/null 2>&1; then
|
||||
OPENVPN_STARTED=true
|
||||
break
|
||||
fi
|
||||
echo "Waiting for OpenVPN process... (retry $retry/5)"
|
||||
sleep 2
|
||||
done
|
||||
|
||||
if [ "$OPENVPN_STARTED" = false ]; then
|
||||
echo "ERROR: OpenVPN server failed to start"
|
||||
docker exec openvpn-server systemctl status openvpn-server@server 2>&1 || true
|
||||
docker exec openvpn-server journalctl -u openvpn-test.service --no-pager -n 100 2>&1 || true
|
||||
|
||||
14
README.md
14
README.md
@@ -359,7 +359,7 @@ The script provides the following choices:
|
||||
|
||||
It defaults to `SHA256`.
|
||||
|
||||
### `tls-auth` and `tls-crypt`
|
||||
### `tls-auth`, `tls-crypt`, and `tls-crypt-v2`
|
||||
|
||||
From the OpenVPN wiki, about `tls-auth`:
|
||||
|
||||
@@ -381,7 +381,17 @@ So both provide an additional layer of security and mitigate DoS attacks. They a
|
||||
|
||||
`tls-crypt` is an OpenVPN 2.4 feature that provides encryption in addition to authentication (unlike `tls-auth`). It is more privacy-friendly.
|
||||
|
||||
The script supports both and uses `tls-crypt` by default.
|
||||
`tls-crypt-v2` is an OpenVPN 2.5 feature that builds on `tls-crypt` by using **per-client keys** instead of a shared key. Each client receives a unique key derived from a server key. This provides:
|
||||
|
||||
- **Better security**: If a client key is compromised, other clients are not affected
|
||||
- **Easier key management**: Client keys can be revoked individually without regenerating the server key
|
||||
- **Scalability**: Better suited for large deployments with many clients
|
||||
|
||||
The script supports all three options:
|
||||
|
||||
- `tls-crypt-v2` (default): Per-client keys for better security
|
||||
- `tls-crypt`: Shared key for all clients, compatible with OpenVPN 2.4+
|
||||
- `tls-auth`: HMAC authentication only (no encryption), compatible with older clients
|
||||
|
||||
### Certificate type verification (`remote-cert-tls`)
|
||||
|
||||
|
||||
@@ -749,7 +749,7 @@ function installQuestions() {
|
||||
DH_TYPE="1" # ECDH
|
||||
DH_CURVE="prime256v1"
|
||||
HMAC_ALG="SHA256"
|
||||
TLS_SIG="1" # tls-crypt
|
||||
TLS_SIG="1" # tls-crypt-v2
|
||||
else
|
||||
log_menu ""
|
||||
log_prompt "Choose which cipher you want to use for the data channel:"
|
||||
@@ -956,12 +956,12 @@ function installQuestions() {
|
||||
;;
|
||||
esac
|
||||
log_menu ""
|
||||
log_prompt "You can add an additional layer of security to the control channel with tls-auth and tls-crypt"
|
||||
log_prompt "tls-auth authenticates the packets, while tls-crypt authenticate and encrypt them."
|
||||
log_menu " 1) tls-crypt (recommended)"
|
||||
log_menu " 2) tls-auth"
|
||||
until [[ $TLS_SIG =~ [1-2] ]]; do
|
||||
read -rp "Control channel additional security mechanism [1-2]: " -e -i 1 TLS_SIG
|
||||
log_prompt "You can add an additional layer of security to the control channel."
|
||||
log_menu " 1) tls-crypt-v2 (recommended): Encrypts control channel, unique key per client"
|
||||
log_menu " 2) tls-crypt: Encrypts control channel, shared key for all clients"
|
||||
log_menu " 3) tls-auth: Authenticates control channel, no encryption"
|
||||
until [[ $TLS_SIG =~ ^[1-3]$ ]]; do
|
||||
read -rp "Control channel additional security mechanism [1-3]: " -e -i 1 TLS_SIG
|
||||
done
|
||||
fi
|
||||
log_menu ""
|
||||
@@ -1170,10 +1170,14 @@ function installOpenVPN() {
|
||||
log_info "Generating TLS key..."
|
||||
case $TLS_SIG in
|
||||
1)
|
||||
# Generate tls-crypt-v2 server key
|
||||
run_cmd_fatal "Generating tls-crypt-v2 server key" openvpn --genkey tls-crypt-v2-server /etc/openvpn/server/tls-crypt-v2.key
|
||||
;;
|
||||
2)
|
||||
# Generate tls-crypt key
|
||||
run_cmd_fatal "Generating tls-crypt key" openvpn --genkey --secret /etc/openvpn/server/tls-crypt.key
|
||||
;;
|
||||
2)
|
||||
3)
|
||||
# Generate tls-auth key
|
||||
run_cmd_fatal "Generating tls-auth key" openvpn --genkey --secret /etc/openvpn/server/tls-auth.key
|
||||
;;
|
||||
@@ -1320,9 +1324,12 @@ push "redirect-gateway ipv6"' >>/etc/openvpn/server/server.conf
|
||||
|
||||
case $TLS_SIG in
|
||||
1)
|
||||
echo "tls-crypt tls-crypt.key" >>/etc/openvpn/server/server.conf
|
||||
echo "tls-crypt-v2 tls-crypt-v2.key" >>/etc/openvpn/server/server.conf
|
||||
;;
|
||||
2)
|
||||
echo "tls-crypt tls-crypt.key" >>/etc/openvpn/server/server.conf
|
||||
;;
|
||||
3)
|
||||
echo "tls-auth tls-auth.key 0" >>/etc/openvpn/server/server.conf
|
||||
;;
|
||||
esac
|
||||
@@ -1550,12 +1557,14 @@ function generateClientConfig() {
|
||||
local client="$1"
|
||||
local home_dir="$2"
|
||||
|
||||
# Determine if we use tls-auth or tls-crypt
|
||||
# Determine if we use tls-crypt-v2, tls-crypt, or tls-auth
|
||||
local tls_sig=""
|
||||
if grep -qs "^tls-crypt" /etc/openvpn/server/server.conf; then
|
||||
if grep -qs "^tls-crypt-v2" /etc/openvpn/server/server.conf; then
|
||||
tls_sig="1"
|
||||
elif grep -qs "^tls-auth" /etc/openvpn/server/server.conf; then
|
||||
elif grep -qs "^tls-crypt" /etc/openvpn/server/server.conf; then
|
||||
tls_sig="2"
|
||||
elif grep -qs "^tls-auth" /etc/openvpn/server/server.conf; then
|
||||
tls_sig="3"
|
||||
fi
|
||||
|
||||
# Generate the custom client.ovpn
|
||||
@@ -1575,11 +1584,25 @@ function generateClientConfig() {
|
||||
|
||||
case $tls_sig in
|
||||
1)
|
||||
# Generate per-client tls-crypt-v2 key using secure temp file
|
||||
tls_crypt_v2_tmpfile=$(mktemp)
|
||||
if ! openvpn --tls-crypt-v2 /etc/openvpn/server/tls-crypt-v2.key \
|
||||
--genkey tls-crypt-v2-client "$tls_crypt_v2_tmpfile"; then
|
||||
rm -f "$tls_crypt_v2_tmpfile"
|
||||
log_error "Failed to generate tls-crypt-v2 client key"
|
||||
exit 1
|
||||
fi
|
||||
echo "<tls-crypt-v2>"
|
||||
cat "$tls_crypt_v2_tmpfile"
|
||||
echo "</tls-crypt-v2>"
|
||||
rm -f "$tls_crypt_v2_tmpfile"
|
||||
;;
|
||||
2)
|
||||
echo "<tls-crypt>"
|
||||
cat /etc/openvpn/server/tls-crypt.key
|
||||
echo "</tls-crypt>"
|
||||
;;
|
||||
2)
|
||||
3)
|
||||
echo "key-direction 1"
|
||||
echo "<tls-auth>"
|
||||
cat /etc/openvpn/server/tls-auth.key
|
||||
|
||||
@@ -22,11 +22,33 @@ export PORT_CHOICE=1
|
||||
export PROTOCOL_CHOICE=1
|
||||
export DNS=2 # Self-hosted Unbound DNS resolver
|
||||
export COMPRESSION_ENABLED=n
|
||||
export CUSTOMIZE_ENC=n
|
||||
export CLIENT=testclient
|
||||
export PASS=1
|
||||
export ENDPOINT=openvpn-server
|
||||
|
||||
# TLS key type configuration (default: tls-crypt-v2)
|
||||
# TLS_SIG: 1=tls-crypt-v2, 2=tls-crypt, 3=tls-auth
|
||||
# TLS_KEY_FILE: the expected key file name for verification
|
||||
TLS_SIG="${TLS_SIG:-1}"
|
||||
TLS_KEY_FILE="${TLS_KEY_FILE:-tls-crypt-v2.key}"
|
||||
export TLS_SIG
|
||||
|
||||
# If using non-default TLS settings, enable encryption customization
|
||||
if [ "$TLS_SIG" != "1" ]; then
|
||||
export CUSTOMIZE_ENC=y
|
||||
# Set other encryption defaults when customizing
|
||||
export CIPHER_CHOICE=1 # AES-128-GCM
|
||||
export CERT_TYPE=1 # ECDSA
|
||||
export CERT_CURVE_CHOICE=1 # prime256v1
|
||||
export CC_CIPHER_CHOICE=1 # ECDHE-ECDSA-AES-128-GCM-SHA256
|
||||
export DH_TYPE=1 # ECDH
|
||||
export DH_CURVE_CHOICE=1 # prime256v1
|
||||
export HMAC_ALG_CHOICE=1 # SHA-256
|
||||
echo "Testing TLS key type: $TLS_SIG (key file: $TLS_KEY_FILE)"
|
||||
else
|
||||
export CUSTOMIZE_ENC=n
|
||||
fi
|
||||
|
||||
echo "Running OpenVPN install script..."
|
||||
# Run in subshell because the script calls 'exit 0' after generating client config
|
||||
# Capture output to validate logging format, while still displaying it
|
||||
@@ -59,7 +81,7 @@ for f in \
|
||||
/etc/openvpn/server/server.conf \
|
||||
/etc/openvpn/server/ca.crt \
|
||||
/etc/openvpn/server/ca.key \
|
||||
/etc/openvpn/server/tls-crypt.key \
|
||||
"/etc/openvpn/server/$TLS_KEY_FILE" \
|
||||
/etc/openvpn/server/crl.pem \
|
||||
/etc/openvpn/server/easy-rsa/pki/ca.crt \
|
||||
/etc/iptables/add-openvpn-rules.sh \
|
||||
|
||||
Reference in New Issue
Block a user