From c0fcf91972faf314ad462c4c75d446abb46e3ac7 Mon Sep 17 00:00:00 2001 From: Stanislas Date: Wed, 10 Dec 2025 00:11:25 +0100 Subject: [PATCH] feat: add ChaCha20-Poly1305 cipher support (#1330) ## Summary - Add `CHACHA20-POLY1305` as a data channel cipher option - Add `ECDHE-*-CHACHA20-POLY1305` control channel cipher options - Add version check (requires OpenVPN 2.5+) - Update README documentation ChaCha20-Poly1305 is particularly useful on devices without hardware AES acceleration (AES-NI), such as ARM-based devices (Raspberry Pi, etc.) and older CPUs, where it can provide better performance than AES. Closes #1244 Closes #190 --- README.md | 5 ++++ openvpn-install.sh | 62 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 78842af..8cc096d 100644 --- a/README.md +++ b/README.md @@ -275,6 +275,8 @@ AES-256 is 40% slower than AES-128, and there isn't any real reason to use a 256 AES-GCM is an [AEAD cipher](https://en.wikipedia.org/wiki/Authenticated_encryption) which means it simultaneously provides confidentiality, integrity, and authenticity assurances on the data. +ChaCha20-Poly1305 is another AEAD cipher that provides similar security to AES-GCM. It is particularly useful on devices without hardware AES acceleration (AES-NI), such as older CPUs and many ARM-based devices, where it can be significantly faster than AES. + The script supports the following ciphers: - `AES-128-GCM` @@ -283,6 +285,7 @@ The script supports the following ciphers: - `AES-128-CBC` - `AES-192-CBC` - `AES-256-CBC` +- `CHACHA20-POLY1305` (requires OpenVPN 2.5+) And defaults to `AES-128-GCM`. @@ -297,9 +300,11 @@ The script proposes the following options, depending on the certificate: - ECDSA: - `TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256` - `TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384` + - `TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256` (requires OpenVPN 2.5+) - RSA: - `TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256` - `TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384` + - `TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256` (requires OpenVPN 2.5+) It defaults to `TLS-ECDHE-*-WITH-AES-128-GCM-SHA256`. diff --git a/openvpn-install.sh b/openvpn-install.sh index 0e507b0..54909e6 100755 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -235,6 +235,29 @@ function initialCheck() { checkOS } +# Check if OpenVPN version is at least the specified version +# Usage: openvpnVersionAtLeast "2.5" +# Returns 0 if version is >= specified, 1 otherwise +function openvpnVersionAtLeast() { + local required_version="$1" + local installed_version + + if ! command -v openvpn &>/dev/null; then + return 1 + fi + + installed_version=$(openvpn --version 2>/dev/null | head -1 | awk '{print $2}') + if [[ -z "$installed_version" ]]; then + return 1 + fi + + # Compare versions using sort -V + if [[ "$(printf '%s\n' "$required_version" "$installed_version" | sort -V | head -n1)" == "$required_version" ]]; then + return 0 + fi + return 1 +} + function installOpenVPNRepo() { log_info "Setting up official OpenVPN repository..." @@ -645,8 +668,9 @@ function installQuestions() { log_menu " 4) AES-128-CBC" log_menu " 5) AES-192-CBC" log_menu " 6) AES-256-CBC" - until [[ $CIPHER_CHOICE =~ ^[1-6]$ ]]; do - read -rp "Cipher [1-6]: " -e -i 1 CIPHER_CHOICE + log_menu " 7) CHACHA20-POLY1305 (requires OpenVPN 2.5+, good for devices without AES-NI)" + until [[ $CIPHER_CHOICE =~ ^[1-7]$ ]]; do + read -rp "Cipher [1-7]: " -e -i 1 CIPHER_CHOICE done case $CIPHER_CHOICE in 1) @@ -667,6 +691,9 @@ function installQuestions() { 6) CIPHER="AES-256-CBC" ;; + 7) + CIPHER="CHACHA20-POLY1305" + ;; esac log_menu "" log_prompt "Choose what kind of certificate you want to use:" @@ -725,8 +752,9 @@ function installQuestions() { 1) log_menu " 1) ECDHE-ECDSA-AES-128-GCM-SHA256 (recommended)" log_menu " 2) ECDHE-ECDSA-AES-256-GCM-SHA384" - until [[ $CC_CIPHER_CHOICE =~ ^[1-2]$ ]]; do - read -rp "Control channel cipher [1-2]: " -e -i 1 CC_CIPHER_CHOICE + log_menu " 3) ECDHE-ECDSA-CHACHA20-POLY1305 (requires OpenVPN 2.5+)" + until [[ $CC_CIPHER_CHOICE =~ ^[1-3]$ ]]; do + read -rp "Control channel cipher [1-3]: " -e -i 1 CC_CIPHER_CHOICE done case $CC_CIPHER_CHOICE in 1) @@ -735,13 +763,17 @@ function installQuestions() { 2) CC_CIPHER="TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384" ;; + 3) + CC_CIPHER="TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256" + ;; esac ;; 2) log_menu " 1) ECDHE-RSA-AES-128-GCM-SHA256 (recommended)" log_menu " 2) ECDHE-RSA-AES-256-GCM-SHA384" - until [[ $CC_CIPHER_CHOICE =~ ^[1-2]$ ]]; do - read -rp "Control channel cipher [1-2]: " -e -i 1 CC_CIPHER_CHOICE + log_menu " 3) ECDHE-RSA-CHACHA20-POLY1305 (requires OpenVPN 2.5+)" + until [[ $CC_CIPHER_CHOICE =~ ^[1-3]$ ]]; do + read -rp "Control channel cipher [1-3]: " -e -i 1 CC_CIPHER_CHOICE done case $CC_CIPHER_CHOICE in 1) @@ -750,6 +782,9 @@ function installQuestions() { 2) CC_CIPHER="TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384" ;; + 3) + CC_CIPHER="TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256" + ;; esac ;; esac @@ -805,10 +840,10 @@ function installQuestions() { ;; esac log_menu "" - # The "auth" options behaves differently with AEAD ciphers + # The "auth" options behaves differently with AEAD ciphers (GCM, ChaCha20-Poly1305) if [[ $CIPHER =~ CBC$ ]]; then log_prompt "The digest algorithm authenticates data channel packets and tls-auth packets from the control channel." - elif [[ $CIPHER =~ GCM$ ]]; then + elif [[ $CIPHER =~ GCM$ ]] || [[ $CIPHER == "CHACHA20-POLY1305" ]]; then log_prompt "The digest algorithm authenticates tls-auth packets from the control channel." fi log_prompt "Which digest algorithm do you want to use for HMAC?" @@ -934,6 +969,17 @@ function installOpenVPN() { elif [[ $OS == 'arch' ]]; then run_cmd "Installing OpenVPN" pacman --needed --noconfirm -Syu openvpn iptables openssl wget ca-certificates curl fi + + # Verify ChaCha20-Poly1305 compatibility if selected + if [[ $CIPHER == "CHACHA20-POLY1305" ]] || [[ $CC_CIPHER =~ CHACHA20 ]]; then + local installed_version + installed_version=$(openvpn --version 2>/dev/null | head -1 | awk '{print $2}') + if ! openvpnVersionAtLeast "2.5"; then + log_fatal "ChaCha20-Poly1305 requires OpenVPN 2.5 or later. Installed version: $installed_version" + fi + log_info "OpenVPN version supports ChaCha20-Poly1305" + fi + # 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/