TBB Sanitized Circuit Path Diagram Support

This is now done. I’ve tested it and it works for clearnet and onion service sites, the circuit path diagram shows without any sensitive info. TBB’s Authenticated Service login prompt now shows. A quick look at the onion-grater debug logs doesn’t show anything dangerous slipping thru, but I will need you to also double check this is the case.

Let me know if you want this committed as a separate profile or merged into the default one.

I noticed:

  • The TBB environment variable that disables the circuit path thingie doesn’t work in practice - it will show when the controlport communicates the needed commands in all cases.

  • The confs bridge command is needed for this to work, but I don’t know exactly what it can allow.

1 Like

Awesome!

Redacted example if using bridges.

GETCONF bridge

250-Bridge=obfs4 xxx.xxx.xxx.xxx:xxx yyy cert=xxx iat-mode=1

Multiple lines. One line for each bridge. That surely should be redacted.

Non-redacted example when not using bridges.

GETCONF bridge

250 Bridge

Therefore when Tor Browser asks GETCONF bridge it would be best to make onion-grater reply 250 Bridge whether using bridges or not?

Btw not in this case but generally often https://gitweb.torproject.org/torspec.git/tree/control-spec.txt helps.

Default one as we don’t want to confuse Tor Browser. By using this widely, we’ll be ready for for any upcoming Tor Browser control protocol demands.

1 Like

Took some effort but got getconf bridge working. Replying just 250 Bridge doesn’t cut it. I had to feed it a redacted reply.

The remaining command I have to clean up to make safe is getinfo circuit-status. It is required so we can’t block it, however it passes all the info about a circuit path fully. The replies have varying lengths and so require a bunch of rules with varying capture group numbers to account for all possible patterns.

There are two problems with the whitelist rule I have right now:

Doing a regex on
250+circuit-status is problematic because + is also interpreted as a special character if not escaped. I tried escaping pattern and reply as well as just the normal pattern, but that doesn’t work. There could also be problems with white-spaces.

Example raw output:

250+circuit-status=00 BUILT Z~Z,Z~Z,Z~Z BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2020-09-16T00:00:00.000000

Example pattern rule checked on pythex.org:

250\+circuit-status=(\S+) BUILT (\S+) (\S+) (\S+) (\S+)

What I am using as a replacement:

250+circuit-status=redacted


The 650 STREAM events seem to be about the destination IP only and don’t reveal anything about circuits.

1 Like

Latest working version of the 40_ tor-browser.yml I am using. It takes effect after running sudo ln -s /usr/share/doc/onion-grater-merger/examples/40_tor-browser.yml /usr/local/etc/onion-grater-merger.d/
The WIP section for circuit-status and related onion-grater debug output is posted below it.

---
- exe-paths:
    - '*'
  users:
    - '*'
  hosts:
    - '*'
  commands:
    SIGNAL:
      - 'NEWNYM'
    GETINFO:
      - 'circuit-status'
    GETCONF:
      - pattern: 'bridge'
        response:
        - pattern:     '250-Bridge=(.+) (\S+) (\S+) (\S+) (\S+)'
          replacement: '250-Bridge='
        - pattern:     '250 Bridge=(.+) (\S+) (\S+) (\S+) (\S+)'
          replacement: '250 Bridge='
  events:
    STREAM:
  restrict-stream-events: true

   GETINFO:
      - pattern: 'circuit-status'
        response:
        - pattern: '250(.+)circuit-status=(\S+) (\S+) (.+) (\S+) (\S+)'
        - replacement: '250+circuit-status='

The onion-grater debug mode:

 host onion-grater[8471]:   - pattern: circuit-status
 host onion-grater[8471]:     response:
 host onion-grater[8471]:     - {pattern: 250(.+)circuit-status=(\S+) (\S+) (.+) (\S+) (\S+)}
 host onion-grater[8471]:     - {replacement: 250+circuit-status=}
 host onion-grater[8471]:   SIGNAL:
 host onion-grater[8471]:   - {pattern: NEWNYM}
 host onion-grater[8471]: events:
 host onion-grater[8471]:   CONF_CHANGED: {suppress: true}
 host onion-grater[8471]:   SIGNAL: {suppress: true}
 host onion-grater[8471]:   STATUS_SERVER: {suppress: true}
 host onion-grater[8471]:   STREAM: {}
 host onion-grater[8471]: restrict-stream-events: false
 host onion-grater[8471]: 10.152.152.11:56158 (filter: 30_autogenerated): -> getinfo circuit-status
 host onion-grater[8471]: 10.152.152.11:56158 (filter: 30_autogenerated) disconnected: client quit
 host onion-grater[8471]: ----------------------------------------
 host onion-grater[8471]: Exception happened during processing of request from ('10.152.152.11', 56158)
 host onion-grater[8471]: Traceback (most recent call last):
 host onion-grater[8471]:   File "/usr/lib/python3.7/socketserver.py", line 650, in process_request_thread
 host onion-grater[8471]:     self.finish_request(request, client_address)
 host onion-grater[8471]:   File "/usr/lib/python3.7/socketserver.py", line 360, in finish_request
 host onion-grater[8471]:     self.RequestHandlerClass(request, client_address, self)
 host onion-grater[8471]:   File "/usr/lib/python3.7/socketserver.py", line 720, in __init__
 host onion-grater[8471]:     self.handle()
 host onion-grater[8471]:   File "/usr/lib/onion-grater", line 661, in handle
 host onion-grater[8471]:     session.handle()
 host onion-grater[8471]:   File "/usr/lib/onion-grater", line 481, in handle
 host onion-grater[8471]:     response_rewriter=response_rewriter)
 host onion-grater[8471]:   File "/usr/lib/onion-grater", line 277, in proxy_line
 host onion-grater[8471]:     new_response = response_rewriter(response)
 host onion-grater[8471]:   File "/usr/lib/onion-grater", line 462, in _response_rewriter
 host onion-grater[8471]:     lines)
 host onion-grater[8471]:   File "/usr/lib/onion-grater", line 314, in rewrite_matched_lines
 host onion-grater[8471]:     for line in split_lines]) + "\r\n"
 host onion-grater[8471]:   File "/usr/lib/onion-grater", line 314, in <listcomp>
 host onion-grater[8471]:     for line in split_lines]) + "\r\n"
 host onion-grater[8471]:   File "/usr/lib/onion-grater", line 307, in rewrite_matched_line
 host onion-grater[8471]:     return self.rewrite_line(replacers, line)
 host onion-grater[8471]:   File "/usr/lib/onion-grater", line 298, in rewrite_line
 host onion-grater[8471]:     match = re.match(r['pattern'] + "$", line)
 host onion-grater[8471]: KeyError: 'pattern'
 host onion-grater[8471]: ----------------------------------------

i want to know what the error means so I can work around it.
My guess is it doesn’t like the relay names because the “$”’ part is breaking it somehow. Or maybe something to do with newlines?

1 Like

Maybe the + is considered a special character and should be escaped as \+?

That is hopefully only considered text and not processed as pattern by onion-grater.