mirror of
https://github.com/angristan/openvpn-install.git
synced 2025-12-14 16:17:03 +01:00
feat: add certificate renewal functionality (#1328)
## Summary
- Add certificate renewal for both client and server certificates
- Allow custom validity period during renewal (prompts user, defaults to
3650 days)
- Show expiry info inline in menus (e.g., "Renew the server certificate
(expires in 3542 days)")
- Regenerate `.ovpn` files after client renewal
- Restart OpenVPN service after server renewal
- Extract reusable helper functions to reduce code duplication
- Add robust input validation and error handling
## New menu option
```
What do you want to do?
1) Add a new user
2) Revoke existing user
3) Renew certificate ← NEW
4) Remove OpenVPN
5) Exit
```
## Renewal submenu
```
What do you want to renew?
1) Renew a client certificate
2) Renew the server certificate (expires in 3542 days)
3) Back to main menu
```
Client list shows expiry for each:
```
Select the existing client certificate you want to renew
1) alice (expires in 3542 days)
2) bob (expires in 30 days)
3) charlie (EXPIRED 5 days ago)
```
## Helper functions added
Extracted common code into reusable functions:
- `getHomeDir()` - home directory detection
- `regenerateCRL()` - CRL regeneration after cert changes
- `generateClientConfig()` - .ovpn file generation
- `selectClient()` - client listing with optional expiry display
- `getDaysUntilExpiry()` - certificate expiry calculation
- `formatExpiry()` - human-readable expiry formatting
## Test plan
- [x] Client certificate renewal tested in Docker CI
- [x] Server certificate renewal tested in Docker CI
- [x] Certificate validity verified after renewal (~3650 days)
- [x] VPN connectivity tested with renewed certificate
Closes #974 #1002 #1228 #1060
This commit is contained in:
8
FAQ.md
8
FAQ.md
@@ -8,6 +8,14 @@ You can, of course, it's even recommended, update the `openvpn` package with you
|
||||
|
||||
---
|
||||
|
||||
**Q:** How do I renew certificates before they expire?
|
||||
|
||||
**A:** Run the script again and select "Renew certificates" from the menu. You can renew either client certificates or the server certificate. The script will show you the current expiration date for each certificate and let you choose a new validity period (default: 3650 days / 10 years).
|
||||
|
||||
For client renewals, a new `.ovpn` file will be generated that you need to distribute to the client. For server renewals, the OpenVPN service will need to be restarted (the script will prompt you).
|
||||
|
||||
---
|
||||
|
||||
**Q:** How do I check for DNS leaks?
|
||||
|
||||
**A:** Go to [browserleaks.com](https://browserleaks.com/dns) or [ipleak.net](https://ipleak.net/) (both perform IPv4 and IPv6 check) with your browser. Your IP should not show up (test without and without the VPN). The DNS servers should be the ones you selected during the setup, not your IP address nor your ISP's DNS servers' addresses.
|
||||
|
||||
@@ -52,6 +52,7 @@ When OpenVPN is installed, you can run the script again, and you will get the ch
|
||||
|
||||
- Add a client
|
||||
- Remove 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.
|
||||
@@ -113,6 +114,7 @@ export PASS="1"
|
||||
## Features
|
||||
|
||||
- Installs and configures a ready-to-use OpenVPN server
|
||||
- Certificate renewal for both client and server certificates
|
||||
- Uses [official OpenVPN repositories](https://community.openvpn.net/openvpn/wiki/OpenvpnSoftwareRepos) 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
|
||||
|
||||
@@ -1318,6 +1318,116 @@ verb 3" >>/etc/openvpn/client-template.txt
|
||||
log_success "If you want to add more clients, you simply need to run this script another time!"
|
||||
}
|
||||
|
||||
# Helper function to get the home directory for storing client configs
|
||||
function getHomeDir() {
|
||||
local client="$1"
|
||||
if [ -e "/home/${client}" ]; then
|
||||
echo "/home/${client}"
|
||||
elif [ "${SUDO_USER}" ]; then
|
||||
if [ "${SUDO_USER}" == "root" ]; then
|
||||
echo "/root"
|
||||
else
|
||||
echo "/home/${SUDO_USER}"
|
||||
fi
|
||||
else
|
||||
echo "/root"
|
||||
fi
|
||||
}
|
||||
|
||||
# Helper function to regenerate the CRL after certificate changes
|
||||
function regenerateCRL() {
|
||||
export EASYRSA_CRL_DAYS=$CRL_VALIDITY_DAYS
|
||||
run_cmd "Regenerating CRL" ./easyrsa gen-crl
|
||||
run_cmd "Removing old CRL" rm -f /etc/openvpn/crl.pem
|
||||
run_cmd "Copying new CRL" cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem
|
||||
run_cmd "Setting CRL permissions" chmod 644 /etc/openvpn/crl.pem
|
||||
}
|
||||
|
||||
# Helper function to generate .ovpn client config file
|
||||
function generateClientConfig() {
|
||||
local client="$1"
|
||||
local home_dir="$2"
|
||||
|
||||
# Determine if we use tls-auth or tls-crypt
|
||||
local tls_sig=""
|
||||
if grep -qs "^tls-crypt" /etc/openvpn/server.conf; then
|
||||
tls_sig="1"
|
||||
elif grep -qs "^tls-auth" /etc/openvpn/server.conf; then
|
||||
tls_sig="2"
|
||||
fi
|
||||
|
||||
# Generate the custom client.ovpn
|
||||
run_cmd "Creating client config" cp /etc/openvpn/client-template.txt "$home_dir/$client.ovpn"
|
||||
{
|
||||
echo "<ca>"
|
||||
cat "/etc/openvpn/easy-rsa/pki/ca.crt"
|
||||
echo "</ca>"
|
||||
|
||||
echo "<cert>"
|
||||
awk '/BEGIN/,/END CERTIFICATE/' "/etc/openvpn/easy-rsa/pki/issued/$client.crt"
|
||||
echo "</cert>"
|
||||
|
||||
echo "<key>"
|
||||
cat "/etc/openvpn/easy-rsa/pki/private/$client.key"
|
||||
echo "</key>"
|
||||
|
||||
case $tls_sig in
|
||||
1)
|
||||
echo "<tls-crypt>"
|
||||
cat /etc/openvpn/tls-crypt.key
|
||||
echo "</tls-crypt>"
|
||||
;;
|
||||
2)
|
||||
echo "key-direction 1"
|
||||
echo "<tls-auth>"
|
||||
cat /etc/openvpn/tls-auth.key
|
||||
echo "</tls-auth>"
|
||||
;;
|
||||
esac
|
||||
} >>"$home_dir/$client.ovpn"
|
||||
}
|
||||
|
||||
# Helper function to list valid clients and select one
|
||||
# Arguments: show_expiry (optional, "true" to show expiry info)
|
||||
# Sets global variables:
|
||||
# CLIENT - the selected client name
|
||||
# CLIENTNUMBER - the selected client number (1-based index)
|
||||
# NUMBEROFCLIENTS - total count of valid clients
|
||||
function selectClient() {
|
||||
local show_expiry="${1:-false}"
|
||||
local client_number
|
||||
|
||||
NUMBEROFCLIENTS=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -c "^V")
|
||||
if [[ $NUMBEROFCLIENTS == '0' ]]; then
|
||||
log_fatal "You have no existing clients!"
|
||||
fi
|
||||
|
||||
if [[ $show_expiry == "true" ]]; then
|
||||
local i=1
|
||||
while read -r client; do
|
||||
local client_cert="/etc/openvpn/easy-rsa/pki/issued/$client.crt"
|
||||
local days
|
||||
days=$(getDaysUntilExpiry "$client_cert")
|
||||
local expiry
|
||||
expiry=$(formatExpiry "$days")
|
||||
echo " $i) $client $expiry"
|
||||
((i++))
|
||||
done < <(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2)
|
||||
else
|
||||
tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
|
||||
fi
|
||||
|
||||
until [[ ${CLIENTNUMBER:-$client_number} -ge 1 && ${CLIENTNUMBER:-$client_number} -le $NUMBEROFCLIENTS ]]; do
|
||||
if [[ $NUMBEROFCLIENTS == '1' ]]; then
|
||||
read -rp "Select one client [1]: " client_number
|
||||
else
|
||||
read -rp "Select one client [1-$NUMBEROFCLIENTS]: " client_number
|
||||
fi
|
||||
done
|
||||
CLIENTNUMBER="${CLIENTNUMBER:-$client_number}"
|
||||
CLIENT=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p)
|
||||
}
|
||||
|
||||
function newClient() {
|
||||
log_header "New Client Setup"
|
||||
log_prompt "Tell me a name for the client."
|
||||
@@ -1327,10 +1437,12 @@ function newClient() {
|
||||
read -rp "Client name: " -e CLIENT
|
||||
done
|
||||
|
||||
if [[ -z $DAYS_VALID ]]; then
|
||||
if [[ -z $DAYS_VALID ]] || ! [[ $DAYS_VALID =~ ^[0-9]+$ ]] || [[ $DAYS_VALID -lt 1 ]]; then
|
||||
log_menu ""
|
||||
log_prompt "How many days should the client certificate be valid for?"
|
||||
read -rp "Certificate validity (days): " -e -i 3650 DAYS_VALID
|
||||
until [[ $DAYS_VALID =~ ^[0-9]+$ ]] && [[ $DAYS_VALID -ge 1 ]]; do
|
||||
read -rp "Certificate validity (days): " -e -i 3650 DAYS_VALID
|
||||
done
|
||||
fi
|
||||
|
||||
log_menu ""
|
||||
@@ -1363,59 +1475,9 @@ function newClient() {
|
||||
log_success "Client $CLIENT added and is valid for $DAYS_VALID days."
|
||||
fi
|
||||
|
||||
# Home directory of the user, where the client configuration will be written
|
||||
if [ -e "/home/${CLIENT}" ]; then
|
||||
# if $1 is a user name
|
||||
homeDir="/home/${CLIENT}"
|
||||
elif [ "${SUDO_USER}" ]; then
|
||||
# if not, use SUDO_USER
|
||||
if [ "${SUDO_USER}" == "root" ]; then
|
||||
# If running sudo as root
|
||||
homeDir="/root"
|
||||
else
|
||||
homeDir="/home/${SUDO_USER}"
|
||||
fi
|
||||
else
|
||||
# if not SUDO_USER, use /root
|
||||
homeDir="/root"
|
||||
fi
|
||||
|
||||
# Determine if we use tls-auth or tls-crypt
|
||||
if grep -qs "^tls-crypt" /etc/openvpn/server.conf; then
|
||||
TLS_SIG="1"
|
||||
elif grep -qs "^tls-auth" /etc/openvpn/server.conf; then
|
||||
TLS_SIG="2"
|
||||
fi
|
||||
|
||||
# Generates the custom client.ovpn
|
||||
run_cmd "Creating client config" cp /etc/openvpn/client-template.txt "$homeDir/$CLIENT.ovpn"
|
||||
{
|
||||
echo "<ca>"
|
||||
cat "/etc/openvpn/easy-rsa/pki/ca.crt"
|
||||
echo "</ca>"
|
||||
|
||||
echo "<cert>"
|
||||
awk '/BEGIN/,/END CERTIFICATE/' "/etc/openvpn/easy-rsa/pki/issued/$CLIENT.crt"
|
||||
echo "</cert>"
|
||||
|
||||
echo "<key>"
|
||||
cat "/etc/openvpn/easy-rsa/pki/private/$CLIENT.key"
|
||||
echo "</key>"
|
||||
|
||||
case $TLS_SIG in
|
||||
1)
|
||||
echo "<tls-crypt>"
|
||||
cat /etc/openvpn/tls-crypt.key
|
||||
echo "</tls-crypt>"
|
||||
;;
|
||||
2)
|
||||
echo "key-direction 1"
|
||||
echo "<tls-auth>"
|
||||
cat /etc/openvpn/tls-auth.key
|
||||
echo "</tls-auth>"
|
||||
;;
|
||||
esac
|
||||
} >>"$homeDir/$CLIENT.ovpn"
|
||||
# Generate the .ovpn config file
|
||||
homeDir=$(getHomeDir "$CLIENT")
|
||||
generateClientConfig "$CLIENT" "$homeDir"
|
||||
|
||||
log_menu ""
|
||||
log_success "The configuration file has been written to $homeDir/$CLIENT.ovpn."
|
||||
@@ -1425,30 +1487,14 @@ function newClient() {
|
||||
}
|
||||
|
||||
function revokeClient() {
|
||||
NUMBEROFCLIENTS=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -c "^V")
|
||||
if [[ $NUMBEROFCLIENTS == '0' ]]; then
|
||||
log_fatal "You have no existing clients!"
|
||||
fi
|
||||
|
||||
log_header "Revoke Client"
|
||||
log_prompt "Select the existing client certificate you want to revoke"
|
||||
tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
|
||||
until [[ $CLIENTNUMBER -ge 1 && $CLIENTNUMBER -le $NUMBEROFCLIENTS ]]; do
|
||||
if [[ $CLIENTNUMBER == '1' ]]; then
|
||||
read -rp "Select one client [1]: " CLIENTNUMBER
|
||||
else
|
||||
read -rp "Select one client [1-$NUMBEROFCLIENTS]: " CLIENTNUMBER
|
||||
fi
|
||||
done
|
||||
CLIENT=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p)
|
||||
selectClient
|
||||
|
||||
cd /etc/openvpn/easy-rsa/ || return
|
||||
log_info "Revoking certificate for $CLIENT..."
|
||||
run_cmd "Revoking certificate" ./easyrsa --batch revoke "$CLIENT"
|
||||
export EASYRSA_CRL_DAYS=$CRL_VALIDITY_DAYS
|
||||
run_cmd "Regenerating CRL" ./easyrsa gen-crl
|
||||
run_cmd "Removing old CRL" rm -f /etc/openvpn/crl.pem
|
||||
run_cmd "Copying new CRL" cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem
|
||||
run_cmd "Setting CRL permissions" chmod 644 /etc/openvpn/crl.pem
|
||||
regenerateCRL
|
||||
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/ipp.txt
|
||||
@@ -1457,6 +1503,186 @@ function revokeClient() {
|
||||
log_success "Certificate for client $CLIENT revoked."
|
||||
}
|
||||
|
||||
function renewClient() {
|
||||
local homeDir days_valid
|
||||
|
||||
log_header "Renew Client Certificate"
|
||||
log_prompt "Select the existing client certificate you want to renew"
|
||||
selectClient "true"
|
||||
|
||||
# Allow user to specify renewal duration (use DAYS_VALID env var for headless mode)
|
||||
if [[ -z $DAYS_VALID ]] || ! [[ $DAYS_VALID =~ ^[0-9]+$ ]] || [[ $DAYS_VALID -lt 1 ]]; then
|
||||
log_menu ""
|
||||
log_prompt "How many days should the renewed certificate be valid for?"
|
||||
until [[ $days_valid =~ ^[0-9]+$ ]] && [[ $days_valid -ge 1 ]]; do
|
||||
read -rp "Certificate validity (days): " -e -i 3650 days_valid
|
||||
done
|
||||
else
|
||||
days_valid=$DAYS_VALID
|
||||
fi
|
||||
|
||||
cd /etc/openvpn/easy-rsa/ || return
|
||||
log_info "Renewing certificate for $CLIENT..."
|
||||
|
||||
# Backup the old certificate before renewal
|
||||
run_cmd "Backing up old certificate" cp "/etc/openvpn/easy-rsa/pki/issued/$CLIENT.crt" "/etc/openvpn/easy-rsa/pki/issued/$CLIENT.crt.bak"
|
||||
|
||||
# Renew the certificate (keeps the same private key)
|
||||
export EASYRSA_CERT_EXPIRE=$days_valid
|
||||
run_cmd "Renewing certificate" ./easyrsa --batch renew "$CLIENT"
|
||||
|
||||
# Revoke the old certificate
|
||||
run_cmd "Revoking old certificate" ./easyrsa --batch revoke-renewed "$CLIENT"
|
||||
|
||||
# Regenerate the CRL
|
||||
regenerateCRL
|
||||
|
||||
# Regenerate the .ovpn file with the new certificate
|
||||
homeDir=$(getHomeDir "$CLIENT")
|
||||
generateClientConfig "$CLIENT" "$homeDir"
|
||||
|
||||
log_menu ""
|
||||
log_success "Certificate for client $CLIENT renewed and is valid for $days_valid days."
|
||||
log_info "The new configuration file has been written to $homeDir/$CLIENT.ovpn."
|
||||
log_info "Download the new .ovpn file and import it in your OpenVPN client."
|
||||
}
|
||||
|
||||
function renewServer() {
|
||||
local server_name days_valid
|
||||
|
||||
log_header "Renew Server Certificate"
|
||||
|
||||
# Get the server name from the config
|
||||
server_name=$(grep '^cert ' /etc/openvpn/server.conf | cut -d ' ' -f 2 | sed 's/\.crt$//')
|
||||
if [[ -z "$server_name" ]]; then
|
||||
log_fatal "Could not determine server certificate name from /etc/openvpn/server.conf"
|
||||
fi
|
||||
|
||||
log_prompt "This will renew the server certificate: $server_name"
|
||||
log_warn "The OpenVPN service will be restarted after renewal."
|
||||
if [[ -z $CONTINUE ]]; then
|
||||
read -rp "Do you want to continue? [y/n]: " -e -i n CONTINUE
|
||||
fi
|
||||
if [[ $CONTINUE != "y" ]]; then
|
||||
log_info "Renewal aborted."
|
||||
return
|
||||
fi
|
||||
|
||||
# Allow user to specify renewal duration (use DAYS_VALID env var for headless mode)
|
||||
if [[ -z $DAYS_VALID ]] || ! [[ $DAYS_VALID =~ ^[0-9]+$ ]] || [[ $DAYS_VALID -lt 1 ]]; then
|
||||
log_menu ""
|
||||
log_prompt "How many days should the renewed certificate be valid for?"
|
||||
until [[ $days_valid =~ ^[0-9]+$ ]] && [[ $days_valid -ge 1 ]]; do
|
||||
read -rp "Certificate validity (days): " -e -i 3650 days_valid
|
||||
done
|
||||
else
|
||||
days_valid=$DAYS_VALID
|
||||
fi
|
||||
|
||||
cd /etc/openvpn/easy-rsa/ || return
|
||||
log_info "Renewing server certificate..."
|
||||
|
||||
# Backup the old certificate before renewal
|
||||
run_cmd "Backing up old certificate" cp "/etc/openvpn/easy-rsa/pki/issued/$server_name.crt" "/etc/openvpn/easy-rsa/pki/issued/$server_name.crt.bak"
|
||||
|
||||
# Renew the certificate (keeps the same private key)
|
||||
export EASYRSA_CERT_EXPIRE=$days_valid
|
||||
run_cmd "Renewing certificate" ./easyrsa --batch renew "$server_name"
|
||||
|
||||
# Revoke the old certificate
|
||||
run_cmd "Revoking old certificate" ./easyrsa --batch revoke-renewed "$server_name"
|
||||
|
||||
# Regenerate the CRL
|
||||
regenerateCRL
|
||||
|
||||
# Copy the new certificate to /etc/openvpn/
|
||||
run_cmd "Copying new certificate" cp "/etc/openvpn/easy-rsa/pki/issued/$server_name.crt" /etc/openvpn/
|
||||
|
||||
# Restart OpenVPN
|
||||
log_info "Restarting OpenVPN service..."
|
||||
if [[ $OS =~ (fedora|arch|centos|oracle) ]]; then
|
||||
run_cmd "Restarting OpenVPN" systemctl restart openvpn-server@server
|
||||
elif [[ $OS == "ubuntu" ]] && [[ $VERSION_ID == "16.04" ]]; then
|
||||
run_cmd "Restarting OpenVPN" systemctl restart openvpn
|
||||
else
|
||||
run_cmd "Restarting OpenVPN" systemctl restart openvpn@server
|
||||
fi
|
||||
|
||||
log_success "Server certificate renewed successfully and is valid for $days_valid days."
|
||||
}
|
||||
|
||||
function getDaysUntilExpiry() {
|
||||
local cert_file="$1"
|
||||
if [[ -f "$cert_file" ]]; then
|
||||
local expiry_date
|
||||
expiry_date=$(openssl x509 -in "$cert_file" -noout -enddate | cut -d= -f2)
|
||||
local expiry_epoch
|
||||
expiry_epoch=$(date -d "$expiry_date" +%s 2>/dev/null || date -j -f "%b %d %T %Y %Z" "$expiry_date" +%s 2>/dev/null)
|
||||
if [[ -z "$expiry_epoch" ]]; then
|
||||
echo "?"
|
||||
return
|
||||
fi
|
||||
local now_epoch
|
||||
now_epoch=$(date +%s)
|
||||
echo $(((expiry_epoch - now_epoch) / 86400))
|
||||
else
|
||||
echo "?"
|
||||
fi
|
||||
}
|
||||
|
||||
function formatExpiry() {
|
||||
local days="$1"
|
||||
if [[ "$days" == "?" ]]; then
|
||||
echo "(unknown expiry)"
|
||||
elif [[ $days -lt 0 ]]; then
|
||||
echo "(EXPIRED $((-days)) days ago)"
|
||||
elif [[ $days -eq 0 ]]; then
|
||||
echo "(expires today)"
|
||||
elif [[ $days -eq 1 ]]; then
|
||||
echo "(expires in 1 day)"
|
||||
else
|
||||
echo "(expires in $days days)"
|
||||
fi
|
||||
}
|
||||
|
||||
function renewMenu() {
|
||||
local server_name server_cert server_days server_expiry renew_option
|
||||
|
||||
log_header "Certificate Renewal"
|
||||
|
||||
# Get server certificate expiry for menu display
|
||||
server_name=$(grep '^cert ' /etc/openvpn/server.conf | cut -d ' ' -f 2 | sed 's/\.crt$//')
|
||||
if [[ -z "$server_name" ]]; then
|
||||
server_expiry="(unknown expiry)"
|
||||
else
|
||||
server_cert="/etc/openvpn/easy-rsa/pki/issued/$server_name.crt"
|
||||
server_days=$(getDaysUntilExpiry "$server_cert")
|
||||
server_expiry=$(formatExpiry "$server_days")
|
||||
fi
|
||||
|
||||
log_menu ""
|
||||
log_prompt "What do you want to renew?"
|
||||
log_menu " 1) Renew a client certificate"
|
||||
log_menu " 2) Renew the server certificate $server_expiry"
|
||||
log_menu " 3) Back to main menu"
|
||||
until [[ ${RENEW_OPTION:-$renew_option} =~ ^[1-3]$ ]]; do
|
||||
read -rp "Select an option [1-3]: " renew_option
|
||||
done
|
||||
renew_option="${RENEW_OPTION:-$renew_option}"
|
||||
|
||||
case $renew_option in
|
||||
1)
|
||||
renewClient
|
||||
;;
|
||||
2)
|
||||
renewServer
|
||||
;;
|
||||
3)
|
||||
manageMenu
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
function removeUnbound() {
|
||||
# Remove OpenVPN-related config
|
||||
run_cmd "Removing Unbound include" sed -i '/include: \/etc\/unbound\/openvpn.conf/d' /etc/unbound/unbound.conf
|
||||
@@ -1584,6 +1810,8 @@ function removeOpenVPN() {
|
||||
}
|
||||
|
||||
function manageMenu() {
|
||||
local menu_option
|
||||
|
||||
log_header "OpenVPN Management"
|
||||
log_prompt "The git repository is available at: https://github.com/angristan/openvpn-install"
|
||||
log_success "OpenVPN is already installed."
|
||||
@@ -1591,13 +1819,15 @@ function manageMenu() {
|
||||
log_prompt "What do you want to do?"
|
||||
log_menu " 1) Add a new user"
|
||||
log_menu " 2) Revoke existing user"
|
||||
log_menu " 3) Remove OpenVPN"
|
||||
log_menu " 4) Exit"
|
||||
until [[ $MENU_OPTION =~ ^[1-4]$ ]]; do
|
||||
read -rp "Select an option [1-4]: " MENU_OPTION
|
||||
log_menu " 3) Renew certificate"
|
||||
log_menu " 4) Remove OpenVPN"
|
||||
log_menu " 5) Exit"
|
||||
until [[ ${MENU_OPTION:-$menu_option} =~ ^[1-5]$ ]]; do
|
||||
read -rp "Select an option [1-5]: " menu_option
|
||||
done
|
||||
menu_option="${MENU_OPTION:-$menu_option}"
|
||||
|
||||
case $MENU_OPTION in
|
||||
case $menu_option in
|
||||
1)
|
||||
newClient
|
||||
;;
|
||||
@@ -1605,9 +1835,12 @@ function manageMenu() {
|
||||
revokeClient
|
||||
;;
|
||||
3)
|
||||
removeOpenVPN
|
||||
renewMenu
|
||||
;;
|
||||
4)
|
||||
removeOpenVPN
|
||||
;;
|
||||
5)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
@@ -1617,7 +1850,7 @@ function manageMenu() {
|
||||
initialCheck
|
||||
|
||||
# Check if OpenVPN is already installed
|
||||
if [[ -e /etc/openvpn/server.conf && $AUTO_INSTALL != "y" ]]; then
|
||||
if [[ -e /etc/openvpn/server.conf ]]; then
|
||||
manageMenu
|
||||
else
|
||||
installOpenVPN
|
||||
|
||||
@@ -92,6 +92,157 @@ cp /root/testclient.ovpn /shared/client.ovpn
|
||||
sed -i 's/^remote .*/remote openvpn-server 1194/' /shared/client.ovpn
|
||||
echo "Client config copied to /shared/client.ovpn"
|
||||
|
||||
# =====================================================
|
||||
# Test certificate renewal functionality
|
||||
# =====================================================
|
||||
echo ""
|
||||
echo "=== Testing Certificate Renewal ==="
|
||||
|
||||
# Get the original certificate serial number for comparison
|
||||
ORIG_CERT_SERIAL=$(openssl x509 -in /etc/openvpn/easy-rsa/pki/issued/testclient.crt -noout -serial | cut -d= -f2)
|
||||
echo "Original client certificate serial: $ORIG_CERT_SERIAL"
|
||||
|
||||
# Test client certificate renewal using the script
|
||||
echo "Testing client certificate renewal..."
|
||||
RENEW_OUTPUT="/tmp/renew-client-output.log"
|
||||
(MENU_OPTION=3 RENEW_OPTION=1 CLIENTNUMBER=1 DAYS_VALID=3650 bash /tmp/openvpn-install.sh) 2>&1 | tee "$RENEW_OUTPUT" || true
|
||||
|
||||
# Verify renewal succeeded
|
||||
if grep -q "Certificate for client testclient renewed" "$RENEW_OUTPUT"; then
|
||||
echo "PASS: Client renewal completed successfully"
|
||||
else
|
||||
echo "FAIL: Client renewal did not complete"
|
||||
cat "$RENEW_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify new certificate has different serial
|
||||
NEW_CERT_SERIAL=$(openssl x509 -in /etc/openvpn/easy-rsa/pki/issued/testclient.crt -noout -serial | cut -d= -f2)
|
||||
echo "New client certificate serial: $NEW_CERT_SERIAL"
|
||||
if [ "$ORIG_CERT_SERIAL" != "$NEW_CERT_SERIAL" ]; then
|
||||
echo "PASS: Certificate serial changed (renewal created new cert)"
|
||||
else
|
||||
echo "FAIL: Certificate serial unchanged"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify renewed certificate has correct validity period
|
||||
# The default is 3650 days, so the cert should be valid for ~10 years from now
|
||||
CLIENT_CERT_NOT_AFTER=$(openssl x509 -in /etc/openvpn/easy-rsa/pki/issued/testclient.crt -noout -enddate | cut -d= -f2)
|
||||
CLIENT_CERT_NOT_BEFORE=$(openssl x509 -in /etc/openvpn/easy-rsa/pki/issued/testclient.crt -noout -startdate | cut -d= -f2)
|
||||
echo "Client certificate valid from: $CLIENT_CERT_NOT_BEFORE"
|
||||
echo "Client certificate valid until: $CLIENT_CERT_NOT_AFTER"
|
||||
|
||||
# Calculate days until expiry (should be close to 3650)
|
||||
CERT_END_EPOCH=$(date -d "$CLIENT_CERT_NOT_AFTER" +%s 2>/dev/null || date -j -f "%b %d %T %Y %Z" "$CLIENT_CERT_NOT_AFTER" +%s 2>/dev/null)
|
||||
NOW_EPOCH=$(date +%s)
|
||||
DAYS_VALID_ACTUAL=$(((CERT_END_EPOCH - NOW_EPOCH) / 86400))
|
||||
echo "Client certificate validity: $DAYS_VALID_ACTUAL days"
|
||||
|
||||
# Should be between 3640 and 3650 days (allowing some tolerance for timing)
|
||||
if [ "$DAYS_VALID_ACTUAL" -ge 3640 ] && [ "$DAYS_VALID_ACTUAL" -le 3650 ]; then
|
||||
echo "PASS: Client certificate validity is correct (~3650 days)"
|
||||
else
|
||||
echo "FAIL: Client certificate validity is unexpected: $DAYS_VALID_ACTUAL days (expected ~3650)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify new .ovpn file was generated
|
||||
if [ -f /root/testclient.ovpn ]; then
|
||||
echo "PASS: New .ovpn file generated"
|
||||
else
|
||||
echo "FAIL: .ovpn file not found after renewal"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify CRL was updated
|
||||
if [ -f /etc/openvpn/crl.pem ]; then
|
||||
echo "PASS: CRL file exists"
|
||||
else
|
||||
echo "FAIL: CRL file missing after renewal"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update shared client config with renewed certificate
|
||||
cp /root/testclient.ovpn /shared/client.ovpn
|
||||
sed -i 's/^remote .*/remote openvpn-server 1194/' /shared/client.ovpn
|
||||
echo "Updated client config with renewed certificate"
|
||||
|
||||
echo "=== Client Certificate Renewal Tests PASSED ==="
|
||||
|
||||
# =====================================================
|
||||
# Test server certificate renewal
|
||||
# =====================================================
|
||||
echo ""
|
||||
echo "=== Testing Server Certificate Renewal ==="
|
||||
|
||||
# Get server certificate name and original serial
|
||||
SERVER_NAME=$(grep '^cert ' /etc/openvpn/server.conf | cut -d ' ' -f 2 | sed 's/\.crt$//')
|
||||
ORIG_SERVER_SERIAL=$(openssl x509 -in "/etc/openvpn/easy-rsa/pki/issued/$SERVER_NAME.crt" -noout -serial | cut -d= -f2)
|
||||
echo "Server certificate: $SERVER_NAME"
|
||||
echo "Original server certificate serial: $ORIG_SERVER_SERIAL"
|
||||
|
||||
# Test server certificate renewal
|
||||
echo "Testing server certificate renewal..."
|
||||
RENEW_SERVER_OUTPUT="/tmp/renew-server-output.log"
|
||||
(MENU_OPTION=3 RENEW_OPTION=2 CONTINUE=y DAYS_VALID=3650 bash /tmp/openvpn-install.sh) 2>&1 | tee "$RENEW_SERVER_OUTPUT" || true
|
||||
|
||||
# Verify renewal succeeded
|
||||
if grep -q "Server certificate renewed successfully" "$RENEW_SERVER_OUTPUT"; then
|
||||
echo "PASS: Server renewal completed successfully"
|
||||
else
|
||||
echo "FAIL: Server renewal did not complete"
|
||||
cat "$RENEW_SERVER_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify new certificate has different serial
|
||||
NEW_SERVER_SERIAL=$(openssl x509 -in "/etc/openvpn/easy-rsa/pki/issued/$SERVER_NAME.crt" -noout -serial | cut -d= -f2)
|
||||
echo "New server certificate serial: $NEW_SERVER_SERIAL"
|
||||
if [ "$ORIG_SERVER_SERIAL" != "$NEW_SERVER_SERIAL" ]; then
|
||||
echo "PASS: Server certificate serial changed (renewal created new cert)"
|
||||
else
|
||||
echo "FAIL: Server certificate serial unchanged"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify renewed server certificate has correct validity period
|
||||
SERVER_CERT_NOT_AFTER=$(openssl x509 -in "/etc/openvpn/easy-rsa/pki/issued/$SERVER_NAME.crt" -noout -enddate | cut -d= -f2)
|
||||
SERVER_CERT_NOT_BEFORE=$(openssl x509 -in "/etc/openvpn/easy-rsa/pki/issued/$SERVER_NAME.crt" -noout -startdate | cut -d= -f2)
|
||||
echo "Server certificate valid from: $SERVER_CERT_NOT_BEFORE"
|
||||
echo "Server certificate valid until: $SERVER_CERT_NOT_AFTER"
|
||||
|
||||
# Calculate days until expiry (should be close to 3650)
|
||||
SERVER_END_EPOCH=$(date -d "$SERVER_CERT_NOT_AFTER" +%s 2>/dev/null || date -j -f "%b %d %T %Y %Z" "$SERVER_CERT_NOT_AFTER" +%s 2>/dev/null)
|
||||
SERVER_DAYS_VALID=$(((SERVER_END_EPOCH - NOW_EPOCH) / 86400))
|
||||
echo "Server certificate validity: $SERVER_DAYS_VALID days"
|
||||
|
||||
if [ "$SERVER_DAYS_VALID" -ge 3640 ] && [ "$SERVER_DAYS_VALID" -le 3650 ]; then
|
||||
echo "PASS: Server certificate validity is correct (~3650 days)"
|
||||
else
|
||||
echo "FAIL: Server certificate validity is unexpected: $SERVER_DAYS_VALID days (expected ~3650)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify the new certificate was copied to /etc/openvpn/
|
||||
if [ -f "/etc/openvpn/$SERVER_NAME.crt" ]; then
|
||||
DEPLOYED_SERIAL=$(openssl x509 -in "/etc/openvpn/$SERVER_NAME.crt" -noout -serial | cut -d= -f2)
|
||||
if [ "$NEW_SERVER_SERIAL" = "$DEPLOYED_SERIAL" ]; then
|
||||
echo "PASS: New server certificate deployed to /etc/openvpn/"
|
||||
else
|
||||
echo "FAIL: Deployed certificate doesn't match renewed certificate"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "FAIL: Server certificate not found in /etc/openvpn/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Server Certificate Renewal Tests PASSED ==="
|
||||
echo ""
|
||||
echo "=== All Certificate Renewal Tests PASSED ==="
|
||||
echo ""
|
||||
|
||||
# Start OpenVPN server manually (systemd doesn't work in containers)
|
||||
echo "Starting OpenVPN server..."
|
||||
|
||||
|
||||
Reference in New Issue
Block a user