Add station-only WiFi UDP bridge with eight authenticated peers
This commit is contained in:
1 parent
7bc3aeb234
commit
5e25faa3d0
45 files changed
+2699
-35
No files matched your search
+67
-1
@@ -5570,7 +5570,73 @@ still overrides the first-boot default after an update.
|
||||
|
||||
For a two-repeater setup and diagnostic flow, see the
|
||||
[ESP-NOW bridge setup guide](espnow_bridge_setup.md) or
|
||||
[RS-232/UART bridge guide](rs232_bridge_setup.md).
|
||||
[RS-232/UART bridge guide](rs232_bridge_setup.md). For an existing WiFi network,
|
||||
see the [eight-peer UDP bridge guide](udp_bridge_setup.md).
|
||||
|
||||
#### WiFi UDP bridge
|
||||
|
||||
Available on supported ESP32 repeater images with `WITH_UDP_BRIDGE`. UDP starts
|
||||
off on new/upgraded installs. It requires an existing station WiFi connection,
|
||||
and pauses during AP/AP+STA operation, disconnection, browser OTA and ownership
|
||||
transitions. It does not start a network or require an MQTT broker.
|
||||
|
||||
```text
|
||||
get udp.enabled
|
||||
set udp.enabled on
|
||||
set udp.enabled off
|
||||
get udp.port
|
||||
set udp.port 4404
|
||||
get udp.peer.1
|
||||
set udp.peer.1 192.168.1.51:4404
|
||||
set udp.peer.1 off
|
||||
get udp.status
|
||||
get udp.stats
|
||||
get udp.stats rx
|
||||
get udp.stats tx
|
||||
get udp.stats drops
|
||||
get udp.stats test
|
||||
```
|
||||
|
||||
Peer slots are `udp.peer.1` through `udp.peer.8`. Each destination is one
|
||||
numeric unicast IPv4 address plus a port `1..65535`. The listening port defaults
|
||||
to `4404`. Multicast, loopback, unspecified/broadcast and duplicate endpoints
|
||||
are rejected. Both boards must list each other's listening address/port.
|
||||
Reserve DHCP addresses so the stored destinations remain valid.
|
||||
|
||||
The transport reuses `bridge.secret` for authenticated sessions and packet
|
||||
integrity; no additional password is introduced. UDP payloads are not
|
||||
encrypted. Counter/status output does not reveal the secret. Config writes
|
||||
use the existing authenticated CLI policy and a separate checked preferences
|
||||
file; a successful save reports intent rather than reachability.
|
||||
|
||||
Local-only diagnostic actions:
|
||||
|
||||
```text
|
||||
udp test 1
|
||||
udp test 1 A1B2C3D4
|
||||
udp resetstats
|
||||
```
|
||||
|
||||
The peer number is `1..8`; the optional ID is exactly eight hexadecimal digits
|
||||
without `0x`. A queued/sent probe is not a delivery acknowledgement. On the
|
||||
destination, check `get udp.stats test` for an increased `rx` and matching
|
||||
`rxid`, then reverse the test. An authenticated peer session must be ready.
|
||||
The status `ready` count records established sessions, not current liveness;
|
||||
use a fresh received probe to confirm reachability. Incoming UDP enters the
|
||||
local LoRa mesh and is not relayed to other UDP peers.
|
||||
Probes do not echo, retry, allocate mesh packets or transmit on LoRa. Resetting
|
||||
statistics does not write preferences or restart the bridge.
|
||||
|
||||
Both `set usb.logging on` and `set usb.debug on` enable bounded runtime USB
|
||||
summaries without requiring a special debug build. Restore both previous
|
||||
settings after capture. CLI pages/probes work with logging disabled.
|
||||
|
||||
WiFi client isolation and firewall rules must allow peer-to-peer UDP; the
|
||||
firmware cannot bypass an isolating guest network. Isolation is an optional
|
||||
network policy, not an intrinsic WiFi restriction. See the
|
||||
[setup and troubleshooting guide](udp_bridge_setup.md).
|
||||
|
||||
---
|
||||
|
||||
#### View the compiled bridge type
|
||||
**Usage:** `get bridge.type`
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
<!-- meshcore-hosted-doc-link:start -->
|
||||
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/udp_bridge_setup/">View this page on MeshCore Docs</a>.</p>
|
||||
<!-- meshcore-hosted-doc-link:end -->
|
||||
|
||||
# WiFi UDP bridge: up to eight IP peers
|
||||
|
||||
Supported ESP32 repeater images can bridge MeshCore packets directly over an
|
||||
existing WiFi network, without an MQTT broker. Each board has one UDP listening
|
||||
port and up to eight configured IPv4 address/port destinations. Eight is the
|
||||
per-board peer limit; it is not a limit on the router's number of WiFi clients.
|
||||
|
||||
```text
|
||||
LoRa network A <--> Repeater A <-- existing WiFi/LAN --> Repeater B <--> LoRa network B
|
||||
```
|
||||
|
||||
The bridge starts off on new and upgraded installations. It operates only with
|
||||
a connected station interface and a valid local IPv4 address. It pauses during
|
||||
SoftAP or AP+STA operation, WiFi disconnection, browser OTA, and incompatible
|
||||
WiFi ownership transitions, then resumes when station operation is available.
|
||||
Opening a captive configuration access point does not create a UDP bridge
|
||||
network. USB/LoRa CLI access remains useful for inspecting a paused bridge.
|
||||
|
||||
## Router client isolation
|
||||
|
||||
Client isolation is an optional access-point or guest-network policy, not a
|
||||
requirement of WiFi. When enabled it can prevent two wireless devices from
|
||||
talking directly, even though both can reach the Internet. A similar effect can
|
||||
come from VLAN rules or host firewalls. The bridge cannot bypass those rules.
|
||||
|
||||
Use a trusted SSID/VLAN that allows the two devices to exchange UDP, or ask the
|
||||
network administrator to allow the bridge peers and port. Disable isolation
|
||||
only where that network policy is appropriate. Simply changing the UDP port,
|
||||
enabling MQTT on a repeater, or configuring a second peer address does not make
|
||||
an isolation rule disappear. Some routers isolate only clients on the same
|
||||
access point; others isolate all clients or the entire guest network. Verify
|
||||
the policy on the router in use.
|
||||
|
||||
Reserve each board's DHCP address on the router. The bridge stores numeric
|
||||
IPv4 addresses, not DNS names; a changed lease can otherwise point a peer at
|
||||
the wrong device. No Internet port forwarding or public exposure is required.
|
||||
|
||||
## Configure two boards
|
||||
|
||||
Use firmware containing the UDP bridge. Connect both boards to the existing
|
||||
WiFi network using the normal [WiFi settings](WiFi.md). Read `get wifi.status`
|
||||
on each board to find its local address once connected. The commands below use
|
||||
example addresses; substitute the actual reserved addresses.
|
||||
|
||||
Both boards use the existing `bridge.secret` as their shared authentication
|
||||
secret. Set the same strong secret on both before enabling the transport. Do
|
||||
not paste it into shared diagnostic captures. The transport authenticates
|
||||
packets with HMAC-SHA256; it does not encrypt their contents. Use trusted LAN
|
||||
access and WPA2/WPA3 protection as appropriate for the network.
|
||||
|
||||
On board A, whose reserved address is `192.168.1.50`:
|
||||
|
||||
```text
|
||||
set udp.enabled off
|
||||
set udp.port 4404
|
||||
set udp.peer.1 192.168.1.51:4404
|
||||
set bridge.source rx
|
||||
set repeat on
|
||||
set udp.enabled on
|
||||
get udp.status
|
||||
```
|
||||
|
||||
On board B, whose reserved address is `192.168.1.51`:
|
||||
|
||||
```text
|
||||
set udp.enabled off
|
||||
set udp.port 4404
|
||||
set udp.peer.1 192.168.1.50:4404
|
||||
set bridge.source rx
|
||||
set repeat on
|
||||
set udp.enabled on
|
||||
get udp.status
|
||||
```
|
||||
|
||||
Each receiving board must also list the sender's listening address/port as a
|
||||
peer; this is an explicit allowlist, not discovery or a broadcast service.
|
||||
Both ports can be changed independently, but each destination must match that
|
||||
peer's actual listening port. Unicast IPv4 addresses and ports `1..65535` are
|
||||
supported; multicast, loopback, unspecified and broadcast destinations are
|
||||
rejected. Remove a destination with `set udp.peer.1 off`. Slots `1..8` have the
|
||||
same behavior, and duplicate endpoints are rejected.
|
||||
|
||||
The UDP settings are saved separately from the historical common preferences.
|
||||
An invalid or truncated record starts with UDP disabled. A rejected save keeps
|
||||
the previous runtime preferences; an uncertain filesystem result requires a
|
||||
reload before further changes. `OK - UDP settings saved` acknowledges saved
|
||||
intent, not network connectivity or confirmed peer delivery.
|
||||
|
||||
## Test each IP direction without sending on LoRa
|
||||
|
||||
Wait for `get udp.status` to show ready peer sessions. Each peer establishes an
|
||||
authenticated session using the shared secret, a fresh boot/session identity
|
||||
and a challenge exchange. Replay checks reject stale data and diagnostic probes.
|
||||
|
||||
From board A's local USB console:
|
||||
|
||||
```text
|
||||
udp test 1 A1B2C3D4
|
||||
get udp.stats test
|
||||
```
|
||||
|
||||
On board B:
|
||||
|
||||
```text
|
||||
get udp.stats test
|
||||
```
|
||||
|
||||
Board B's `rx` should increase and `rxid` should match `A1B2C3D4`. Reverse the
|
||||
test with a different ID to check the other direction. `udp test 1` generates
|
||||
an ID from uptime; an explicit ID must have exactly eight hexadecimal digits.
|
||||
The peer number is the local configured slot, not a global board identifier.
|
||||
|
||||
A queued/sent result confirms only local acceptance by the UDP stack. UDP
|
||||
itself does not guarantee delivery. A received probe proves authenticated
|
||||
transport receipt on that peer; it does not prove LoRa forwarding. Probes do
|
||||
not enter the mesh packet pool, echo, retransmit or transmit on LoRa. Test and
|
||||
counter-reset commands require a local connection; normal configuration uses
|
||||
the existing authenticated CLI access policy.
|
||||
|
||||
## Diagnose mesh traffic
|
||||
|
||||
```text
|
||||
get udp.status
|
||||
get udp.stats
|
||||
get udp.stats rx
|
||||
get udp.stats tx
|
||||
get udp.stats drops
|
||||
get udp.stats test
|
||||
```
|
||||
|
||||
Status separates saved intent from network readiness and authenticated peer
|
||||
sessions. `ready` counts established boot sessions, not current peer liveness;
|
||||
an offline peer can retain its session until a restart or reconfiguration.
|
||||
Use a fresh received probe to establish current reachability.
|
||||
Counter pages distinguish framing/authentication problems, unknown
|
||||
source endpoints, replay, mesh filters/duplicates, packet-pool pressure and
|
||||
outbound queue/socket failures. `udp resetstats` starts a new counter window
|
||||
without changing saved settings or restarting the bridge.
|
||||
|
||||
If no peer session becomes ready, check both stored endpoints, matching
|
||||
`bridge.secret`, station connectivity, isolation/firewall policy and the peer's
|
||||
actual firmware. If sessions/probes work but mesh traffic does not, check
|
||||
`bridge.source`, filters, duplicate counters and each side's LoRa setup.
|
||||
`bridge.source rx` is valid; `tx` instead selects packets after LoRa forwarding
|
||||
decisions. These source/filter settings are shared with other compiled bridges.
|
||||
|
||||
The peer list contains direct destinations for locally received/transmitted
|
||||
LoRa traffic. An incoming UDP packet enters the local LoRa mesh; it is not
|
||||
relayed to other UDP peers, including through its later local LoRa TX callback.
|
||||
A hub therefore does not provide UDP-to-UDP transit between its peers. Normal
|
||||
mesh duplicate/filter checks still apply, including when several repeaters
|
||||
hear the same LoRa packet. The configured eight-peer fan-out is bounded; it
|
||||
does not increase LoRa capacity or promise delivery through an arbitrary IP
|
||||
topology. Avoid unnecessary parallel paths and loops.
|
||||
|
||||
For a short USB diagnostic capture, record `get usb.logging` and
|
||||
`get usb.debug`, then enable both:
|
||||
|
||||
```text
|
||||
set usb.logging on
|
||||
set usb.debug on
|
||||
```
|
||||
|
||||
Restore both previous values afterward. Bounded `UDP:` updates are emitted
|
||||
from the main loop at most once per second when diagnostic state changes.
|
||||
The counter pages and probes work without either logging gate. Never include
|
||||
WiFi passwords or `get bridge.secret` in logs you share.
|
||||
Reference in new issue
Block a user