Upgrading the VPN Profile Switcher Script for OpenWRT
In this post, I will walk you through the process of updating and upgrading a shell script I originally wrote a few years ago for changing the VPN profile on OpenWRT routers. This script connects to NordVPN’s recommended servers, and I’ve recently added support for WireGuard (NordLynx) alongside the existing OpenVPN functionality.
The original script was intended for OpenWRT installations on TP-Link Archer C20i and Raspberry Pi 3B+ with 2019 firmware. You can find the VPN Profile Switcher script here.
The script queries NordVPN’s API for the recommended server and then updates the OpenVPN or WireGuard configuration on the router accordingly.
Here, I’ll discuss the upgrade process, including adding support for WireGuard, and share the essential parts of the script without exposing application-specific details.
Understanding the Script’s Purpose
The primary goal of the script is to:
- Fetch the recommended NordVPN server using their API.
- Check if the recommended profile exists on the router.
- If the profile does not exist, download it and configure it with the saved username and password.
- Update the router’s VPN configuration to use the new profile.
- Clean up old profiles, keeping only the currently connected and previously connected profiles.
Research and Preparation
Since NordVPN started offering WireGuard servers (NordLynx) but didn’t provide a tutorial for manual connection on OpenWRT, I had to spend some time researching how to set it up. I found an unofficial documentation for NordVPN’s API long time ago, and used a comment on a GitHub gist as a starting point for extracting the necessary details.
Setting Up WireGuard
First, I set up WireGuard on my development machine (a Mac) and then ported it to OpenWRT. Since I was unfamiliar with WireGuard, this involved a lot of trial and error. I used Claude (Anthropic’s AI) to help convert cURL commands to the lighter wget
command suitable for OpenWRT. Despite Claude’s help, I had to install the wget-ssl
package to avoid errors from NordVPN’s servers.
With the necessary data extracted using jsonfilter
, I created a WireGuard interface using LuCI, OpenWRT’s web interface. This initial success allowed me to formalize my approach in a script.
Script Details
Below is a simplified description of the script’s structure and logic. The actual script is more detailed and includes error handling and logging.
- Check for Required Packages:
function check_packages() { opkg list-installed wget-ssl | grep -q . || opkg list-installed curl | grep -q . if [ $? -ne 0 ]; then logger -s "($0) Error: either wget-ssl or curl are required to run this script. Please install either one of the packages." exit 1 fi }
- Fetch Credentials:
function get_credentials() { if which curl >/dev/null 2>&1; then response_json=$(curl -s -u token:"$access_token" https://api.nordvpn.com/v1/users/services/credentials) else response_json=$(wget -q -O - --auth-no-challenge --user=token --password="$access_token" https://api.nordvpn.com/v1/users/services/credentials) fi if [ $? -ne 0 ]; then logger -s "$(0) Error: Failed to fetch credentials. Please check your access token and internet connection." exit 1 fi }
- Save Credentials:
function save_credentials() { if [ "$vpn_type" == "openvpn" ]; then _username=$(jsonfilter -s "$response_json" -e '@.username') _password=$(jsonfilter -s "$response_json" -e '@.password') echo "$_username" > /etc/openvpn/secret echo "$_password" >> /etc/openvpn/secret else _key=$(jsonfilter -s "$response_json" -e "@.nordlynx_private_key") uci set network.$wg_iface=interface uci set network.$wg_iface.proto='wireguard' uci set network.$wg_iface.private_key=$_key uci set network.$wg_iface.listen_port='51820' uci set network.$wg_iface.addresses='10.5.0.2/32' uci commit network fi }
- Script Execution:
check_packages get_credentials save_credentials
For more details, you can review the full script in the GitHub repository.
In the next post, I’ll cover the final integration of the updated script into the VPN Profile Switcher, ensuring seamless switching between OpenVPN and WireGuard profiles.
This post is a continuation of my previous post on setting up a Raspberry Pi for shell script development. I hope you find it useful!.