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
This commit is contained in:
Stanislas
2025-12-10 00:11:25 +01:00
committed by GitHub
parent ffcffac061
commit c0fcf91972
2 changed files with 59 additions and 8 deletions

View File

@@ -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`.

View File

@@ -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/