Whonix friendly applications best practices

From Whonix
< Dev
Jump to navigation Jump to search

Best practices on writing applications compatible with Whonix.

config.d support[edit]

Please parse a configuration directory to apply options to your application, such as parsing /etc/your-application.d configuration folder (and /usr/local/etc/your-application.d for better Qubes support) so Linux distributions such as Debian, Kicksecure and Whonix can set defaults (such as proxy / stream isolation configuration). Users are of course free to overrule these defaults using the usual configuration files in the user's home folder.

Please parse only configuration files with a defined file extension such as .conf to avoid parsing backup, swap and temporary files. Graphical editors such as kate create backup files such as file-name~, vim create .file-name.swp or APT / dpkg creating files such as file-name.dpkg-old which would lead to unexpected results, should be ignored by your parsing logic.

The parsing rules should be consistent and documented, preferably on the manual page or the program's documentation. As of Tor version 4.7.10, the manual page describes the parsing logic and could inspire the parsing design of your application:

       Configuration options can be imported from files or folders using the %include option with
       the value being a path. This path can have wildcards. Wildcards are expanded first, then
       sorted using lexical order. Then, for each matching file or folder, the following rules
       are followed: if the path is a file, the options from the file will be parsed as if they
       were written where the %include option is. If the path is a folder, all files on that
       folder will be parsed following lexical order. Files starting with a dot are ignored.
       Files in subfolders are ignored. The %include option can be used recursively. New
       configuration files or directories cannot be added to already running Tor instance if
       Sandbox is enabled.

It is important the parsing occurs has a defined order, such as the lexical.

If it is lexical, the configuration shipped with your program named 00_default.conf for example, has a lower precedence compared to an anonymity system configuration file that overrides the default options with a file parsed later 30_whonix.conf. A user can then overwrite all configuration files by making it be last one to be parse, named 50_user.conf as an example.

It is also possible to combine the lexical order with overriding by last match, stopping on the first match. It is up to your team to design what is best for the development of the program, as long as it is documented clearly, you are taking the first step for your application to become Tor friendly.

Stream Isolation[edit]

Please set SOCKS user name for Stream Isolationarchive.org, this enables IsolateSOCKSAuth which is one of the default isolation flags for tor ports used by clients. This method enforces stream isolation on the application level independent of other applications using the same port, different SOCKS Authorizations will be stream isolated.

Ephemeral onion services[edit]

  • Please use ADD_ONION Tor control protocol command / Tor ephemeral onion services.

ephemeral: Means the onion service will be gone after the Tor control connection is closed. It's however possible to retrieve onion service private key and to restore it at next run. It is important for your application to retry ADD_ONION after the Tor control connection is closed so the user does not have to stop and start your application again to retrieve an onion service. If your application uses Flags=Detach, it is important for your program to issue the DEL_ONION controller command to avoid having an onion hanging when your application has already closed.

Tor ephemeral onion services are a lot a lot better for Whonix than preconfigued Tor hidden services because it does not require the user to configure onion services manually, therefore a better usability.

OnionSharearchive.org by @micahfleearchive.org has superb Tails and Whonix support.

Listening Interface[edit]

The listening interface is that interface that your program will bind to listen for incoming connections.

  • Listen on all interfaces (0.0.0.0) rather than just 127.0.0.1. (This is required since the incoming onion service connection comes from the network, not from localhost.)
    # In Whonix, listen on 0.0.0.0 instead of 127.0.0.1
    if os.path.exists('/usr/share/anon-ws-base-files/workstation'):
        host = '0.0.0.0'
    else:
        host = '127.0.0.1'

Related: Listen Port Conventionarchive.org

Listening Port[edit]

  • Don't listen on a random local server port, instead listen on a specific local server port or port range. Using this method, it is easier to open only the necessary range of incoming ports on the firewall instead of all ports, as it would not be possible to automate the process of opening the firewall port when there is no range.
  • Tor VIRTPROT (remote virtual port on the onion service) does not matter.

An application that applies that listening port methodology is Onionshare:

  • OnionShare uses 17600 - 17659. That is handy, so we can match for it using (176[0-5][0-9]) in the onionshare onion-grater whitelist configarchive.org.
  • That way OnionShare (running inside a compromised Workstation) cannot open arbitrary ports on the workstation. For example, not to the real Tor ControlPort and circumvent the filtering. (We use Tor ControlSocket rather than ControlPort now for this reason.) There are no local ports open on Whonix-Gateway besides Tor Socks, DNS and TransPort, but if there was (let's say for example for brlttyarchive.org), then we don't want connections to it.
  • That allows us to set a limit on how many Tor hidden services (a compromised) workstation can create.
  • It's also useful so users don't have to open all incoming ports in Whonix-Workstation Firewall.

Tor Settings Autodetection[edit]

  • Auto detect Tor settings through TOR_* environment variables.

In Whonix:

TOR_CONTROL_IPC_PATH=/var/run/anon-ws-disable-stacked-tor/127.0.0.1_9151.sock
TOR_SOCKS_IPC_PATH=/var/run/anon-ws-disable-stacked-tor/127.0.0.1_9150.sock

These are Unix domain socket files.

Ports works fine for Whonix as per design the Workstation is isolated and uses the Gateway as its only source of networking, but nowadays Unix domain socket files are much more advisable since these are less likely to leak for non-isolated systems.

Robustness[edit]

  • The application should not crash if Tor ControlPort replies something unexpected such as 510 Command filtered.

If the application does crash, even though it can not get replies from the tor controller by receiving 510 Command filtered, the user won't understand why your program is not working and won't try to use it again, that is not a good user experience. The application should have error handling for unexpected tor control replies.

Usability[edit]

  • Show an error message if Whonix is detected and ControlPort receiving 510 Command filtered replies. Sample error message:
  • onionshare has a Tor settings dialogarchive.org. But not really needed in Whonix.

Bonus[edit]

Connections to the controller are passed through a proxy called onion-grater, which only allows basic features by default. After the profile is built for your program, your application should work gracefully.

  • Bonus: Make a list of Tor control commands you are using so an onion-grater profile can be written.
  • Bonus: Write an onion-grater profilearchive.org.

Programmatically Detecting Whonix[edit]

Various marker files are available:

  • Whonix generally: /usr/share/whonix/marker
  • Whonix-Gateway: /usr/share/anon-gw-base-files/gateway
  • Whonix-Workstation: /usr/share/anon-ws-base-files/workstation

See Also[edit]

Forum Discussion[edit]

https://forums.whonix.org/t/whonix-friendly-applications-best-practicesarchive.org

Footnotes[edit]

We believe security software like Whonix needs to remain open source and independent. Would you help sustain and grow the project? Learn more about our 12 year success story and maybe DONATE!