Creating a secure BMS system for your customers: Part 3, OpenVPN server

One important note here; we chose to put the OpenVPN server on each customer server which means we can’t allow datacenter LAN access for things coming in over the VPN. We chose to view this as a security measure as the only thing remote sites can possibly access is the VPN virtual IP address on that server.

Start by installing OpenVPN community edition. We did use windows here but if your platform of choice is a linux solution this config will largely be the same with some minor differences in the location paths. In windows the server install contains everything you need, but you need to check include easy RSA and uncheck GUI option.

Now we can start working with the OpenVPN server config file to tell the server how to operate. I’m going to break it down into chunks, explain what’s going on and then put it all together at the end. I have quite a few comments in my config file marked with # and ; and I would encourage this as reminders.

### Connection info
proto tcp-server
port 1194
mode server
keepalive 10 120

Above we are going to use TCP for the VPN tunnel. This is against general OpenVPN advice, but if you read the reasons why you will find most web traffic is already TCP so layering TCP on top of TCP is problematic for good reason. The thing here is BACnet/IP and Modbus/IP are UDP protocols, and if you layer UDP on UDP over the internet things tend to go missing. I’ve found BACnet/IP and Modbus/IP work much more reliably when inside a TCP tunnel over the internet.

The first bit is talking about the port OpenVPN is listening to on that server. I chose to leave it default here and in the router for the hosting system it is going to pass some high number port of your choice internet facing to this port internally. I’ll mention this again on the client portion.

### encryption info
tls-server
remote-cert-eku "TLS Web Client Authentication"
cipher AES-256-CBC
ca "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\ca.crt"
cert "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\server.crt"
key "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\server.key"
dh "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\dh4096.pem"

This is the default locations for the keys and certificates we made earlier. I’m also choosing a pretty strong cipher suite. In testing with the amount of traffic we see with BACnet/IP barely sees any CPU usage with this stronger cipher suite so why not?

### authentication
tls-auth "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\ta.key" 0 # This file is secret

More security and protection against various attacks. Some background discussion on hardening OpenVPN here.

### Compression "compress" new standard,
# lz4 best performance, lzo backwards compatibility
# Seems ER does not support new command or lz4
;compress lz4
comp-lzo

A bit of backwards compatibility here for the router I chose, seems the Ubuquiti EdgeRouter is a little behind on what compression methods it can use. I left the comments in as a reminder to try it again on future versions, the EdgeRouter is under constant development.

### Network
# FYI; VPN DHCP server is on 10.8.0.254
# route gateway is 10.8.0.2
# server is on 10.8.0.1
# always avoid these addresses when addressing clients via CCD
dev tun
topology "subnet"
push "topology subnet"
server 10.8.0.0 255.255.255.0
# Push routes to connecting clients, they need to know how to route to other LANs
push "route 10.105.101.0 255.255.255.0"
push "route 10.105.102.0 255.255.255.0"
push "route 10.105.103.0 255.255.255.0"
push "route 10.105.104.0 255.255.255.0"
push "route 10.105.105.0 255.255.255.0"
push "route 10.105.106.0 255.255.255.0"
push "route 10.105.107.0 255.255.255.0"
# Allow LAN routing between clients
client-to-client
# Allow the server to route traffic to client LANs
route 10.105.101.0 255.255.255.0
route 10.105.102.0 255.255.255.0
route 10.105.103.0 255.255.255.0
route 10.105.104.0 255.255.255.0
route 10.105.105.0 255.255.255.0
route 10.105.106.0 255.255.255.0
route 10.105.107.0 255.255.255.0
# ovpn server pushes config info to clients from files in ccd dir.
# Matches are based on CN in connecting key, so CN in key must match file name exactly.
# Static VPN addressing and Client LAN routing is controlled in these files.
# client configuration directory (home is config dir, so rel path ok here)
client-config-dir ccd

Here I am deviating from the HOW TO article to use topology subnet. This way the virtual VPN network is much easier to understand and can easily handle more clients.

This together with the ccd files explicitly allows site to site routing and defines that routing. In this case it is set up for for six remote sites but you can do more or less. This is a really good article on how all this works, just remember we are leaving out the server LAN subnet.

The last line defines your client configuration directory. This is important because these files control the VPN IP addresses of connecting clients and also define some routing for site to site communications. I’ll talk more about these CCD files later.

### Logging
# OpenVPN log goes to C:\Program Files\OpenVPN\log\* whatever this ovpn file is named
# 0 is silent, except for fatal errors
# 3 default?
# 4 is reasonable for general usage
# 5 and 6 can help to debug connection problems
# 9 is extremely verbose
verb 3
# read this to see what clients are connected
status "C:\\Program Files\\OpenVPN\\log\\openvpn-status.log"

This puts both log files in the same place. The status log in particular is good to read to see what VPN clients are connected, it gets updated periodically. The server log at 3 isn’t too talkative and easy to read to see what’s going on.

That’s it, now the entire config file in one go, you should be able to copy and paste this below. After you have created keys in the next session you should be able to start the OpenVPN service.

### This file compatible with topology SUBNET
### Remember to edit LAN addressing for server routing below, and client addressing in CCD files
### Server VPN IP is 10.8.0.1, bind BMS to that IP.
### Set OpenVPN service to automatic startup (no delay) so that the IP will be there when BMS (with delayed start) asks.
### Connection info
proto tcp-server
port 1194
mode server
keepalive 10 120
### encryption info
tls-server
remote-cert-eku "TLS Web Client Authentication"
cipher AES-256-CBC
ca "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\ca.crt"
cert "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\server.crt"
key "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\server.key"
dh "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\dh4096.pem"
### authentication
tls-auth "C:\\Program Files\\OpenVPN\\easy-rsa\\keys\\ta.key" 0 # This file is secret
### Compression "compress" new standard,
# lz4 best performance, lzo backwards compatibility
# Seems ER does not support new command or lz4
;compress lz4
comp-lzo
### Network
# FYI; VPN DHCP server is on 10.8.0.254
# route gateway is 10.8.0.2
# server is on 10.8.0.1
# always avoid these addresses when addressing clients via CCD
dev tun
topology "subnet"
push "topology subnet"
server 10.8.0.0 255.255.255.0
# Push routes to connecting clients, they need to know how to route to other LANs
push "route 10.105.101.0 255.255.255.0"
push "route 10.105.102.0 255.255.255.0"
push "route 10.105.103.0 255.255.255.0"
push "route 10.105.104.0 255.255.255.0"
push "route 10.105.105.0 255.255.255.0"
push "route 10.105.106.0 255.255.255.0"
push "route 10.105.107.0 255.255.255.0"
# Allow LAN routing between clients
client-to-client
# Allow the server to route traffic to client LANs
route 10.105.101.0 255.255.255.0
route 10.105.102.0 255.255.255.0
route 10.105.103.0 255.255.255.0
route 10.105.104.0 255.255.255.0
route 10.105.105.0 255.255.255.0
route 10.105.106.0 255.255.255.0
route 10.105.107.0 255.255.255.0
# ovpn server pushes config info to clients from files in ccd dir.
# Matches are based on CN in connecting key, so CN in key must match file name exactly.
# Static VPN addressing and Client LAN routing is controlled in these files.
# client configuration directory (home is config dir, so rel path ok here)
client-config-dir ccd
### Logging
# OpenVPN log goes to C:\Program Files\OpenVPN\log\* whatever this ovpn file is named
# 0 is silent, except for fatal errors
# 3 default?
# 4 is reasonable for general usage
# 5 and 6 can help to debug connection problems
# 9 is extremely verbose
verb 3
# read this to see what clients are connected
status "C:\\Program Files\\OpenVPN\\log\\openvpn-status.log"