GitHub

Fox Red Labs / Builds / Networking

A DNS ad blocker on a Wi-Fi board

The CC35X1 answers DNS on your network. Names on a 71,492-name blocklist get 0.0.0.0; everything else is forwarded to your router. Nothing changes until you point one device at it.

HardNo wiringabout half an hour (estimate, not timed)

Parts and steps

You need

  1. Get a blocklist.TERMINAL

    Download the hosts file.

    cd ports/dns-sinkhole curl -fsS -o hosts.txt https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts

    You should see: hosts.txt exists and lists tens of thousands of names.

  2. Make the table.TERMINAL

    Hash and sort the names: 5 bytes per domain.

    python3 gen_blocklist.py hosts.txt -o blocklist.bin

    You should see: blocklist.bin is about 349 kB.

  3. Build and sign.TERMINAL

    Build the full blocker. The Wi-Fi name comes from the Mac's saved networks and the password from a file you name. It takes about two minutes. APP=min ./build.sh builds stage 1, which answers 192.0.2.1 to every name.

    Replace <file with WIFI_PASSWORD=...> before you run this.

    APP=full BLOCKLIST=$PWD/blocklist.bin WIFI_ENV=<file with WIFI_PASSWORD=...> ./build.sh

    You should see: The script prints the build folder with ex/freertos/ticlang/toolbox/tool_settings.json.

  4. Program the board.TERMINAL

    Program the signed build with the Wi-Fi Toolbox, then reset the board. Add -param1 <probe serial> when more than one probe is connected.

    Replace <build folder> before you run this.

    /Applications/ti/simplelink_wifi_toolbox_macos_4_3_23/simplelink-wifi-toolbox programmer -i XDS110 programming --tool_settings <build folder>/ex/freertos/ticlang/toolbox/tool_settings.json

    You should see: The programmer reports success; the console at 115200 baud shows the board's address.

  5. Ask the board.TERMINAL

    Ask for a listed name and an unlisted one. Your Mac's settings do not change.

    Replace <board ip> before you run this.

    dig @<board ip> doubleclick.net dig @<board ip> www.python.org

    You should see: The first answer is 0.0.0.0. The second is the real address.

  6. Point one device at it, then undo it.BROWSER

    Set one device's DNS server to the board's address in its network settings. To go back, set it to automatic. The board is not inline, so unplugging it only affects devices pointed at it.

    Replace <board ip> before you run this.

    curl http://<board ip>/

    You should see: The counters page shows blocked and forwarded names rising as that device browses.

Or hand it to a coding assistant

Paste this in a terminal. It hands off to an AI assistant.

git clone --depth 1 --filter=blob:none https://github.com/Fox-Red-Labs/fox-red-labs.git && cd fox-red-labs ./start.sh cc35x1 dns-ad-blocker --assistant claude

It runs the steps above and reports what it saw.

Not Claude Code? Copy this prompt instead.
Clone https://github.com/Fox-Red-Labs/fox-red-labs and read ports/dns-sinkhole/AGENTS.md first. Then run A DNS ad blocker on a Wi-Fi board on my LP-EM-CC35X1, following docs/builds/dns-ad-blocker.md. Tell me when to plug in a board and what you saw at each step.

If something goes wrong

Curl failsCheck the network and run it again.
Python reports a syntax errorUse Python 3.12 or newer (.python-version).
It cannot read the network nameMacOS hides it from command-line tools: set it in the file you pass as WIFI_ENV.
The programmer fails with error -260 on every callRemove any BoosterPack and replug the probe cable.
Dig times outCheck the board joined your network: the console prints its address, and a router may hand it a new one, so reserve it.
More troubleshooting
The device loses the networkSet its DNS back to automatic.

What to build next

Every build. The code for all of them is in the GitHub repository.

Evidence and limitsThe CC35X1 blocks 71,492 names from a 349 kB table in flash and answers a blocked name in a median 6 ms. Ran on 1 board. Results, sources, timing and limits.

Expected result: The board answers 0.0.0.0 for blocklisted names and the real address for the rest.

What this shows

  • A 71,492-name blocklist fits the board as a sorted table of 5-byte hashes searched in place in flash: 349 kB of flash and 0.7 kB of RAM.
  • A blocked name is answered in a median 6 ms.
What this does not establish, and limits

What this does not establish

  • No DNSSEC: answers are relayed as the upstream gave them, not validated.
  • Nobody ran it as a household's only resolver for days.

Limits to keep in mind

  • Exact name match only: a listed name does not block its subdomains.
  • IPv4 and UDP only, no caching, 16 queries in flight, a 2.5 s forward timeout.
  • A 40-bit hash means an unlisted name matches with a probability of about 7e-8. The largest list the application slot takes is about 304,000 names (link arithmetic, not booted).

Sources

Versions, sizes and timing

Blocked namemedian 6 ms, 95th percentile 20 msREADME notes
Forwarded namemedian 70 ms, 95th percentile 172 ms (router directly: 52 and 99)README notes
Forwarding defencesrandom 16-bit ID from the hardware generator, a fresh random UDP port per query, random upper and lower case in the nameREADME notes

Evidence

  • From a Mac on the same Wi-Fi, 100 queries each: blocked names answered in a median 6 ms (95th percentile 20); forwarded names in a median 70 ms (95th percentile 172) against 52 ms (99) to the router directly. README notes
  • The list of 71,492 domains is 349 kB of flash and 0.7 kB of RAM. the data (CSV)

Other boards

What the status words mean

Works ran here and did what it shouldCould work some of it ran; real porting effort is left; hover for whatNot for this chip the chip or its vendor software cannot; hover for why

Result grid

Project
LP-MSPM0G3507MSPM0G3507 chip
LP-MSPM0L1306MSPM0L1306 chip
LP-EM-CC2340R5CC2340R52 chip
LAUNCHXL-F2800137TMS320F2800137 chip
A DNS ad blocker on a Wi-Fi board
LP-MSPM0G3507Not for this chipNo Wi-Fi radio
LP-MSPM0L1306Not for this chipNo Wi-Fi
LP-EM-CC2340R5Not for this chipNo Wi-Fi radio on this chip
LAUNCHXL-F2800137Not for this chipNo radio on this chip

Works ran here and did what it shouldShould work it builds; only naming, packaging or build glue is in the way; hover for whichCould work some of it ran; real porting effort is left; hover for whatNot for this chip the chip or its vendor software cannot; hover for why

Experiments (1)

StatusWhat was triedResult
WorksCan a TI LP-EM-CC35X1 act as a DNS ad blocker for the devices pointed at it?
CC35X1, 2026-10-20
A DNS sinkhole with 71,492 blocked domains as a 349 kB hash table in flash answers blocked names in a median 6 ms and forwarded names in a median 70 ms against 52 ms asking the gateway directly, from the CC35X1.

Source files

Code brought from elsewhere

This project uses code that was written for other chips or tools. Each links to how to get it running.

Start with your code, and the prompt to port your own

Get the code and tell us how it wentThe clone command, the board folder with its AGENTS.md, reports from others, and the three report forms.

Get the code

Clone the repository and open the board's folder below. AGENTS.md is a plain text file of notes for AI coding assistants, and llms.txt at the root indexes the site for one.

git clone https://github.com/Fox-Red-Labs/fox-red-labs.git

Code is BSD-3-Clause, writing is CC BY 4.0; third-party folders keep their own licenses.

Built it? Tell us

Built this, or got stuck? Report it on GitHub with a few short answers. Your report shows here in your words, marked as yours. A failure that repeats on the bench gets its fix here.