|
| 1 | +.. highlight:: none |
| 2 | + |
| 3 | +============================= |
| 4 | +Virtual Private Network (VPN) |
| 5 | +============================= |
| 6 | + |
| 7 | +.. warning:: **WireGuard VPN support is only available on (upcoming) ESP-IDF v5+ builds** - unfortunately there is no |
| 8 | + easy way to make it work with (current) ESP-IDF v3.3.4 builds. |
| 9 | + |
| 10 | +The OVMS module can be (optionally) configured with a `WireGuard <https://www.wireguard.com/>`_ VPN tunnel. |
| 11 | +This allows your module to connect (attach) to a private network as if it were part of this network, like |
| 12 | +a local node. |
| 13 | +In addition WireGuard VPN natively supports roaming, thus if your module changes network, or source IP address |
| 14 | +for whatever reason, it will still be connected and visible from your private network. |
| 15 | + |
| 16 | +Possible use cases : |
| 17 | + - securing the (incoming) connection to your module, so that it's not publicly visible (and scannable) on a public IP address, thus reducing the attack surface |
| 18 | + - have an always-on SSH connexion to your module - even if it's roaming |
| 19 | + - being able to (securely) send files and data, back and forth, from / to your module to / from your private network |
| 20 | + |
| 21 | +---------------------- |
| 22 | +Principle of operation |
| 23 | +---------------------- |
| 24 | + |
| 25 | +At the moment, only one connexion is supported. When configured the VPN tunnel will connect as soon as the |
| 26 | +network is ready, and your module will be able to communicate with other nodes of your private network. |
| 27 | + |
| 28 | + |
| 29 | +.. note:: **WireGuard VPN needs the time to be monotonic**, i.e. always goes forward. While not mandatory, it's best to have |
| 30 | + a time/date properly setup (NTP, GPS, ...) |
| 31 | + |
| 32 | +.. note:: You will need a properly configured (and tested) WireGuard peer that we will refer to as **the server** (WireGuard VPN has no |
| 33 | + such distinction between clients and servers, but in our case it's easier to grasp), while we will consider that our |
| 34 | + module is **the client**. |
| 35 | + |
| 36 | +The **server** needs to be properly configured to accept incoming WireGuard traffic (i.e. UDP packets) on a public interface - we will |
| 37 | +call the address of this public interface the **Peer Endpoint**. |
| 38 | + |
| 39 | +------------- |
| 40 | +Configuration |
| 41 | +------------- |
| 42 | + |
| 43 | +New configuration items are introduced to configure this VPN tunnel, organised using the :doc:`configuration system<configuration>`:: |
| 44 | + |
| 45 | + <parameter> <instance> = <value> |
| 46 | + |
| 47 | +Where **parameter** is always ``network.wireguard``, and **instance** is as follow: |
| 48 | + |
| 49 | + |
| 50 | +========================= ===== |
| 51 | +Instance (in OVMS) Comment |
| 52 | +========================= ===== |
| 53 | +``local_ip_address`` The IP address of your module IN YOUR PRIVATE NETWORK |
| 54 | +``local_ip_netmask`` The netmask of your module IN YOUR PRIVATE NETWORK |
| 55 | +``local_private_key`` The PRIVATE key of your module for your WireGuard VPN tunnel |
| 56 | +``local_port`` The UDP port from which your module will communicate with the WireGuard server |
| 57 | +``peer_endpoint`` The IP address or hostname of the WireGuard server |
| 58 | +``peer_public_key`` The PUBLIC key of the WireGuard server |
| 59 | +``peer_port`` The UDP port on which the WireGuard server listens |
| 60 | +``preshared_key`` A (recommended) pre-shared symmetric key for additional protection |
| 61 | +``persistent_keepalive`` A keep-alive if your module is behind NAT (recommended for NAT) |
| 62 | +========================= ===== |
| 63 | + |
| 64 | +Example:: |
| 65 | + |
| 66 | + OVMS# config set network.wireguard local_ip_address 192.168.4.58 |
| 67 | + OVMS# config set network.wireguard local_ip_netmask 255.255.255.0 |
| 68 | + OVMS# config set network.wireguard local_private_key "IsvT72MAXzA8EtV0FSD1QT59B4x0oe6Uea5rd/dDzhE=" |
| 69 | + OVMS# config set network.wireguard local_port 11010 |
| 70 | + OVMS# config set network.wireguard peer_endpoint demo.wireguard.com |
| 71 | + OVMS# config set network.wireguard peer_public_key "FjrsQ/HD1Q8fUlFILIasDlOuajMeZov4NGqMJpkswiw=" |
| 72 | + OVMS# config set network.wireguard peer_port 12912 |
| 73 | + OVMS# config set network.wireguard preshared_key "0/2H97Sd5EJ9LAAAYUglVjPYv7ihNIm/ziuv6BtSI50=" |
| 74 | + OVMS# config set network.wireguard persistent_keepalive 25 |
| 75 | + |
| 76 | +.. note:: The preceding values are for documentation only, they won't work as is. If you need to test the tunnel |
| 77 | + on a demo server, have a look at `WireGuard Demo <http://demo.wireguard.com/>`_, download the shell script |
| 78 | + and adapt it to your needs. |
| 79 | + |
| 80 | +``local_ip_address`` and ``local_ip_netmask`` are used to decide: |
| 81 | + - what will be the IP address of the module in your private network (``local_ip_address``). A new (local) network interface will be configured with this IP address. |
| 82 | + - which routing will be allowed through the VPN tunnel (using ``local_ip_address`` + ``local_ip_netmask``) |
| 83 | + |
| 84 | +In general, ``local_ip_netmask`` will be the netmask of your private network to enable packets from/to your other network nodes to cross the tunnel. |
| 85 | +(In opposite, when setting the reciprocate configuration, you would define only the) |
| 86 | + |
| 87 | +Correspondance with WireGuard's `Configuration file format <https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8>`_ |
| 88 | + |
| 89 | +========================= =========================================== ============================================================ |
| 90 | +OVMS Wireguard Client Wireguard Server |
| 91 | +========================= =========================================== ============================================================ |
| 92 | +``local_ip_address`` Peer / AllowedIPs (one address only) (address of the server in the private network) |
| 93 | +``local_ip_netmask`` Peer / AllowedIPs (one address only) (netmask of the private network) |
| 94 | +``local_private_key`` Interface / PrivateKey Peer / PublicKey |
| 95 | +``local_port`` Interface / ListenPort N/A |
| 96 | +``peer_endpoint`` Peer / Endpoint (before colon) (public IP address of the server) |
| 97 | +``peer_public_key`` Peer / PublicKey Interface / PrivateKey |
| 98 | +``peer_port`` Peer / Endpoint (port number, after colon) Interface / ListenPort |
| 99 | +``preshared_key`` Peer / PresharedKey Peer / PresharedKey |
| 100 | +``persistent_keepalive`` Peer / PersistentKeepalive Peer / PersistentKeepalive |
| 101 | +========================= =========================================== ============================================================ |
| 102 | + |
| 103 | +^^^^^^^^^^^ |
| 104 | +Quick start |
| 105 | +^^^^^^^^^^^ |
| 106 | +.. note:: for configuring the different keys (private keys, publics keys, shared key) you will need to access a computer with the proper WireGuard |
| 107 | + VPN tools installed. In this documentation we will assume that the command line tool ``wg`` is installed on this computer. |
| 108 | + |
| 109 | +The example configuration is the following: |
| 110 | + |
| 111 | +.. image:: vpn-ovms-wireguard.png |
| 112 | + |
| 113 | +* The server listens on ``wg.example.net``, on UDP port ``51820`` |
| 114 | +* The private network is ``172.16.0.0/12`` (corresponding netmask ``255.240.0.0``) |
| 115 | +* In this private network: |
| 116 | + |
| 117 | + * the OVMS module has a reserved IP of ``172.16.10.20`` |
| 118 | + * the server has a reserved IP of ``172.16.1.10`` (for information purposes, not used in the configuration) |
| 119 | +* The OVMS module uses UDP port ``11010`` for its WireGuard VPN purposes. |
| 120 | + |
| 121 | +Steps:: |
| 122 | + |
| 123 | + # Generate the server private key |
| 124 | + $ wg genkey |
| 125 | + SGfeKo9cmhIJ5tpDOjOimnEKi3M+3mJ21+jJ7otllHI= |
| 126 | + |
| 127 | + # Generate the corresponding server public key |
| 128 | + $ echo 'SGfeKo9cmhIJ5tpDOjOimnEKi3M+3mJ21+jJ7otllHI=' | wg pubkey |
| 129 | + r5xRjMaiu1apmP6YzRviL8djtBfjcWGnOd2mmHNOqm4= |
| 130 | + |
| 131 | + # Generate the ovms module private key |
| 132 | + $ wg genkey |
| 133 | + kI2/adVWRseT2ZtYxn/5lTzQsPKK8F7YHWcIo3iwgHk= |
| 134 | + |
| 135 | + # Generate the corresponding ovms module public key |
| 136 | + $ echo 'kI2/adVWRseT2ZtYxn/5lTzQsPKK8F7YHWcIo3iwgHk=' | wg pubkey |
| 137 | + hi0SNx8JJVLWIOuIfeQW5Ea5SK/41g4DeXJ2eJR9R3Y= |
| 138 | + |
| 139 | + # Generate the pre-shared key |
| 140 | + $ wg genpsk |
| 141 | + JUvxtI5sFm9n0zY6N4Z8rz/nSnww2DaeFKsOPGnC1WA= |
| 142 | + |
| 143 | + |
| 144 | +Server configuration:: |
| 145 | + |
| 146 | + [Interface] |
| 147 | + PrivateKey = SGfeKo9cmhIJ5tpDOjOimnEKi3M+3mJ21+jJ7otllHI= |
| 148 | + ListenPort = 51820 |
| 149 | + |
| 150 | + [Peer] |
| 151 | + PublicKey = hi0SNx8JJVLWIOuIfeQW5Ea5SK/41g4DeXJ2eJR9R3Y= |
| 152 | + PresharedKey = JUvxtI5sFm9n0zY6N4Z8rz/nSnww2DaeFKsOPGnC1WA= |
| 153 | + AllowedIPs = 172.16.10.20/32 |
| 154 | + PersistentKeepalive = 25 |
| 155 | + |
| 156 | +OVMS configuration:: |
| 157 | + |
| 158 | + OVMS# config set network.wireguard local_ip_address 172.16.10.20 |
| 159 | + OVMS# config set network.wireguard local_ip_netmask 255.240.0.0 |
| 160 | + OVMS# config set network.wireguard local_port 11010 |
| 161 | + OVMS# config set network.wireguard local_private_key "kI2/adVWRseT2ZtYxn/5lTzQsPKK8F7YHWcIo3iwgHk=" |
| 162 | + OVMS# config set network.wireguard peer_endpoint wg.example.net |
| 163 | + OVMS# config set network.wireguard peer_port 51820 |
| 164 | + OVMS# config set network.wireguard peer_public_key "r5xRjMaiu1apmP6YzRviL8djtBfjcWGnOd2mmHNOqm4=" |
| 165 | + OVMS# config set network.wireguard preshared_key "JUvxtI5sFm9n0zY6N4Z8rz/nSnww2DaeFKsOPGnC1WA=" |
| 166 | + OVMS# config set network.wireguard persistent_keepalive 25 |
| 167 | + |
| 168 | +.. note:: The preceding values are for documentation only, they won't work as is. |
| 169 | + |
| 170 | +^^^^^^^^^^^^^^^ |
| 171 | +Troubleshooting |
| 172 | +^^^^^^^^^^^^^^^ |
| 173 | + |
| 174 | +If the module doesn't find your WireGuard server, you can use the following tools for diagnostic:: |
| 175 | + |
| 176 | + OVMS# wireguard status |
| 177 | + |
| 178 | + OVMS# network status |
| 179 | + |
| 180 | + OVMS# wireguard stop |
| 181 | + OVMS# wireguard start |
| 182 | + OVMS# wireguard restart |
| 183 | + |
| 184 | + OVMS# network ping X.Y.Z.T |
| 185 | + |
| 186 | +Set the logs to debug, and every 10s the wireguard subsystem will print if the peer is 'up' or 'down'. |
| 187 | + |
| 188 | +When neither the WireGuard VPN nor the WiFi client are active, the output of ``network status`` looks like this:: |
| 189 | + |
| 190 | + OVMS# network status |
| 191 | + Interface#2: ap2 (ifup=1 linkup=1) |
| 192 | + IPv4: 192.168.4.1/255.255.255.0 gateway 192.168.4.1 |
| 193 | + |
| 194 | + Interface#1: st1 (ifup=0 linkup=0) |
| 195 | + IPv4: 0.0.0.0/0.0.0.0 gateway 0.0.0.0 |
| 196 | + |
| 197 | + DNS: None |
| 198 | + |
| 199 | + Default Interface: ap2 (192.168.4.1/255.255.255.0 gateway 192.168.4.1) |
| 200 | + |
| 201 | +As soon as the WiFi client is connected, the WireGuard VPN interface appears, but not connected (``linkup=0``):: |
| 202 | + |
| 203 | + OVMS# network status |
| 204 | + Interface#3: wg3 (ifup=1 linkup=0) |
| 205 | + IPv4: 172.16.10.20/255.255.255.0 gateway 0.0.0.0 |
| 206 | + |
| 207 | + Interface#2: ap2 (ifup=1 linkup=1) |
| 208 | + IPv4: 192.168.4.1/255.255.255.0 gateway 192.168.4.1 |
| 209 | + |
| 210 | + Interface#1: st1 (ifup=1 linkup=1) |
| 211 | + IPv4: 192.168.1.12/255.255.255.0 gateway 192.168.1.1 |
| 212 | + |
| 213 | + DNS: 192.168.1.1 |
| 214 | + |
| 215 | + Default Interface: st1 (192.168.1.12/255.255.255.0 gateway 192.168.1.1) |
| 216 | + |
| 217 | +The status is:: |
| 218 | + |
| 219 | + OVMS# wireguard status |
| 220 | + Connection status: started |
| 221 | + Peer status: down |
| 222 | + |
| 223 | +After a little while, the WireGuard VPN interface connects (``linkup=1``) and the status is ``up``:: |
| 224 | + |
| 225 | + OVMS# network status |
| 226 | + Interface#3: wg3 (ifup=1 linkup=1) |
| 227 | + IPv4: 172.16.10.20/255.255.255.0 gateway 0.0.0.0 |
| 228 | + |
| 229 | + Interface#2: ap2 (ifup=1 linkup=1) |
| 230 | + IPv4: 192.168.4.1/255.255.255.0 gateway 192.168.4.1 |
| 231 | + |
| 232 | + Interface#1: st1 (ifup=1 linkup=1) |
| 233 | + IPv4: 192.168.1.12/255.255.255.0 gateway 192.168.1.1 |
| 234 | + |
| 235 | + DNS: 192.168.1.1 |
| 236 | + |
| 237 | + Default Interface: st1 (192.168.1.12/255.255.255.0 gateway 192.168.1.1) |
| 238 | + |
| 239 | + OVMS# wireguard status |
| 240 | + Connection status: started |
| 241 | + Peer status: up |
| 242 | + |
| 243 | +And you can ping another host on the private network:: |
| 244 | + |
| 245 | + OVMS# network ping 172.16.1.2 |
| 246 | + PING 172.16.1.2 (172.16.1.2): 64 data bytes |
| 247 | + 64 bytes from 172.16.1.2: icmp_seq=0 ttl=64 time=2 ms |
| 248 | + 64 bytes from 172.16.1.2: icmp_seq=1 ttl=64 time=2 ms |
| 249 | + 64 bytes from 172.16.1.2: icmp_seq=2 ttl=64 time=5 ms |
| 250 | + 64 bytes from 172.16.1.2: icmp_seq=3 ttl=64 time=3 ms |
| 251 | + |
| 252 | + --- 172.16.1.2 ping statistics --- |
| 253 | + 4 packets transmitted, 4 received, 0% packet loss, time 12ms |
| 254 | + round-trip avg = 3.00 ms |
| 255 | + |
| 256 | +----------------------- |
| 257 | +Firewall considerations |
| 258 | +----------------------- |
| 259 | + |
| 260 | +WireGuard is an UDP-based protocol. |
| 261 | +There is one UDP port to consider for each node (one for the server, one for the module). |
| 262 | +By convention, the UDP port is often **51820** but can be changed with no issue. |
| 263 | + |
| 264 | +For the **server**, the firewall needs to accept incoming UDP packets on a public interface from the possible source addresses of your module. (In case of a WiFi network you manage, this can be a certain range. However if your module is either roaming or using a mobile network with unknown source |
| 265 | +addresses you may have to open this UDP port to the whole internet). |
| 266 | + |
| 267 | +------------------------ |
| 268 | +Bandwidth considerations |
| 269 | +------------------------ |
| 270 | +If you use the ``persistent_keepalive`` setting, it will send an UDP packet each ``persistent_keepalive`` seconds. |
| 271 | +The recommended value for systems behind NATs is 25s, so it can make your module send a lot of (small) packets many time per hour. |
| 272 | + |
| 273 | +If this is a concern you may want to disable the tunnel when you don't need it (``wireguard stop``) and only enable it when needed (``wireguard start``) |
0 commit comments