Re: [Tails-dev] Tails control port filter proxy in Whonix?

Delete this message

Reply to this message
Author: Patrick Schleizer
Date:  
To: The Tails public development discussion list
Subject: Re: [Tails-dev] Tails control port filter proxy in Whonix?
anonym:
> Patrick Schleizer:
>>>>>> - https://phabricator.whonix.org/T564
>>>>
>>>> Protecting cpfpy from DDOS from client applications. Not sure that
>>>> matters for Tails?
>>>
>>> We do not do much specific here. What kind of DoS are you talking about
>>> here? Eating up all RAM or crashing the filter via oom kill? Preventing
>>> the filter from serving other clients? We admittedly do not do much here
>>> except that each client is dealt with in a separate thread, and that
>>> client requests are limited to 1024 bytes.
>>
>> Yes, I meant crashing the filter or making the whole computer unusable
>> by flooding cpfpy with too much requests.
>
> So the scenario is something like this: an attacker compromises the
> workstation, and then want to crash the filter running on the gateway
> (or even crash the whole gateway)?


Yes.

> If so, IMHO DoS is the least of our
> worries since all gateway activity (= user activity) now is compromised.
> I mean, the attacker can DoS the workstation by killing all user
> processes or whatever.
>
> ... but now I get that you may run several workstations (in Qubes, I
> guess), and then this makes sense.


Yes.

> Quick solution that a determined adversary probably easily can work
> around: in the gatway's firewall rules, rate limit the traffic to the
> control filter per workstation.


I will consider this, useful, but guess it's not a priority as you
pointed out.

> Slightly more involved, slightly more efficient solution: we could add
> an option to the filter making the server forking instead of threading,
> and then adjust OOM scores and NICEness for these subprocesses so they
> are low prio for the CPU, and prone to get OOM killed if memory gets
> low. The server process itself will be configured in the opposite way
> (you can add the options via a systemd override).
>
> Any way, DoS protection is pretty hard... and I doubt it's much of a
> problem on *local* systems. Rather DoS gives away that a workstation has
> been compromised, instead of it remaining in a stealthy surveillance
> mode, which I think I must consider worse (even when limited to a single
> workstation == application).


>>> I could even imagine yet another rule-type for solving these types of
>>> issues:
>>>
>>>     GETINFO:
>>>       - pattern: 'net/listeners/socks'
>>>         respond: '250-net/listeners/socks="127.0.0.1:9150"'

>>
>> Seems great!
>
> In the end, this was generalised into:
>
>     GETINFO:
>       - pattern: 'net/listeners/socks'
>         response:
>         - pattern:     '250-net/listeners/socks=".*"'
>         - replacement: '250-net/listeners/socks="127.0.0.1:9150"'


That crashes the filter for me.

config:

---
- match-exe-paths:
    - '*'
  match-users:
    - '*'
  match-hosts:
    - '*'
  commands:
    SIGNAL:
      - 'NEWNYM'
    GETINFO:
      - 'circuit-established'
    GETINFO:
      - pattern: 'net/listeners/socks'
        response:
        - pattern:     '250-net/listeners/socks=".*"'
        - replacement: '250-net/listeners/socks="127.0.0.1:9150"'


run:

user@host:~$ ./tor-controlport-filter --listen-address 0.0.0.0 --debug
Tor control port filter started, listening on 0.0.0.0:9051
10.137.11.80:49996 (filter: tor-browser) connected: loaded filter:
tor-browser
Final rules:
commands:
  GETCONF:
  - {pattern: ()}
  GETINFO:
  - pattern: net/listeners/socks
    response:
    - {pattern: 250-net/listeners/socks=".*"}
    - {replacement: '250-net/listeners/socks="127.0.0.1:9150"'}
  SIGNAL:
  - {pattern: NEWNYM}
events: {}
restrict-stream-events: false


10.137.11.80:49996 (filter: tor-browser): -> GETINFO net/listeners/socks
10.137.11.80:49996 (filter: tor-browser) disconnected: client quit
----------------------------------------
Exception happened during processing of request from ('10.137.11.80', 49996)
Traceback (most recent call last):
  File "/usr/lib/python3.4/socketserver.py", line 613, in
process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python3.4/socketserver.py", line 344, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python3.4/socketserver.py", line 669, in __init__
    self.handle()
  File "./tor-controlport-filter", line 550, in handle
    restrict_stream_events
  File "./tor-controlport-filter", line 466, in handle_controlport_session
    response_rewriter=response_rewriter)
  File "./tor-controlport-filter", line 302, in proxy_line
    new_response = response_rewriter(response)
  File "./tor-controlport-filter", line 447, in _response_rewriter
    return rewrite_matched_lines(rule['response'], lines)
  File "./tor-controlport-filter", line 331, in rewrite_matched_lines
    for line in split_lines]) + "\r\n"
  File "./tor-controlport-filter", line 331, in <listcomp>
    for line in split_lines]) + "\r\n"
  File "./tor-controlport-filter", line 324, in rewrite_matched_line
    return rewrite_line(replacers, line)
  File "./tor-controlport-filter", line 319, in rewrite_line
    return r['replacement'].format(*match.groups()) + terminator
KeyError: 'replacement'
----------------------------------------


Cheers,
Patrick