VPN: Wireguard - themactep/thingino-firmware GitHub Wiki

Thingino includes support for the WireGuard VPN protocol.

It may be desirable - in the case of remote cameras on untrusted networks, for example - to establish a secure connection to some central collector. While Linux and WireGuard support complicated routing configurations, this interface supports the simple use case of connecting a single tunnel to a peer (server), and routing traffic from the camera, to a set of CIDRs (networks) through that server.

Configuration

The following persistent environment variables are used for this service:

  • wireguard_address - the address and mask length of the wireguard interface, eg. 192.0.2.1/24
  • wireguard_allowed - a list of networks to be routed through the tunnel
  • wireguard_enabled - set to true to enable WireGuard at boot.
  • wireguard_endpoint - the WireGuard server, eg. "vpn.example.com:51280"
  • wireguard_peerpub - the public key of the WireGuard server
  • wireguard_privkey - the private key of this camera
  • wireguard_dns - (optional) a list of DNS resolvers to use when the VPN is up, eg. 192.0.2.254
  • wireguard_keepalive - (optional) the interval at which keep-alive messages are sent. This is likely unnecessary if an RTSP stream is connected to a client (eg. frigate, zoneminder, mpv, ffplay,...)
  • wireguard_mtu - (optional) the maximum transmission unit. It is likely unnecessary to change this from the default value of 1420.
  • wireguard_peerpsk - (optional) WireGuard can use an additional preshared key for additional protection.
  • wireguard_port - (optional) the local listening port for this instance. It is likely unnecessary to set this

These variables should be considered as reserved and not used for any other purpose.

Lists of addresses, networks, or CIDRs may be separated by commas or spaces; 192.0.2.1,192.0.2.2, 192.0.2.1, 192.0.2.2, or 192.0.2.1 192.0.2.2 are all valid.

WebUI

There is a panel in the WebUI for configuring the WireGuard subsystem; it can display the configuration variables as stored in the firmware environment, and allows those variable to be set. The correct values are site-specific and can be obtained from the WireGuard server, the exact details of the process depend on the server (eg. OpenWRT, vendor-skinned OpenWRT, pfSense, OpnSense).

The panel can also display the state of the tunnel if the interface is up, and allows the VPN to be started or stopped on demand.

wg_gui2

Once WireGuard has been configured, reboot the camera to apply the changes or use the red button to start or stop the VPN immediately. Use caution when configuring remote devices as VPN changes may lead to loss of connectivity.

CLI

If desired, the environment variables can be declared in /etc/web.conf.

wireguard_enabled false
wireguard_keepalive 25
wireguard_endpoint vpn.example.com:51280
wireguard_mtu 1420
wireguard_dns 192.0.2.253
wireguard_address 192.0.2.1/32
wireguard_allowed 192.0.2.0/24, 195.51.100.0/24
wireguard_peerpub QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ=
wireguard_privkey XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=
wireguard_peerpsk ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ=

The VPN can then be immediately started with /etc/init.d/S42wireguard force. If that works, the wireguard_enabled flag can be set to true to enable autostart. If you're confident in your VPN configuration create the environment with wireguard_enabled true and reboot - may the odds be ever in your favor.

A Magic Key

Just in case the odds aren't in your favor, here's a magic key which will let you get back into your camera if a mistake in your WireGuard configuration has locked you out. This uses the "runonce.sh" functionality built-into the Thingino firmware to disable WireGuard and reboot the camera after a specified time period (ten minutes is the default).

During a normal boot sequence, Thingino will check for the existence of a "runonce.sh" file on the SD card (the SD card doesn't need a bootstrap or any special partitioning or offsets, but it does need to be a VFAT formatted card) and, if that file exists, it will execute it using /bin/sh. After running the runonce.sh file, it will create a separate, new file on the SD card named "runonce.done", which inhibits the execution of runonce.sh on subsequent reboots.

You should create runonce.sh with this content:-

TGC=/etc/thingino.config;	## Main Thingino configuration.
TEMPO=/tmp/__thng-cfg.tmp;	## Temporary file.
export TGC; export TEMPO;

sleep 3;			## Give the system time to catch up.

( sleep 600 && cat ${TGC}  | \
  sed -e '/^wireguard_enabled="true"/s//wireguard_enabled="false"/' > ${TEMPO} && \
  cat ${TEMPO} > ${TGC} && sync && sleep 1 && reboot ) &

The function of this script is to wait for ten minutes without doing anything and then to simply change the "wireguard_enabled" variable from "true" to "false" and reboot the camera. This is a fairly dumb magic key, in that it doesn't know whether you're already inside or not (whether the WireGuard configuration is correct or not), so it will reboot the camera regardless (unless you do actually have access and can kill the subshell before it times-out).

Once you're happy that your WireGuard configuration on the camera is correct, you can delete the "runonce.sh" file (or just remove the SD card).

If your configuration still isn't correct, you can try another iteration and remove the "runonce.done" file from the SD card before re-enabling WireGuard and rebooting the system (or you can simply execute the script from the command-line using /bin/sh /mnt/mmcblk0p1/runonce.sh).

Additional Tips & Tricks

  • Use the command wg show to see the public-key generated by Thingino WireGuard for your camera (WG must have started successfully at least once before this is populated, but it does not need to have made an actual connection yet).
  • Use the wildcard setting of 0.0.0.0/0 for your allowed_ips (or Allowed CIDRs) until you have a good, working, debugged config.
  • Use a comma as a separator between multiple entries in your permanent Allowed CIDRs list (spaces currently don't work).