Skip to content

Commit 9efd7ef

Browse files
committed
Switch mode WireGuard example!
1 parent c72bdc6 commit 9efd7ef

File tree

4 files changed

+84
-3
lines changed

4 files changed

+84
-3
lines changed

Examples/SwitchBytecode/README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,14 @@ b3 f3 53 00
165165
67 80 00 00
166166
13 05 f0 ff
167167
67 80 00 00
168-
```
168+
```
169+
170+
### Example - WireGuard
171+
172+
[WireGuard](https://www.wireguard.com/papers/wireguard.pdf) (WG) runs exclusively on UDP, and sessions use 32bit sender and receiver IDs. So it's a perfect candidate for MiniPlex Switch mode.
173+
174+
Using MiniPlex as a central WireGuard switch, you could have a completely ephemeral VPN where all endpoints are dynamic (no fixed addresses and all initiators). MiniPlex would be the only fixed point, and it just forwards encrypted traffic, so the only risk is denial of service even if it's compromised.
175+
176+
It's an interesting [Example](SwitchWireGuard.s), because sessions are established by a handshake which exchanges sender and receiver IDs. Following the handshake, packets only container the receiver ID, so the example showcases the ability for bytecode to use persistent memory for stateful protocols.
177+
178+
Disclaimer: this example hasn't been performance tested. Obvioulsy, funnelling a WG VPN through a userspace app is going to create a performance constraint - your miliage may vary.
390 KB
Binary file not shown.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# a0: pointer to packet
2+
# a1: size of packet
3+
# a2: pointer to src (output u64)
4+
# a3: pointer to dst (output u64)
5+
6+
#
7+
# WireGuard (WG) sessions are established by a handshake which establishes 32bit sender and receiver IDs
8+
# After the first two handshake messages, packets only contain the receiver ID
9+
# So, we need to keep a record of the sender/receiver pairs from the handshake
10+
# Here we use a simple 'hash' table (the 'hash' is really just the 16 LSBits of an ID) to store the pairs
11+
# Hash collisions aren't really a problem, a session will get dropped and it will just change IDs and restart
12+
#
13+
14+
# macro to lookup a hash table entry
15+
.macro LOOKUP addr key
16+
li t2, 0xFFFF
17+
and t2, \key, t2 # take 'hash' (lower 16)
18+
la t3, hash_table # load the address of the hash table
19+
li t4, 6 # size of an entry (2byte receiver msbs, 4byte sender)
20+
mul \addr, t4, t2 # get the offset for the hash
21+
add \addr, \addr, t3# address of the hash table entry
22+
.endm
23+
24+
start:
25+
li t0, 12 # All WG packets are more than 12 bytes
26+
bltu a1, t0, err # error, buffer size < 12
27+
28+
lbu t0, 0(a0) # load WG packet type
29+
li t1, 4
30+
beq t0, t1, trans # transport message
31+
li t1, 1
32+
beq t0, t1, init # initiation packet
33+
li t1, 2
34+
beq t0, t1, resp # initiation response
35+
li t1, 3
36+
beq t0, t1, cookie # under load - cookie
37+
j err # error, start bytes invalid
38+
init:
39+
lwu t0, 4(a0) # load sender
40+
li t1, 0x123456789 # bogus receiver - 33 bits
41+
j success
42+
resp:
43+
lwu t0, 4(a0) # load sender
44+
lwu t1, 8(a0) # load receiver
45+
LOOKUP t5, t1 # lookup receiver
46+
srli t2, t1, 16 # get most significant bytes of receiver
47+
sh t2, 0(t5) # store the receiver msbs
48+
sd t0, 2(t5) # store the sender
49+
LOOKUP t5, t0 # lookup sender
50+
srli t2, t0, 16 # get most significant bytes of sender
51+
sh t2, 0(t5) # store the sender msbs
52+
sd t1, 2(t5) # store the receiver
53+
j success
54+
cookie:
55+
trans:
56+
lwu t1, 4(a0) # load receiver
57+
LOOKUP t5, t1 # lookup receiver
58+
lhu t2, 0(t5) # load msbs from table
59+
srli t3, t1, 16 # get receiver msbs
60+
bne t2, t3, err # error, 'hash' collision - drop and it'll switch addrs
61+
lwu t0, 2(t5) # load sender
62+
success:
63+
sd t0, 0(a2) # store src to output
64+
sd t1, 0(a3) # store dst to output
65+
li a0, 0 # success return 0
66+
jr ra
67+
err:
68+
li a0, -1 # error return -1
69+
jr ra
70+
hash_table:
71+
.space 399360, 0 # 64k 6 byte slots

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ You can download a pre-built binaries for various platforms from the github [Rel
246246
## Example Use Case
247247

248248
Suppose you have a network that doesn't support UDP multicast. Maybe it's disabled for security or performance, or maybe you like firewall policies to have strict point-to-point rules.
249-
But you would still like to stream UDP packets to multiple endpoints. This is where MiniPlex can help. MiniPlex can convert a single unicast stream into multiple streams. For example:
249+
But you would still like to stream UDP packets to multiple endpoints. This is where MiniPlex can help. MiniPlex can convert a single unicast stream into multiple streams, or route packets in any number of ways. For example:
250250

251251
### Stream some audio to multiple endpoints:
252252

@@ -271,7 +271,7 @@ vlc udp://@:1234
271271

272272
### UDP Switch
273273

274-
See [these examples](Examples/SwitchBytecode/README.md) for how to use MiniPlex as a layer 4 UDP switch!
274+
See [these examples](Examples/SwitchBytecode/README.md) for how to use MiniPlex as a layer 4 UDP switch! The examples include VXLAN, WireGuard and DNP3, but any address based protocol is possible.
275275

276276
## Build
277277

0 commit comments

Comments
 (0)