Skip to content

pbr: document Tor, and link to the full reference - #27

Merged
egc112 merged 1 commit into
mainfrom
pbr-1.2.3-tor-docs
Aug 13, 2026
Merged

pbr: document Tor, and link to the full reference#27
egc112 merged 1 commit into
mainfrom
pbr-1.2.3-tor-docs

Conversation

@egc112

@egc112 egc112 commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

What

Tor had exactly one line in the docs, repeated verbatim in every version:

Tor tunnels supported in nft mode only (interface name must match tor).

Everything a user needs in order to set Tor up, or to work out why it isn't working, was undocumented.

Two files:

  • pbr/1.2.3/README.md — a ### Tor section between DNS Policies and Custom User Files, with the existing Gateways/Tunnels bullet linked to it.
  • pbr/tor/README.md — the deep-dive reference it links out to, version-independent, published at https://docs.mossdef.org/pbr/tor/.

Scope

Deliberately kept to what a casual OpenWrt user needs for a working setup:

  • What Tor is here — a dstnat redirect rather than a routed interface, with no routing table, mark or gateway of its own.
  • That only ports 53, 80 and 443 are redirected, so a Tor policy is not a kill switch.
  • That dest_port, proto and chain are ignored on a Tor policy and src_port produces an invalid rule — match on source address instead.
  • A minimal working torrc, why AutomapHostsOnResolve is mandatory, and the IPv6 listeners.
  • That the service reads /etc/tor/torrc only, so ports in /etc/tor/custom — where OpenWrt's own Tor client guide puts them — are never seen.
  • A source-matched example policy, and the tradeoff that it sends all of that client's DNS through Tor.
  • Why .onion does not resolve on a stock OpenWrt: /usr/share/dnsmasq/rfc6761.conf carries an addressless server=/onion/ that overrides any server=/onion/127.0.0.1#9053, with the one-line logread check that confirms it.

Depth lives elsewhere

The full mechanism, the complete set of silent failure modes, and step-by-step diagnostics live in pbr/tor/README.md, which the README section links to rather than restating. That keeps the version README suited to its audience and stops two copies of the fiddly parts drifting apart.

Both files are in this PR, so there is no cross-repo merge dependency and no window where the link is broken. (An earlier draft put this file in the pbr repository — mossdef-org/pbr#151, now closed in favour of this.)

Laid out as <dir>/README.md and linked with an absolute URL, matching how every other page in this repo is structured and linked — all 33 pages are directory READMEs, and every cross-page link is a full https://docs.mossdef.org/... URL.

Details

The reference torrc uses VirtualAddrNetworkIPv4 172.16.0.0/12 rather than Tor's own default of 127.192.0.0/10, to match what OpenWrt's Tor client guide sets — so a reader following both doesn't hit a mismatch.

Scoped to 1.2.3 only — the top-level pbr/README.md and the older versioned copies (1.1.x, 1.2.0, 1.2.2) are left alone.

Provenance (maintainer-facing)

Moved here out of the published doc, which now carries only a two-line note.

Written by Claude (Anthropic) on 2026-08-12/13 while working a pbr support thread: reading the pbr source and its git history, the dnsmasq and Tor manuals, and running tests against a live OpenWrt router. Most of it is verified against those sources or reproduced experimentally, but some is inference.

Worth recording that several confident-sounding conclusions were proposed and then disproved during that investigation before the real cause surfaced — dnsmasq rebind protection, all-servers racing the upstreams, and ".onion cannot be forwarded at all". Each was plausible from the configuration alone and each was killed by evidence rather than argument. The two things that actually moved it forward were the reporter's logqueries output and a grep of OpenWrt's dnsmasq init script.

Facts verified directly rather than inferred: the five rules and their gating (source), TransPort being TCP-only and DNSPort UDP-only (Tor manual), all-servers distributing only within the servers matched for a domain (dnsmasq man page and Simon Kelley on dnsmasq-discuss), rfc6761.conf contents and its boguspriv gating (the file and the init script, reproduced with a throwaway dnsmasq on a spare port), and the Tor path being unchanged 1.1.6 → 1.2.3 (git history).

🤖 Generated with Claude Code

@egc112
egc112 force-pushed the pbr-1.2.3-tor-docs branch 5 times, most recently from 1f5a730 to a526050 Compare August 13, 2026 11:15
@egc112

egc112 commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

All four done in a526050.

1. Provenance — shortened in the doc, full text moved to this PR

You were right, and this was flagged as an open question when the file went up. The published doc now carries two lines:

Drafted with LLM assistance and verified against the pbr source, the dnsmasq and Tor manuals, and tests on a live OpenWrt router. Paths, defaults and behaviour change between releases and the ones quoted here come from one system at one point in time — check the commands against your own.

The full version — including which conclusions were proposed and disproved along the way, and which facts were verified directly rather than inferred — is now in the PR description under Provenance (maintainer-facing). That seemed worth keeping somewhere: three plausible-sounding causes were wrong before the real one surfaced, and knowing which parts rest on evidence versus inference is useful if any of this ever needs revisiting.

2. Mode A promoted

It was buried under "The practical rule" after the whole mode B discussion. Now a callout immediately after the two modes are introduced, before either is explained:

If you just want Tor to work reliably, use mode A: set src_addr and leave dest_addr empty. It matches on the first packet, needs no DNS cooperation, and none of the ten failure modes catalogued further down can touch it. …

The one tradeoff: mode A sends all of that client's DNS through Tor, so local filtering (adblock and friends) stops applying to it.

Tradeoff kept prominent, as you asked.

3a. Filled nftset example

Added right after the <uid> note, with what a healthy set looks like and how to read the two failure shapes:

set pbr_tor_4_dst_ip_cfg0c6ff5 {
        type ipv4_addr
        flags interval
        auto-merge
        comment "TOR_ONION"
        elements = { 172.17.245.221, 172.18.3.14 }
}

Followed by: public addresses (40.x, 140.x, 185.x…) mean something other than Tor answered; no elements line at all means nothing has resolved yet, or lookups aren't reaching dnsmasq. Those are the two states seen in the support thread that started this.

3b. Post-upgrade check in the quick reference

| How do I check .onion still resolves after an OpenWrt upgrade? | grep -c rfc6761 /var/etc/dnsmasq.conf.*0 = forwardable, 1 = localised |

Worth having there: the boguspriv workaround for rfc6761.conf works by accident rather than design, so an upgrade can silently undo it — which is how the original breakage happened.

4. Wording suggestions

I don't see the inline suggestions on this PR — possibly not submitted with the review. Happy to take them if you post them.

@egc112
egc112 force-pushed the pbr-1.2.3-tor-docs branch from a526050 to f94375d Compare August 13, 2026 11:21
@egc112

egc112 commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

Second one applied in f94375d. On the first I'd push back — I think it's a misread.

1. See [Tor](#tor) — this is an in-page anchor, not a cross-page link

The bullet is at pbr/1.2.3/README.md:181; its target ### Tor is at line 314 of the same file. Clicking it jumps a few screens down to the setup section on the page the reader is already on — it does not leave the page.

The absolute-URL convention applies to cross-page links, and it is followed: the one genuine cross-page link in this section, the "Going deeper" pointer to the deep-dive, uses https://docs.mossdef.org/pbr/tor/.

For same-page references this file uses in-page anchors 150 times](#requirements), ](#policy-options), ](#custom-user-files), ](#footnotesknown-issues) and so on. ](#tor) matches that exactly.

Changing it as suggested would also change the behaviour for the worse. Someone reading the Gateways/Tunnels list and clicking "See Tor for setup and caveats" wants the setup section — a short read on the page they are already on. Sending them instead to the 495-line mechanism reference is the wrong destination for that intent; that document is what "Going deeper" is for, at the end of the section.

Happy to change it if you still disagree, but as it stands it is both conventional and pointing where the wording promises.

2. "those 3 ports" → "those ports"

Done. The row directly above it already says "only ports 53, 80 and 443", so the numeral was redundant as well as stylistically off.

@egc112

egc112 commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

Co-pilot final review:

Merge readiness and risk

Status: Ready to merge from my side (documentation-only, no code).
Risk: Low. No behavioural changes; only docs added/edited.
CI: not applicable.

@egc112
egc112 merged commit 54c53f5 into main Aug 13, 2026
Tor had exactly one line in the docs -- "Tor tunnels supported in nft mode
only (interface name must match tor)" -- repeated verbatim in every version.
Everything a user needs in order to set it up, or to work out why it is not
working, was undocumented.

Adds a Tor section to pbr/1.2.3/README.md, between DNS Policies and Custom
User Files, and links the existing Gateways/Tunnels bullet to it. Scoped to
what a casual OpenWrt user needs:

 - What Tor is here: not a routed interface but a dstnat redirect, with no
   routing table, mark or gateway of its own.
 - That only ports 53, 80 and 443 are redirected, so a Tor policy is not a
   kill switch.
 - That dest_port, proto and chain are ignored on a Tor policy and src_port
   produces an invalid rule; match on source address instead.
 - A minimal working torrc, why AutomapHostsOnResolve is mandatory, and the
   IPv6 listeners.
 - That the service reads /etc/tor/torrc only, so ports in /etc/tor/custom --
   where OpenWrt's own Tor client guide puts them -- are not seen.
 - A source-matched example policy, and the tradeoff that it sends all of that
   client's DNS through Tor.
 - Why .onion does not resolve on a stock OpenWrt: rfc6761.conf carries an
   addressless server=/onion/ that overrides any server=/onion/127.0.0.1#9053,
   with the logread check that confirms it.

The full mechanism, the complete set of silent failure modes and the
step-by-step diagnostics live in docs/tor.md in the pbr repository, which this
section links to rather than restating. Keeping the depth in one place stops
the two copies drifting, and keeps this page suited to its audience.

The reference torrc uses VirtualAddrNetworkIPv4 172.16.0.0/12 rather than
Tor's own default, to match what OpenWrt's Tor client guide sets, so a reader
following both does not hit a mismatch.

Scoped to 1.2.3 only. The top-level pbr/README.md and the older versioned
copies (1.1.x, 1.2.0, 1.2.2) are left alone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Signed-off-by: Erik Conijn <egc112@msn.com>
@egc112
egc112 deleted the pbr-1.2.3-tor-docs branch August 13, 2026 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant