antiTree | posts and projects
posted on Nov 29, 2017

One of my favorite things about the Tor Project is their proposal system. Every idea that’s worth thinking about goes into a proposal template that talks about the idea, the technical background, why it’s proposed, as well as any risks or design issues that need to be factored in. They read like RFC’s and that will either make you kind of excited or kind of sleepy. But in any case, they are a look into the future of tor as well as some hints about current issues that need to be addressed.

You may know by now that v3 of the onion services/hidden service protocol is pushing forward in the latest alpha and besides the changes to the main protocol, there are some changes needed for managing onion services as well. Some of this is outlined in Proposal 284: Hidden Service V3 Control Port.

Control Port

The optional control port is designed to be a way of controlling the tor instance on a system. It was a way of collecting event information, checking circuit status, and building your own circuits manually. Libraries like Stem abstract control port commands to make interaction easier. But if you wanted to, you can always simply console in via the control port and issue commands manually.

From Ports to Sockets

In the past the control port was suggested to be run on 9051/TCP using cookie-based authentication. Exposing a full TCP service that’s only meant to run on localhost could be further hardened on Linux-based systems by doing a local socket instead. This is now supported in torrc using the ControlSocket configuration item.

Hidden Service Controls

If you wanted to create an onion service[1] dynamically or manage it after it’s started, you could normally do so using the control port. With Hidden Service Protocol v3, there are a few extra control features that have to change. Namely:

  • ADD_ONION
  • DEL_ONION
  • HSFETCH
  • GETINFO

ADD_ONION and DEL_ONION will let you create and destroy a service and are already in the control spec. It has to be updated to support the new ED25519 key type and eventually the two “new” auth modes, basic and stealth.

The control port also displays event information that now has to be updated. HSFETCH is used to “fetch” service descriptors off of the network. This method is changing a lot so this control needs to change with it. There will now be a v2 fetch for legacy onion services and a v3 fetch with the blinded key of a descriptor.

The GETINFO command is a common one that I’ve used for debugging or just testing that I can interact with the tor service on the console. This will dump information about various aspects of the service depending on its arguments

GETINFO stream-status
GETINFO circuit-status
GETINFO onions/current
GETINFO onions/detached

[1]: NOTE: We’re supposed to call any service hosted with a .onion domain an “onion service” but at the same time, the protocol to create an onion services is still called a “Hidden Service” and still referenced as “HS”.

For posterity, here’s the current state of the proposal:

Filename: 284-hsv3-control-port.txt
Title: Hidden Service v3 Control Port
Author: David Goulet
Created: 02-November-2017
Status: Open

1. Summary

   This document extends the hidden service control port events and commands
   to version 3 (rend-spec-v3.txt).

   No command nor events are newly added in this document, it only desribes
   how the current commands and events are extended to support v3.

2. Format

   The formatting of this document follows section 2 of control-spec.txt. It
   is split in two sections, the Commands and the Events for hidden service
   version 3.

   We define the alphabet of a Base64 encoded value to be:

      Base64Character = "A"-"Z" / "a"-"z" / "0"-"9" / "+" / "/"

   For a command or event, if nothing is mentionned, the behavior doesn't
   change from the control port specification.

3. Specification:

3.1. Commands

   As specified in the control specification, all commands are
   case-insensitive but the keywords are case-sensitive.

3.1.1. GETINFO

   Hidden service commands are:

     "hs/client/desc/id/<ADDR>"
       The <ADDR> can be a v3 address without the ".onion" part. The rest is
       as is.

     "hs/service/desc/id/<ADDR>"
       The <ADDR> can be a v3 address without the ".onion" part. The rest is
       as is.

     "onions/{current,detached}"
       No change. This command can support v3 hidden service without changes
       returning v3 address(es).

3.1.2. HSFETCH

   The syntax of this command supports both an HSAddress or a versionned
   descriptor ID. However, for descriptor ID, version 3 doesn't have the same
   concept as v2 so, for v3 the descriptor ID is the blinded key of a
   descriptor which is used as an index to query the HSDir:

   The syntax becomes:
     "HSFETCH" SP (HSAddress / "v" Version "-" DescId)
               *[SP "SERVER=" Server] CRLF

     HSAddress = (16*Base32Character / 56*Base32Character)
     Version = "2" / "3"
     DescId = (32*Base32Character / 32*Base64Character)
     Server = LongName

   The "HSAddress" key is extended to accept 56 base32 characters which is the
   format of a version 3 onion address.

   The "DescId" of the form 32*Base64Character is the descriptor blinded key
   used as an index to query the directory. It can only be used with
   "Version=3".

3.1.5. HSPOST

   No change. This command can support v3 hidden service without changes.

3.1.3. ADD_ONION

   For this command to support version 3, new values are added but the syntax
   is unchanged:

     "ADD_ONION" SP KeyType ":" KeyBlob
                 [SP "Flags=" Flag *("," Flag)]
                 1*(SP "Port=" VirtPort ["," Target])
                 *(SP "ClientAuth=" ClientName [":" ClientBlob]) CRLF

   New "KeyType" value to "ED25519-V3" which identifies the key type to be a
   v3 ed25519 key.

   With the KeyType == "ED25519-V3", the "KeyBlob" should be a base64 encoded
   ed25519 private key.

   The "NEW:BEST" option will still return a version 2 address as long as the
   HiddenServiceVersion torrc option default is 2. To ask for a new v3 key,
   this should be used: "NEW:ED25519-V3".

   Because client authentication is not yet implemented, the "ClientAuth"
   field is ignored as well as "Flags=BasicAuth". A 513 error is returned if
   "ClientAuth" is used with an ED25519-V3 key type.

3.1.4. DEL_ONION

   The syntax of this command is:

     "DEL_ONION" SP ServiceID CRLF

     ServiceID = The Onion Service address without the trailing ".onion"
                 suffix

   The "ServiceID" can simply be a v3 address. Nothing else changes.

3.2. Events

3.2.1. HS_DESC

   For this event to support vesrion 3, one optional field and new
   values are added:

     "650" SP "HS_DESC" SP Action SP HSAddress SP AuthType SP HsDir
           [SP DescriptorID] [SP "REASON=" Reason] [SP "REPLICA=" Replica]
           [SP "HSDIR_INDEX=" HSDirIndex]

     Action =  "REQUESTED" / "UPLOAD" / "RECEIVED" / "UPLOADED" / "IGNORE" /
               "FAILED" / "CREATED"
     HSAddress = 16*Base32Character / 56*Base32Character / "UNKNOWN"
     AuthType = "NO_AUTH" / "BASIC_AUTH" / "STEALTH_AUTH" / "UNKNOWN"
     HsDir = LongName / Fingerprint / "UNKNOWN"
     DescriptorID = 32*Base32Character / 43*Base64Character
     Reason = "BAD_DESC" / "QUERY_REJECTED" / "UPLOAD_REJECTED" / "NOT_FOUND" /
              "UNEXPECTED" / "QUERY_NO_HSDIR"
     Replica = 1*DIGIT
     HSDirIndex = 64*HEXDIG

   The "HSDIR_INDEX=" is an optional field that is only for version 3 which
   contains the computed index of the HsDir the descriptor was uploaded to or
   fetched from.

   The "HSAddress" key is extended to accept 56 base32 characters which is the
   format of a version 3 onion address.

   The "DescriptorID" key is extended to accept 43 base64 characters which is
   the descriptor blinded key used for the index value at the "HsDir".

   The "REPLICA=" field is not used for the "CREATED" event because v3 doesn't
   use the replica number in the descriptor ID computation.

   Because client authentication is not yet implemented, the "AuthType" field
   is always "NO_AUTH".

3.2.2. HS_DESC_CONTENT

   For this event to support version 3, new values are added but the syntax is
   unchanged:

     "650" "+" "HS_DESC_CONTENT" SP HSAddress SP DescId SP HsDir CRLF
                Descriptor CRLF "." CRLF "650" SP "OK" CRLF

     HSAddress = 16*Base32Character / 56*Base32Character / "UNKNOWN"
     DescId = 32*Base32Character / 32*Base64Character
     HsDir = LongName / "UNKNOWN"
     Descriptor = The text of the descriptor formatted as specified in
                  rend-spec-v3.txt section 2.4 or empty string on failure.

   The "HSAddress" key is extended to accept 56 base32 characters which is the
   format of a version 3 onion address.

   The "DescriptorID" key is extended to accept 32 base64 characters which is
   the descriptor blinded key used for the index value at the "HsDir".

3.2.3 CIRC and CIRC_MINOR

   These circuit events have an optional field named "REND_QUERY" which takes
   an "HSAddress". This field is extended to support v3 address:

      HSAddress = 16*Base32Character / 56*Base32Character / "UNKNOWN"

from https://gitweb.torproject.org/torspec.git/tree/proposals/284-hsv3-control-port.txt