A microcontroller with a UART Wi-Fi module does not need to implement a VPN to reach a service behind one. The module already runs a TCP/IP stack and exposes sockets over serial, and a gateway on the same LAN can carry that traffic through the tunnel. The design works only if you can answer four questions in order, so treat this as a checklist: address, socket, route, boundary. Stop at the first gate that fails, because the later ones cannot compensate for it.

Assign one job per layer

The UART link carries AT commands and payload between the microcontroller and the module. The module joins the Wi-Fi network and owns the IP connection, including its source address. The gateway owns the tunnel, the credentials and the forwarding policy. Keeping those jobs separate is what makes the design debuggable at each stage.

The separation also changes how you write the gateway policy. A source rule should name the module's LAN address, not an imaginary address for the microcontroller behind the serial link. The microcontroller has no IP identity of its own in this design, and pretending it does produces a rule that never matches.

Give the module a stable address through whatever reservation mechanism the network supports, or put the devices on their own segment and let the gateway match by interface. A pool address that changes after a reboot will eventually break a policy that was correct when you wrote it.

Can the gateway name the module's address?

Before any socket opens, confirm the module is associated, has an address, and that the gateway sees it on the expected interface. This is the gate most likely to fail silently, because the module will happily report a connection attempt that never left the LAN.

AT+CWMODE=1
AT+CWJAP="lab-wifi","passphrase"
AT+CIPSTA?
AT+CIPMUX=0

Single-connection mode keeps the command sequence simple, and it is the right starting point for one sensor talking to one service. Multi-connection mode changes the syntax of every later command, so decide which one you are in before you copy an example from a different firmware version.

Open the socket from the module

With an address and a mode settled, the module can open a TCP connection to the private service. The address below is an example from a documentation range; substitute your own and keep the same shape.

AT+CIPSTART="TCP","10.90.0.20",9000
AT+CIPSEND=18
{"t":21.4,"rh":48}

What that AT command does is open a plain TCP socket, and a socket is not a tunnel: nothing in it creates a VPN and nothing in it encrypts the payload. The firmware's TLS mode is a separate feature with its own command and its own certificate handling, and an arbitrary UART module may support neither. Check the TCP/IP AT command reference for your firmware rather than assuming the syntax above applies to it.

The payload length in AT+CIPSEND has to match what you actually send, or the module will wait for bytes that never arrive and the connection will appear to hang. That failure looks like a network problem and is almost always an off-by-one in the length.

Route the connection through the gateway

The gateway needs a route to the private destination, permission to forward from the device network into the tunnel, and a return path that reaches the module. If the remote side does not route back to the device subnet, the design needs an intentional translation rule, and that rule changes the source identity the service sees.

ip route get 10.90.0.20
sudo tcpdump -ni wg0 'host 10.90.0.20 and port 9000'
sudo conntrack -L | grep 9000

Watch for the return path first. A forwarded packet that reaches the service and never comes back produces a timeout at the module with no error on the gateway, which sends people looking at the Wi-Fi link for hours. The conntrack entry tells you whether the gateway saw the reply at all.

Decide where the tunnel actually ends

The tunnel starts at the gateway. It does not encrypt the UART link, and it does not turn the module-to-gateway LAN segment into part of the tunnel. Anything that needs protection on that segment needs its own mechanism, and plain TCP in this example is not TLS.

Decide what happens when the tunnel drops, too. If delivery must be VPN-only, the forwarding policy must not allow the same destination through an alternate path, because a fallback route quietly defeats the requirement. Bound the reconnect behaviour so a disconnected module does not flood the serial link or the remote service with retries.

Record the four answers together: the module's address, the socket target, the gateway route and where encryption begins. The next person to debug this device will need all four, and none of them can be inferred from the firmware alone.

Pennadoù liammet