Skip to content

Commit 32fbce4

Browse files
committed
networking: add support for WireGuard VPN
This VPN allows your OVMS module to "connect" itself to your own private network, make it visible and reachable, whatever the connexion it is using (WiFi, Mobile, ...) (Note: 3G untested at the moment) It should also (unverified) be able to roam from one connexion to the other, or even among different WiFi networks, without any specific setting to do. A documentation has been added. (Note: The schematics, drawn with [draw.io](https://get.diagrams.net/) is embedded in the resulting PNG file, so you can open the PNG file with the editor to edit the diagram. Please keep it that way (by checking the 'Include a copy of my diagram' check box)) Support for wireguard on ESP provided by https://github.com/trombik/esp_wireguard , cf https://github.com/trombik/esp_wireguard/blob/main/LICENSE Cf #752 Signed-off-by: Ludovic LANGE <[email protected]>
1 parent f38a531 commit 32fbce4

File tree

12 files changed

+691
-0
lines changed

12 files changed

+691
-0
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313
[submodule "vehicle/OVMS.V3/components/wolfssl/wolfssl"]
1414
path = vehicle/OVMS.V3/components/wolfssl/wolfssl
1515
url = https://github.com/openvehicles/wolfssl.git
16+
[submodule "vehicle/OVMS.V3/components/esp_wireguard"]
17+
path = vehicle/OVMS.V3/components/esp_wireguard
18+
url = https://github.com/trombik/esp_wireguard.git

docs/source/userguide/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ User Guide
1414
logging
1515
configuration
1616
wifi
17+
vpn
1718
vfs
1819
metrics
1920
ota
99.2 KB
Loading

docs/source/userguide/vpn.rst

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
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``)

vehicle/OVMS.V3/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,7 @@
55

66
PROJECT_NAME := ovms3
77

8+
# Not compatible with ESP-IDF < 4
9+
EXCLUDE_COMPONENTS := esp_wireguard
10+
811
include $(IDF_PATH)/make/project.mk

vehicle/OVMS.V3/changes.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
Open Vehicle Monitor System v3 - Change log
22

33
????-??-?? ??? ??????? OTA release
4+
- Network: Add support for WireGuard VPN (ESP-IDFv4+ only / needs to be enabled in menuconfig - Developer Options)
5+
New commands:
6+
wireguard start -- start the VPN tunnel
7+
wireguard stop -- stop the VPN tunnel (and reset default route)
8+
wireguard restart -- restart the VPN tunnel (and reset default route)
9+
wireguard default -- set default route to use the VPN tunnel
10+
New Configs:
11+
[network.wireguard] local_ip_address -- The IP address of your module IN YOUR PRIVATE NETWORK
12+
[network.wireguard] local_ip_netmask -- The netmask of your module IN YOUR PRIVATE NETWORK
13+
[network.wireguard] local_private_key -- The PRIVATE key of your module for your WireGuard VPN tunnel
14+
[network.wireguard] local_port -- The UDP port from which your module will communicate with the WireGuard server
15+
[network.wireguard] peer_endpoint -- The IP address or hostname of the WireGuard server
16+
[network.wireguard] peer_public_key -- The PUBLIC key of the WireGuard server
17+
[network.wireguard] peer_port -- The UDP port on which the WireGuard server listens
18+
[network.wireguard] preshared_key -- A (recommended) pre-shared symmetric key for additional protection
19+
[network.wireguard] persistent_keepalive -- A keep-alive if your module is behind NAT (recommended for NAT)
420

521
2024-03-23 MB 3.3.004 OTA release
622
- MG EV Added support for MG5 (2020 - 2023) Short Range
Submodule esp_wireguard added at a441e52
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
set(srcs)
2+
set(include_dirs)
3+
4+
if (CONFIG_OVMS_COMP_WIREGUARD)
5+
list(APPEND srcs "src/ovms_wireguard.cpp")
6+
list(APPEND include_dirs "src")
7+
endif ()
8+
9+
# requirements can't depend on config
10+
idf_component_register(SRCS ${srcs}
11+
INCLUDE_DIRS ${include_dirs}
12+
PRIV_REQUIRES "main" "esp_wireguard"
13+
WHOLE_ARCHIVE)

0 commit comments

Comments
 (0)