Stanislas 9175c2c221 feat: support headless client revocation by name (#1387)
Add support for revoking clients by setting the CLIENT environment
variable directly with the client name, in addition to the existing
CLIENTNUMBER support (from
https://github.com/angristan/openvpn-install/pull/1328)

This makes headless revocation more user-friendly as users no longer
need to know the client's index number.
2025-12-13 20:18:07 +01:00
2019-06-05 01:13:03 +02:00

openvpn-install

Test Lint Say Thanks!

OpenVPN installer for Debian, Ubuntu, Fedora, openSUSE, CentOS, Amazon Linux, Arch Linux, Oracle Linux, Rocky Linux and AlmaLinux.

This script will let you setup your own secure VPN server in just a few seconds.

What is this?

This script is meant to be run on your own server, whether it's a VPS or a dedicated server, or even a computer at home.

Once set up, you will be able to generate client configuration files for every device you want to connect.

Each client will be able to route its internet traffic through the server, fully encrypted.

graph LR
  A[Phone] -->|Encrypted| VPN
  B[Laptop] -->|Encrypted| VPN
  C[Computer] -->|Encrypted| VPN

  VPN[OpenVPN Server]

  VPN --> I[Internet]

Why OpenVPN?

OpenVPN was the de facto standard for open-source VPNs when this script was created. WireGuard came later and is simpler and faster for most use cases. Check out wireguard-install.

That said, OpenVPN still makes sense when you need:

  • TCP support: works in restrictive environments where UDP is blocked (corporate networks, airports, hotels, etc.)
  • Password-protected private keys: WireGuard configs store the private key in plain text
  • Legacy compatibility: clients exist for pretty much every platform, including older systems

Usage

First, on your server, get the script and make it executable:

curl -O https://raw.githubusercontent.com/angristan/openvpn-install/master/openvpn-install.sh
chmod +x openvpn-install.sh

Then run it:

./openvpn-install.sh

You need to run the script as root and have the TUN module enabled.

The first time you run it, you'll have to follow the assistant and answer a few questions to setup your VPN server.

When OpenVPN is installed, you can run the script again, and you will get the choice to:

  • Add a client
  • List client certificates
  • Revoke a client
  • Renew certificates (client or server)
  • Uninstall OpenVPN

In your home directory, you will have .ovpn files. These are the client configuration files. Download them from your server and connect using your favorite OpenVPN client.

If you have any question, head to the FAQ first. And if you need help, you can open a discussion. Please search existing issues and dicussions first.

Headless install

It's also possible to run the script headless, e.g. without waiting for user input, in an automated manner.

Example usage:

AUTO_INSTALL=y ./openvpn-install.sh

# or

export AUTO_INSTALL=y
./openvpn-install.sh

A default set of variables will then be set, by passing the need for user input.

If you want to customise your installation, you can export them or specify them on the same line, as shown above.

  • APPROVE_INSTALL=y
  • APPROVE_IP=y
  • IPV6_SUPPORT=n
  • PORT_CHOICE=1
  • PROTOCOL_CHOICE=1
  • DNS=1
  • COMPRESSION_ENABLED=n
  • CUSTOMIZE_ENC=n
  • CLIENT=clientname
  • PASS=1 (set to 2 for password-protected clients, requires PASSPHRASE)
  • MULTI_CLIENT=n
  • CLIENT_CERT_DURATION_DAYS=3650
  • SERVER_CERT_DURATION_DAYS=3650
  • NEW_CLIENT=y (set to n to skip client creation after installation)

If the server is behind NAT, you can specify its endpoint with the ENDPOINT variable. If the endpoint is the public IP address which it is behind, you can use ENDPOINT=$(curl -4 ifconfig.co) (the script will default to this). The endpoint can be an IPv4 or a domain.

Other variables can be set depending on your choice (encryption, compression). You can search for them in the installQuestions() function of the script.

The headless install is more-or-less idempotent, in that it has been made safe to run multiple times with the same parameters, e.g. by a state provisioner like Ansible/Terraform/Salt/Chef/Puppet. It will only install and regenerate the Easy-RSA PKI if it doesn't already exist, and it will only install OpenVPN and other upstream dependencies if OpenVPN isn't already installed. It will recreate all local config and re-generate the client file on each headless run.

Headless User Addition

It's also possible to automate the addition of a new user. Here, the key is to provide the (string) value of the MENU_OPTION variable along with the remaining mandatory variables before invoking the script.

The following Bash script adds a new user foo to an existing OpenVPN configuration

#!/bin/bash
export MENU_OPTION="1"
export CLIENT="foo"
export PASS="1" # set to "2" for a password-protected client, and set PASSPHRASE
./openvpn-install.sh

Headless User Revocation

It's also possible to automate the revocation of an existing user. The key is to provide the MENU_OPTION variable set to 2 along with either CLIENT (client name) or CLIENTNUMBER (1-based index from the client list).

The following Bash script revokes the existing user foo:

#!/bin/bash
export MENU_OPTION="2"
export CLIENT="foo"
./openvpn-install.sh

Alternatively, you can use the client number:

#!/bin/bash
export MENU_OPTION="2"
export CLIENTNUMBER="1"  # Revokes the first client in the list
./openvpn-install.sh

Features

  • Installs and configures a ready-to-use OpenVPN server
  • Certificate renewal for both client and server certificates
  • Uses official OpenVPN repositories when possible for the latest stable releases
  • Iptables rules and forwarding managed in a seamless way
  • If needed, the script can cleanly remove OpenVPN, including configuration and iptables rules
  • Customisable encryption settings, enhanced default settings (see Security and Encryption below)
  • OpenVPN 2.4 features, mainly encryption improvements (see Security and Encryption below)
  • Variety of DNS resolvers to be pushed to the clients
  • Choice to use a self-hosted resolver with Unbound (supports already existing Unbound installations)
  • Choice between TCP and UDP
  • NATed IPv6 support
  • Compression disabled by default to prevent VORACLE. LZ4 (v1/v2) and LZ0 algorithms available otherwise.
  • Unprivileged mode: run as nobody/nogroup
  • Block DNS leaks on Windows 10
  • 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)
  • Many other little things!

Compatibility

The script supports these Linux distributions:

Support
AlmaLinux >= 8 🤖
Amazon Linux 2023 🤖
Arch Linux 🤖
CentOS Stream >= 8 🤖
Debian >= 11 🤖
Fedora >= 40 🤖
openSUSE Leap >= 16 🤖
openSUSE Tumbleweed 🤖
Oracle Linux >= 8 🤖
Rocky Linux >= 8 🤖
Ubuntu >= 18.04 🤖

To be noted:

  • The script is regularly tested against the distributions marked with a 🤖 only.
    • It's only tested on amd64 architecture.
  • The script requires systemd.

Fork

This script is based on the great work of Nyr and its contributors.

Since 2016, the two scripts have diverged and are not alike anymore, especially under the hood. The main goal of the script was enhanced security. But since then, the script has been completely rewritten and a lot a features have been added. The script is only compatible with recent distributions though, so if you need to use a very old server or client, I advise using Nyr's script.

FAQ

More Q&A in FAQ.md.

Q: Which provider do you recommend?

A: I recommend these:

  • Vultr: Worldwide locations, IPv6 support, starting at $5/month
  • Hetzner: Germany, Finland and USA. IPv6, 20 TB of traffic, starting at 4.5€/month
  • Digital Ocean: Worldwide locations, IPv6 support, starting at $4/month

Q: Which OpenVPN client do you recommend?

A: If possible, an official OpenVPN 2.4 client.


Q: Am I safe from the NSA by using your script?

A: Please review your threat models. Even if this script has security in mind and uses state-of-the-art encryption, you shouldn't be using a VPN if you want to hide from the NSA.


Q: Is there an OpenVPN documentation?

A: Yes, please head to the OpenVPN Manual, which references all the options.


More Q&A in FAQ.md.

Contributing

Discuss changes

Please open an issue before submitting a PR if you want to discuss a change, especially if it's a big one.

Code formatting

We use shellcheck and shfmt to enforce Bash styling guidelines and good practices. They are executed for each commit / PR with GitHub Actions, so you can check the lint workflow configuration.

Security and Encryption

Note

This script was created in 2016 when OpenVPN's defaults were quite weak. Back then, customising encryption settings was essential for a secure setup. Since then, OpenVPN has significantly improved its defaults, but the script still offers customisation options.

OpenVPN 2.3 and earlier shipped with outdated defaults like Blowfish (BF-CBC), TLS 1.0, and SHA1. Each major release since has brought significant improvements:

  • OpenVPN 2.4 (2016): Added ECDSA, ECDH, AES-GCM, NCP (cipher negotiation), and tls-crypt
  • OpenVPN 2.5 (2020): Default cipher changed from BF-CBC to AES-256-GCM:AES-128-GCM, added ChaCha20-Poly1305, tls-crypt-v2, and TLS 1.3 support
  • OpenVPN 2.6 (2023): TLS 1.2 minimum by default, compression blocked by default, --peer-fingerprint for PKI-less setups, and DCO kernel acceleration

If you want more information about an option mentioned below, head to the OpenVPN manual. It is very complete.

Certificate and PKI management is handled by Easy-RSA. Default parameters are in the vars.example file.

Compression

Note

OpenVPN 2.6+ defaults --allow-compression to no, which blocks even server-pushed compression. Prior versions allowed servers to push compression settings to clients.

By default, OpenVPN doesn't enable compression. This script provides support for LZ0 and LZ4 (v1/v2) algorithms, the latter being more efficient.

However, it is discouraged to use compression since the VORACLE attack makes use of it.

TLS version

Note

OpenVPN 2.6+ defaults to TLS 1.2 minimum. Prior versions accepted TLS 1.0 by default.

OpenVPN 2.5 and earlier accepted TLS 1.0 by default, which is nearly 20 years old.

With tls-version-min 1.2 we enforce TLS 1.2, which the best protocol available currently for OpenVPN.

TLS 1.2 is supported since OpenVPN 2.3.3.

Certificate

OpenVPN uses an RSA certificate with a 2048 bits key by default.

OpenVPN 2.4 added support for ECDSA. Elliptic curve cryptography is faster, lighter and more secure.

This script provides:

  • ECDSA: prime256v1/secp384r1/secp521r1 curves
  • RSA: 2048/3072/4096 bits keys

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.

Data channel

Note

The default data channel cipher changed in OpenVPN 2.5. Prior versions defaulted to BF-CBC, while OpenVPN 2.5+ defaults to AES-256-GCM:AES-128-GCM. OpenVPN 2.6+ also includes CHACHA20-POLY1305 in the default cipher list when available.

By default, OpenVPN 2.4 and earlier used BF-CBC as the data channel cipher. Blowfish is an old (1993) and weak algorithm. Even the official OpenVPN documentation admits it.

The default is BF-CBC, an abbreviation for Blowfish in Cipher Block Chaining mode.

Using BF-CBC is no longer recommended, because of its 64-bit block size. This small block size allows attacks based on collisions, as demonstrated by SWEET32. See https://community.openvpn.net/openvpn/wiki/SWEET32 for details. Security researchers at INRIA published an attack on 64-bit block ciphers, such as 3DES and Blowfish. They show that they are able to recover plaintext when the same data is sent often enough, and show how they can use cross-site scripting vulnerabilities to send data of interest often enough. This works over HTTPS, but also works for HTTP-over-OpenVPN. See https://sweet32.info/ for a much better and more elaborate explanation.

OpenVPN's default cipher, BF-CBC, is affected by this attack.

Indeed, AES is today's standard. It's the fastest and more secure cipher available today. SEED and Camellia are not vulnerable to date but are slower than AES and relatively less trusted.

Of the currently supported ciphers, OpenVPN currently recommends using AES-256-CBC or AES-128-CBC. OpenVPN 2.4 and newer will also support GCM. For 2.4+, we recommend using AES-256-GCM or AES-128-GCM.

AES-256 is 40% slower than AES-128, and there isn't any real reason to use a 256 bits key over a 128 bits key with AES. (Source: 1,2). Moreover, AES-256 is more vulnerable to Timing attacks.

AES-GCM is an AEAD cipher 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
  • AES-192-GCM
  • AES-256-GCM
  • AES-128-CBC
  • AES-192-CBC
  • AES-256-CBC
  • CHACHA20-POLY1305 (requires OpenVPN 2.5+)

And defaults to AES-128-GCM.

OpenVPN 2.4 added a feature called "NCP": Negotiable Crypto Parameters. It means you can provide a cipher suite like with HTTPS. It is set to AES-256-GCM:AES-128-GCM by default and overrides the --cipher parameter when used with an OpenVPN 2.4 client. For the sake of simplicity, the script sets --cipher (fallback for non-NCP clients), --data-ciphers (modern OpenVPN 2.5+ naming), and --ncp-ciphers (legacy alias for OpenVPN 2.4 compatibility) to the cipher chosen above.

Control channel

OpenVPN 2.4 will negotiate the best cipher available by default (e.g ECDHE+AES-256-GCM)

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.

Diffie-Hellman key exchange

OpenVPN uses a 2048 bits DH key by default.

OpenVPN 2.4 added support for ECDH keys. Elliptic curve cryptography is faster, lighter and more secure.

Also, generating a classic DH keys can take a long, looong time. ECDH keys are ephemeral: they are generated on-the-fly.

The script provides the following options:

  • ECDH: prime256v1/secp384r1/secp521r1 curves
  • DH: 2048/3072/4096 bits keys

It defaults to prime256v1.

HMAC digest algorithm

From the OpenVPN wiki, about --auth:

Authenticate data channel packets and (if enabled) tls-auth control channel packets with HMAC using message digest algorithm alg. (The default is SHA1 ). HMAC is a commonly used message authentication algorithm (MAC) that uses a data string, a secure hash algorithm, and a key, to produce a digital signature.

If an AEAD cipher mode (e.g. GCM) is chosen, the specified --auth algorithm is ignored for the data channel, and the authentication method of the AEAD cipher is used instead. Note that alg still specifies the digest used for tls-auth.

The script provides the following choices:

  • SHA256
  • SHA384
  • SHA512

It defaults to SHA256.

tls-auth, tls-crypt, and tls-crypt-v2

From the OpenVPN wiki, about tls-auth:

Add an additional layer of HMAC authentication on top of the TLS control channel to mitigate DoS attacks and attacks on the TLS stack.

In a nutshell, --tls-auth enables a kind of "HMAC firewall" on OpenVPN's TCP/UDP port, where TLS control channel packets bearing an incorrect HMAC signature can be dropped immediately without response.

About tls-crypt:

Encrypt and authenticate all control channel packets with the key from keyfile. (See --tls-auth for more background.)

Encrypting (and authenticating) control channel packets:

  • provides more privacy by hiding the certificate used for the TLS connection,
  • makes it harder to identify OpenVPN traffic as such,
  • provides "poor-man's" post-quantum security, against attackers who will never know the pre-shared key (i.e. no forward secrecy).

So both provide an additional layer of security and mitigate DoS attacks. They aren't used by default by OpenVPN.

tls-crypt is an OpenVPN 2.4 feature that provides encryption in addition to authentication (unlike tls-auth). It is more privacy-friendly.

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)

The server is configured with remote-cert-tls client, which requires connecting peers to have a certificate with the "TLS Web Client Authentication" extended key usage. This prevents a server certificate from being used to impersonate a client.

Similarly, clients are configured with remote-cert-tls server to ensure they only connect to servers presenting valid server certificates. This protects against an attacker with a valid client certificate setting up a rogue server.

Data Channel Offload (DCO)

Data Channel Offload (DCO) is a kernel acceleration feature that significantly improves OpenVPN performance by keeping data channel encryption/decryption in kernel space, eliminating costly context switches between user and kernel space for each packet.

DCO was merged into the Linux kernel 6.16 (April 2025).

Requirements:

  • OpenVPN 2.6.0 or later
  • Linux kernel 6.16+ (built-in) or ovpn-dco kernel module
  • UDP protocol (TCP is not supported)
  • AEAD cipher (AES-128-GCM, AES-256-GCM, or CHACHA20-POLY1305)
  • Compression disabled

The script's default settings (AES-128-GCM, UDP, no compression) are DCO-compatible. When DCO is available and the configuration is compatible, OpenVPN will automatically use it for improved performance.

Note: DCO must be supported on both the server and the client for full acceleration. Client support is available in OpenVPN 2.6+ (Linux, Windows, FreeBSD) and OpenVPN Connect 3.4+ (Windows). macOS does not currently support DCO, but clients can still connect to DCO-enabled servers with partial performance benefits on the server-side.

The script will display the DCO availability status during installation.

Say thanks

You can say thanks if you want!

Credits & Licence

Many thanks to the contributors and Nyr's original work.

This project is under the MIT Licence

Star History

Star History Chart

Languages
Shell 97.7%
Makefile 2.3%