OpenVPN on Opto 22 groov EPIC & RIO
A number of recent Corso Systems projects have involved using Opto 22 hardware in remote locations not easily accessible by the our team or even our customers’ maintenance staff.
When an Opto 22 device is installed in a manufacturing facility (much like a recent project with an HVAC management system using groov RIOs), we typically access the device through the plant’s existing VPN connection.
But, for remote locations, especially in a “low-IT” environment, we need other options.
Luckily, Opto 22 thought ahead and included OpenVPN functionality in their hardware for these exact scenarios!
What is OpenVPN?
OpenVPN is an open source VPN project. Much like Tailscale or Wireguard, OpenVPN provides client software for devices connecting over the VPN, and a tunneling protocol to connect everything.
Since many existing VPN appliances support OpenVPN, it is easy to integrate it with existing hardware. Additionally, services like CloudConnexa (which we will use in this post’s example) can host the VPN backbone in the cloud to simplify managing devices across many customers and sites.
Setting Up OpenVPN on the groov EPIC and groov RIO
If you are using another VPN appliance with OpenVPN, access your process will be different. We chose CloudConnexa for this post since it offers three free connections—so you can try everything out with minimal overhead.
The first step is setting up an account on CloudConnexa. In addition to CloudConnexa has detailed instructions for the following steps below as well in their documentation for adding a host to access an application server.
Once you’ve accessed the CloudConnexa Portal, navigate to the hosts menu and “Add New Host”.
The host basically acts as the central gateway for all the tunnels for your devices and VPN clients. If you were using another service in place of CloudConnexa (or self-hosting the OpenVPN system) this would be the VPN appliance or computer running OpenVPN you would use to connect everything.
Typically we would set up a host per customer or site, then add more connectors as needed to separate the devices in the OpenVPN system. For the example in this post, we will add a single device under a single host with a single connector.
Corso Systems Can Quickly Set It All Up For You!
Schedule a short intro call with Cody Johnson in sales to get started ASAP
Or contact us with your project details.
The next step is to define the details of your host, starting with a name and description:
You also have the have the (optional) ability to set up a domain name to access the host rather than using the IP address.
Finally, define the name and location of the connector. We typically choose the region/location option that is closest to the device (and most of the users who will need to access it). The region is the datacenter location of the Host, choosing a location closest to the device will improve overall network performance.
After choosing your settings and clicking “Finish”, navigate to the “Connectors” menu below the Hosts menu to see your connection status. Since we haven’t deployed anything yet, the connection status will be displayed as Offline.
Take note of the Tunnel IP address to access the device via the IP address, or if you configured a domain name in a previous step, you can also use the domain to access the device.
Finally, download the ovpn file from the “Deploy” dropdown so you can install this on your groov EPIC or RIO.
With that file handy, access the groov Manage site on your groov device, and navigate to the Network menu. Scroll down to the OpenVPN section to begin configuring your tunnel.
First, Enable OpenVPN:
For our purposes, we will select DHCP for the IPv4 method since we want to use the CloudConnexa IP Address for our device:
Finally, upload the opvn client configuration file you downloaded from CloudConnexa:
After completing the configuration, click the save button. After restarting the groov device, you should be able to connect using an OpenVPN client.
For our example in this post, we downloaded the OpenVPN Connect client software on to a computer, and logged in with our CloudConnexa credentials.
Now we can connect using the CloudConnexa IP from a previous step:
Managing Remote Access to the groov EPIC and groov RIO
Since the CloudConnexa free tier is limited to three free connections, if you are using more than three devices—but only need OpenVPN access to up to three of your devices simultaneously configuration purposes, there’s a relatively work around to enable and disable the connection on demand using Node-RED and MQTT.
To easily move between the OpenVPN network connection and the non-OpenVPN network connection we will use MQTT to communicate with the groov EPIC. Because the groov EPIC will handle its own connection to the MQTT broker, we can communicate with the broker. This is how the groov EPIC will see the changes regardless of which network connection is active or what IP address it has.
To set this up, we will first need to pick a Generic MMP register to use. For our example, we’ll choose the first register. Navigate to the Generic MMP section starting at groov Manage, selecting I/O, I/O Services next, then Generic MMP. For this post we will use F0D81000 for our MQTT tag.
Now, we need to set up MQTT on our groov EPIC. For a detailed tutorial on how to set this up, see our post about HiveMQ, Ignition, and Opto 22.
For everything to work, please sure to enable “Allow Writes”. You can enable this setting in the MQTT Sparkplug B configuration area.
Once connected, you can set up another MQTT Client—in our case Ignition (also explained in the HIVEMQ, Ignition, and Opto 22 post linked above)—and you will see the tag populated in Ignition and ready to write (see image below).
Finally we will need a way to integrate with the groov Manage API to turn OpenVPN on an off. We will do this using Node-RED.
You will need to install the groov IO package to your Node-RED flow, and then you can copy/paste the following code snippit into your flow. (Thanks to friend of Corso Systems, Jason Hamlin for sharing this code snippet!)
[ { "id": "12aad0a5993e7051", "type": "tab", "label": "vpn ctrl", "disabled": false, "info": "", "env": [] }, { "id": "f20c8f5b2a4fd6ad", "type": "groov-io-input", "z": "12aad0a5993e7051", "device": "3e24140890d75c42", "dataType": "mmp-address", "moduleIndex": "", "channelIndex": "", "mmpAddress": "0xF0D81000", "mmpType": "uint32", "mmpLength": "1", "mmpEncoding": "ascii", "sendInitialValue": false, "deadband": "1", "scanTimeSec": "1.0", "name": "vpn ctrl", "x": 70, "y": 60, "wires": [ [ "983dda8513358dbf" ] ] }, { "id": "983dda8513358dbf", "type": "change", "z": "12aad0a5993e7051", "name": "", "rules": [ { "t": "change", "p": "payload", "pt": "msg", "from": "0", "fromt": "num", "to": "false", "tot": "bool" }, { "t": "change", "p": "payload", "pt": "msg", "from": "1", "fromt": "num", "to": "true", "tot": "bool" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 220, "y": 60, "wires": [ [ "41a1665c8c5bfb3e" ] ] }, { "id": "41a1665c8c5bfb3e", "type": "function", "z": "12aad0a5993e7051", "name": "set headers and payload", "func": "msg.headers = {};\nmsg.headers['accept'] = 'application/json';\nmsg.headers['apiKey'] = '<YOUR KEY HEERE>';\n// redefine msg.payload to be the request JSON body\nmsg.payload = { \"value\": msg.payload };\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 430, "y": 60, "wires": [ [ "4f5f9f2f0ba767ee" ] ] }, { "id": "4f5f9f2f0ba767ee", "type": "http request", "z": "12aad0a5993e7051", "name": "HTTP POST", "method": "POST", "ret": "txt", "paytoqs": "ignore", "url": "https://localhost/manage/api/v1/system/network/vpn/openvpn/enable", "tls": "b35e1060c459cdb3", "persist": false, "proxy": "", "authType": "", "senderr": false, "x": 650, "y": 60, "wires": [ [] ] }, { "id": "3e24140890d75c42", "type": "groov-io-device", "address": "localhost", "msgQueueFullBehavior": "DROP_OLD" }, { "id": "b35e1060c459cdb3", "type": "tls-config", "name": "localhost", "cert": "", "key": "", "ca": "", "certname": "", "keyname": "", "caname": "", "servername": "", "verifyservercert": false, "alpnprotocol": "" } ]
You will need to add your API key in a couple places as indicated in the flow. Then you should be able to write a 1 to the MQTT tag to turn on your OpenVPN connection, and a 0 to close it. You can then see this reflected in the CloudConnexa dashboard!
Reducing IT Costs and Overhead
As the number and types of edge devices continue to grow and evolve, SCADA and IIoT can become a huge burden for managing multiple devices across multiple facilities. To help reduce IT overhead, costs involved with configuring and managing firewalls and VPN appliances—while improving overall security—using OpenVPN built into Opto 22 hardware is a very viable solution.
At Corso Systems, we also like to choose open source tools to reduce overall IT costs where possible. Using OpenVPN with CloudConnexa is a great example since it allows us to manage as many Opto 22 devices as we need without incurring additional fees for dozens of concurrent connections.
After configuration, a particular device will still be able to communicate with the MQTT broker, regardless of if it is connected to CloudConnexa or no. You will be able to get in and manage the device as needed without any risk of losing data.