Replies
Reply codes follow the same 3-character format as used by SMTP, with the first character defining a status, the second character defining a subsystem, and the third designating fine-grained information.
The TC protocol currently uses the following first characters:
2yz Positive Completion Reply
The command was successful; a new request can be started.
4yz Temporary Negative Completion reply
The command was unsuccessful but might be reattempted later.
5yz Permanent Negative Completion Reply
The command was unsuccessful; the client should not try exactly
that sequence of commands again.
6yz Asynchronous Reply
Sent out-of-order in response to an earlier SETEVENTS command.
The following second characters are used:
x0z Syntax
Sent in response to ill-formed or nonsensical commands.
x1z Protocol
Refers to operations of the Tor Control protocol.
x5z Tor
Refers to actual operations of Tor system.
The following codes are defined:
250 OK
251 Operation was unnecessary
[Tor has declined to perform the operation, but no harm was done.]
451 Resource exhausted
500 Syntax error: protocol
510 Unrecognized command
511 Unimplemented command
512 Syntax error in command argument
513 Unrecognized command argument
514 Authentication required
515 Bad authentication
550 Unspecified Tor error
551 Internal error
[Something went wrong inside Tor, so that the client's
request couldn't be fulfilled.]
552 Unrecognized entity
[A configuration key, a stream ID, circuit ID, event,
mentioned in the command did not actually exist.]
553 Invalid configuration value
[The client tried to set a configuration option to an
incorrect, ill-formed, or impossible value.]
554 Invalid descriptor
555 Unmanaged entity
650 Asynchronous event notification
Unless specified to have specific contents, the human-readable messages in error replies should not be relied upon to match those in this document.
Asynchronous events
These replies can be sent after a corresponding SETEVENTS command has been received. They will not be interleaved with other Reply elements, but they can appear between a command and its corresponding reply. For example, this sequence is possible:
C: SETEVENTS CIRC
S: 250 OK
C: GETCONF SOCKSPORT ORPORT
S: 650 CIRC 1000 EXTENDED moria1,moria2
S: 250-SOCKSPORT=9050
S: 250 ORPORT=0
But this sequence is disallowed:
C: SETEVENTS CIRC
S: 250 OK
C: GETCONF SOCKSPORT ORPORT
S: 250-SOCKSPORT=9050
S: 650 CIRC 1000 EXTENDED moria1,moria2
S: 250 ORPORT=0
Clients MUST tolerate more arguments in an asynchronous reply than expected, and MUST tolerate more lines in an asynchronous reply than expected. For instance, a client that expects a CIRC message like:
650 CIRC 1000 EXTENDED moria1,moria2
must tolerate:
650-CIRC 1000 EXTENDED moria1,moria2 0xBEEF
650-EXTRAMAGIC=99
650 ANONYMITY=high
If clients receives extended events (selected by USEFEATUERE EXTENDED_EVENTS in Tor 0.1.2.2-alpha..Tor-0.2.1.x, and always-on in Tor 0.2.2.x and later), then each event line as specified below may be followed by additional arguments and additional lines. Additional lines will be of the form:
"650" ("-"/" ") KEYWORD ["=" ARGUMENTS] CRLF
Additional arguments will be of the form
SP KEYWORD ["=" ( QuotedString / * NonSpDquote ) ]
Clients MUST tolerate events with arguments and keywords they do not recognize, and SHOULD process those events as if any unrecognized arguments and keywords were not present.
Clients SHOULD NOT depend on the order of keyword=value arguments, and SHOULD NOT depend on there being no new keyword=value arguments appearing between existing keyword=value arguments, though as of this writing (Jun 2011) some do. Thus, extensions to this protocol should add new keywords only after the existing keywords, until all controllers have been fixed. At some point this "SHOULD NOT" might become a "MUST NOT".
Circuit status changed
The syntax is:
"650" SP "CIRC" SP CircuitID SP CircStatus [SP Path]
[SP "BUILD_FLAGS=" BuildFlags] [SP "PURPOSE=" Purpose]
[SP "HS_STATE=" HSState] [SP "REND_QUERY=" HSAddress]
[SP "TIME_CREATED=" TimeCreated]
[SP "REASON=" Reason [SP "REMOTE_REASON=" Reason]]
[SP "SOCKS_USERNAME=" EscapedUsername]
[SP "SOCKS_PASSWORD=" EscapedPassword]
[SP "HS_POW=" HSPoW ]
CRLF
CircStatus =
"LAUNCHED" / ; circuit ID assigned to new circuit
"BUILT" / ; all hops finished, can now accept streams
"GUARD_WAIT" / ; all hops finished, waiting to see if a
; circuit with a better guard will be usable.
"EXTENDED" / ; one more hop has been completed
"FAILED" / ; circuit closed (was not built)
"CLOSED" ; circuit closed (was built)
Path = LongName *("," LongName)
; In Tor versions 0.1.2.2-alpha through 0.2.2.1-alpha with feature
; VERBOSE_NAMES turned off and before version 0.1.2.2-alpha, Path
; is as follows:
; Path = ServerID *("," ServerID)
BuildFlags = BuildFlag *("," BuildFlag)
BuildFlag = "ONEHOP_TUNNEL" / "IS_INTERNAL" /
"NEED_CAPACITY" / "NEED_UPTIME"
Purpose = "GENERAL" / "HS_CLIENT_INTRO" / "HS_CLIENT_REND" /
"HS_SERVICE_INTRO" / "HS_SERVICE_REND" / "TESTING" /
"CONTROLLER" / "MEASURE_TIMEOUT" /
"HS_VANGUARDS" / "PATH_BIAS_TESTING" /
"CIRCUIT_PADDING"
HSState = "HSCI_CONNECTING" / "HSCI_INTRO_SENT" / "HSCI_DONE" /
"HSCR_CONNECTING" / "HSCR_ESTABLISHED_IDLE" /
"HSCR_ESTABLISHED_WAITING" / "HSCR_JOINED" /
"HSSI_CONNECTING" / "HSSI_ESTABLISHED" /
"HSSR_CONNECTING" / "HSSR_JOINED"
HSPoWType = "v1"
HSPoWEffort = 1*DIGIT
HSPoW = HSPoWType "," HSPoWEffort
EscapedUsername = QuotedString
EscapedPassword = QuotedString
HSAddress = 16*Base32Character / 56*Base32Character
Base32Character = ALPHA / "2" / "3" / "4" / "5" / "6" / "7"
TimeCreated = ISOTime2Frac
Seconds = 1*DIGIT
Microseconds = 1*DIGIT
Reason = "NONE" / "TORPROTOCOL" / "INTERNAL" / "REQUESTED" /
"HIBERNATING" / "RESOURCELIMIT" / "CONNECTFAILED" /
"OR_IDENTITY" / "OR_CONN_CLOSED" / "TIMEOUT" /
"FINISHED" / "DESTROYED" / "NOPATH" / "NOSUCHSERVICE" /
"MEASUREMENT_EXPIRED"
The path is provided only when the circuit has been extended at least one
hop.
The "BUILD_FLAGS" field is provided only in versions 0.2.3.11-alpha
and later. Clients MUST accept build flags not listed above.
Build flags are defined as follows:
ONEHOP_TUNNEL (one-hop circuit, used for tunneled directory conns)
IS_INTERNAL (internal circuit, not to be used for exiting streams)
NEED_CAPACITY (this circuit must use only high-capacity nodes)
NEED_UPTIME (this circuit must use only high-uptime nodes)
The "PURPOSE" field is provided only in versions 0.2.1.6-alpha and
later, and only if extended events are enabled (see 3.19). Clients
MUST accept purposes not listed above. Purposes are defined as
follows:
GENERAL (circuit for AP and/or directory request streams)
HS_CLIENT_INTRO (HS client-side introduction-point circuit)
HS_CLIENT_REND (HS client-side rendezvous circuit; carries AP streams)
HS_SERVICE_INTRO (HS service-side introduction-point circuit)
HS_SERVICE_REND (HS service-side rendezvous circuit)
TESTING (reachability-testing circuit; carries no traffic)
CONTROLLER (circuit built by a controller)
MEASURE_TIMEOUT (circuit being kept around to see how long it takes)
HS_VANGUARDS (circuit created ahead of time when using
HS vanguards, and later repurposed as needed)
PATH_BIAS_TESTING (circuit used to probe whether our circuits are
being deliberately closed by an attacker)
CIRCUIT_PADDING (circuit that is being held open to disguise its
true close time)
The "HS_STATE" field is provided only for hidden-service circuits,
and only in versions 0.2.3.11-alpha and later. Clients MUST accept
hidden-service circuit states not listed above. Hidden-service
circuit states are defined as follows:
HSCI_* (client-side introduction-point circuit states)
HSCI_CONNECTING (connecting to intro point)
HSCI_INTRO_SENT (sent INTRODUCE1; waiting for reply from IP)
HSCI_DONE (received reply from IP relay; closing)
HSCR_* (client-side rendezvous-point circuit states)
HSCR_CONNECTING (connecting to or waiting for reply from RP)
HSCR_ESTABLISHED_IDLE (established RP; waiting for introduction)
HSCR_ESTABLISHED_WAITING (introduction sent to HS; waiting for rend)
HSCR_JOINED (connected to HS)
HSSI_* (service-side introduction-point circuit states)
HSSI_CONNECTING (connecting to intro point)
HSSI_ESTABLISHED (established intro point)
HSSR_* (service-side rendezvous-point circuit states)
HSSR_CONNECTING (connecting to client's rend point)
HSSR_JOINED (connected to client's RP circuit)
The "SOCKS_USERNAME" and "SOCKS_PASSWORD" fields indicate the credentials
that were used by a SOCKS client to connect to Tor's SOCKS port and
initiate this circuit. (Streams for SOCKS clients connected with different
usernames and/or passwords are isolated on separate circuits if the
IsolateSOCKSAuth flag is active; see Proposal 171.) [Added in Tor
0.4.3.1-alpha.]
The "REND_QUERY" field is provided only for hidden-service-related
circuits, and only in versions 0.2.3.11-alpha and later. Clients
MUST accept hidden service addresses in formats other than that
specified above. [Added in Tor 0.4.3.1-alpha.]
The "TIME_CREATED" field is provided only in versions 0.2.3.11-alpha and
later. TIME_CREATED is the time at which the circuit was created or
cannibalized. [Added in Tor 0.4.3.1-alpha.]
The "REASON" field is provided only for FAILED and CLOSED events, and only
if extended events are enabled (see 3.19). Clients MUST accept reasons
not listed above. [Added in Tor 0.4.3.1-alpha.] Reasons are as given in
tor-spec.txt, except for:
NOPATH (Not enough nodes to make circuit)
MEASUREMENT_EXPIRED (As "TIMEOUT", except that we had left the circuit
open for measurement purposes to see how long it
would take to finish.)
IP_NOW_REDUNDANT (Closing a circuit to an introduction point that
has become redundant, since some other circuit
opened in parallel with it has succeeded.)
The "REMOTE_REASON" field is provided only when we receive a DESTROY cell or
RELAY_TRUNCATE message, and only if extended events are enabled. It contains the
actual reason given by the remote OR for closing the circuit. Clients MUST
accept reasons not listed above. Reasons are as listed in tor-spec.txt.
[Added in Tor 0.4.3.1-alpha.]
Stream status changed
The syntax is:
"650" SP "STREAM" SP StreamID SP StreamStatus SP CircuitID SP Target
[SP "REASON=" Reason [ SP "REMOTE_REASON=" Reason ]]
[SP "SOURCE=" Source] [ SP "SOURCE_ADDR=" Address ":" Port ]
[SP "PURPOSE=" Purpose] [SP "SOCKS_USERNAME=" EscapedUsername]
[SP "SOCKS_PASSWORD=" EscapedPassword]
[SP "CLIENT_PROTOCOL=" ClientProtocol] [SP "NYM_EPOCH=" NymEpoch]
[SP "SESSION_GROUP=" SessionGroup] [SP "ISO_FIELDS=" IsoFields]
CRLF
StreamStatus =
"NEW" / ; New request to connect
"NEWRESOLVE" / ; New request to resolve an address
"REMAP" / ; Address re-mapped to another
"SENTCONNECT" / ; Sent a connect message along a circuit
"SENTRESOLVE" / ; Sent a resolve message along a circuit
"SUCCEEDED" / ; Received a reply; stream established
"FAILED" / ; Stream failed and not retriable
"CLOSED" / ; Stream closed
"DETACHED" / ; Detached from circuit; still retriable
"CONTROLLER_WAIT" ; Waiting for controller to use ATTACHSTREAM
; (new in 0.4.5.1-alpha)
"XOFF_SENT" ; XOFF has been sent for this stream
; (new in 0.4.7.5-alpha)
"XOFF_RECV" ; XOFF has been received for this stream
; (new in 0.4.7.5-alpha)
"XON_SENT" ; XON has been sent for this stream
; (new in 0.4.7.5-alpha)
"XON_RECV" ; XON has been received for this stream
; (new in 0.4.7.5-alpha)
Target = TargetAddress ":" Port
Port = an integer from 0 to 65535 inclusive
TargetAddress = Address / "(Tor_internal)"
EscapedUsername = QuotedString
EscapedPassword = QuotedString
ClientProtocol =
"SOCKS4" /
"SOCKS5" /
"TRANS" /
"NATD" /
"DNS" /
"HTTPCONNECT" /
"UNKNOWN"
NymEpoch = a nonnegative integer
SessionGroup = an integer
IsoFields = a comma-separated list of IsoField values
IsoField =
"CLIENTADDR" /
"CLIENTPORT" /
"DESTADDR" /
"DESTPORT" /
the name of a field that is valid for STREAM events
The circuit ID designates which circuit this stream is attached to. If the stream is unattached, the circuit ID "0" is given. The target indicates the address which the stream is meant to resolve or connect to; it can be "(Tor_internal)" for a virtual stream created by the Tor program to talk to itself.
Reason = "MISC" / "RESOLVEFAILED" / "CONNECTREFUSED" /
"EXITPOLICY" / "DESTROY" / "DONE" / "TIMEOUT" /
"NOROUTE" / "HIBERNATING" / "INTERNAL"/ "RESOURCELIMIT" /
"CONNRESET" / "TORPROTOCOL" / "NOTDIRECTORY" / "END" /
"PRIVATE_ADDR"
The "REASON" field is provided only for FAILED, CLOSED, and DETACHED
events, and only if extended events are enabled (see 3.19). Clients MUST
accept reasons not listed above. Reasons are as given in tor-spec.txt,
except for:
END (We received a RELAY_END message from the other side of this
stream.)
PRIVATE_ADDR (The client tried to connect to a private address like
127.0.0.1 or 10.0.0.1 over Tor.)
[XXXX document more. -NM]
The "REMOTE_REASON" field is provided only when we receive a RELAY_END
message, and only if extended events are enabled. It contains the actual
reason given by the remote OR for closing the stream. Clients MUST accept
reasons not listed above. Reasons are as listed in tor-spec.txt.
"REMAP" events include a Source if extended events are enabled:
Source = "CACHE" / "EXIT"
Clients MUST accept sources not listed above. "CACHE" is given if
the Tor client decided to remap the address because of a cached
answer, and "EXIT" is given if the remote node we queried gave us
the new address as a response.
The "SOURCE_ADDR" field is included with NEW and NEWRESOLVE events if
extended events are enabled. It indicates the address and port
that requested the connection, and can be (e.g.) used to look up the
requesting program.
Purpose = "DIR_FETCH" / "DIR_UPLOAD" / "DNS_REQUEST" /
"USER" / "DIRPORT_TEST"
The "PURPOSE" field is provided only for NEW and NEWRESOLVE events, and
only if extended events are enabled (see 3.19). Clients MUST accept
purposes not listed above. The purposes above are defined as:
"DIR_FETCH" -- This stream is generated internally to Tor for
fetching directory information.
"DIR_UPLOAD" -- An internal stream for uploading information to
a directory authority.
"DIRPORT_TEST" -- A stream we're using to test our own directory
port to make sure it's reachable.
"DNS_REQUEST" -- A user-initiated DNS request.
"USER" -- This stream is handling user traffic, OR it's internal
to Tor, but it doesn't match one of the purposes above.
The "SOCKS_USERNAME" and "SOCKS_PASSWORD" fields indicate the credentials
that were used by a SOCKS client to connect to Tor's SOCKS port and
initiate this stream. (Streams for SOCKS clients connected with different
usernames and/or passwords are isolated on separate circuits if the
IsolateSOCKSAuth flag is active; see Proposal 171.)
The "CLIENT_PROTOCOL" field indicates the protocol that was used by a client
to initiate this stream. (Streams for clients connected with different
protocols are isolated on separate circuits if the IsolateClientProtocol
flag is active.) Controllers MUST tolerate unrecognized client protocols.
The "NYM_EPOCH" field indicates the nym epoch that was active when a client
initiated this stream. The epoch increments when the NEWNYM signal is
received. (Streams with different nym epochs are isolated on separate
circuits.)
The "SESSION_GROUP" field indicates the session group of the listener port
that a client used to initiate this stream. By default, the session group is
different for each listener port, but this can be overridden for a listener
via the "SessionGroup" option in torrc. (Streams with different session
groups are isolated on separate circuits.)
The "ISO_FIELDS" field indicates the set of STREAM event fields for which
stream isolation is enabled for the listener port that a client used to
initiate this stream. The special values "CLIENTADDR", "CLIENTPORT",
"DESTADDR", and "DESTPORT", if their correspondingly named fields are not
present, refer to the Address and Port components of the "SOURCE_ADDR" and
Target fields.
OR Connection status changed
The syntax is:
"650" SP "ORCONN" SP (LongName / Target) SP ORStatus [ SP "REASON="
Reason ] [ SP "NCIRCS=" NumCircuits ] [ SP "ID=" ConnID ] CRLF
ORStatus = "NEW" / "LAUNCHED" / "CONNECTED" / "FAILED" / "CLOSED"
; In Tor versions 0.1.2.2-alpha through 0.2.2.1-alpha with feature
; VERBOSE_NAMES turned off and before version 0.1.2.2-alpha, OR
; Connection is as follows:
"650" SP "ORCONN" SP (ServerID / Target) SP ORStatus [ SP "REASON="
Reason ] [ SP "NCIRCS=" NumCircuits ] CRLF
NEW is for incoming connections, and LAUNCHED is for outgoing connections. CONNECTED means the TLS handshake has finished (in either direction). FAILED means a connection is being closed that hasn't finished its handshake, and CLOSED is for connections that have handshaked.
A LongName or ServerID is specified unless it's a NEW connection, in which case we don't know what server it is yet, so we use Address:Port.
If extended events are enabled (see 3.19), optional reason and circuit counting information is provided for CLOSED and FAILED events.
Reason = "MISC" / "DONE" / "CONNECTREFUSED" /
"IDENTITY" / "CONNECTRESET" / "TIMEOUT" / "NOROUTE" /
"IOERROR" / "RESOURCELIMIT" / "PT_MISSING"
NumCircuits counts both established and pending circuits.
The ORStatus values are as follows:
NEW -- We have received a new incoming OR connection, and are starting
the server-side handshake.
LAUNCHED -- We have launched a new outgoing OR connection, and are
starting the client-side handshake.
CONNECTED -- The OR connection has been connected and the handshake is
done.
FAILED -- Our attempt to open the OR connection failed.
CLOSED -- The OR connection closed in an unremarkable way.
The Reason values for closed/failed OR connections are:
DONE -- The OR connection has shut down cleanly.
CONNECTREFUSED -- We got an ECONNREFUSED while connecting to the target
OR.
IDENTITY -- We connected to the OR, but found that its identity was
not what we expected.
CONNECTRESET -- We got an ECONNRESET or similar IO error from the
connection with the OR.
TIMEOUT -- We got an ETIMEOUT or similar IO error from the connection
with the OR, or we're closing the connection for being idle for too
long.
NOROUTE -- We got an ENOTCONN, ENETUNREACH, ENETDOWN, EHOSTUNREACH, or
similar error while connecting to the OR.
IOERROR -- We got some other IO error on our connection to the OR.
RESOURCELIMIT -- We don't have enough operating system resources (file
descriptors, buffers, etc) to connect to the OR.
PT_MISSING -- No pluggable transport was available.
MISC -- The OR connection closed for some other reason.
[First added ID parameter in 0.2.5.2-alpha]
Bandwidth used in the last second
The syntax is:
"650" SP "BW" SP BytesRead SP BytesWritten *(SP Type "=" Num) CRLF
BytesRead = 1*DIGIT
BytesWritten = 1*DIGIT
Type = "DIR" / "OR" / "EXIT" / "APP" / ...
Num = 1*DIGIT
BytesRead and BytesWritten are the totals. [In a future Tor version, we may also include a breakdown of the connection types that used bandwidth this second (not implemented yet).]
Log messages
The syntax is:
"650" SP Severity SP ReplyText CRLF
or
"650+" Severity CRLF Data 650 SP "OK" CRLF
Severity = "DEBUG" / "INFO" / "NOTICE" / "WARN"/ "ERR"
Some low-level logs may be sent from signal handlers, so their destination logs must be signal-safe. These low-level logs include backtraces, logging function errors, and errors in code called by logging functions. Signal-safe logs are never sent as control port log events.
Control port message trace debug logs are never sent as control port log events, to avoid modifying control output when debugging.
New descriptors available
This event is generated when new router descriptors (not microdescs or extrainfos or anything else) are received.
Syntax:
"650" SP "NEWDESC" 1*(SP LongName) CRLF
; In Tor versions 0.1.2.2-alpha through 0.2.2.1-alpha with feature
; VERBOSE_NAMES turned off and before version 0.1.2.2-alpha, it
; is as follows:
"650" SP "NEWDESC" 1*(SP ServerID) CRLF
New Address mapping
These events are generated when a new address mapping is entered in Tor's address map cache, or when the answer for a RESOLVE command is found. Entries can be created by a successful or failed DNS lookup, a successful or failed connection attempt, a RESOLVE command, a MAPADDRESS command, the AutomapHostsOnResolve feature, or the TrackHostExits feature.
Syntax:
"650" SP "ADDRMAP" SP Address SP NewAddress SP Expiry
[SP "error=" ErrorCode] [SP "EXPIRES=" UTCExpiry] [SP "CACHED=" Cached]
[SP "STREAMID=" StreamId] CRLF
NewAddress = Address / "<error>"
Expiry = DQUOTE ISOTime DQUOTE / "NEVER"
ErrorCode = "yes" / "internal" / "Unable to launch resolve request"
UTCExpiry = DQUOTE IsoTime DQUOTE
Cached = DQUOTE "YES" DQUOTE / DQUOTE "NO" DQUOTE
StreamId = DQUOTE StreamId DQUOTE
Error and UTCExpiry are only provided if extended events are enabled. The values for Error are mostly useless. Future values will be chosen to match 1*(ALNUM / "_"); the "Unable to launch resolve request" value is a bug in Tor before 0.2.4.7-alpha.
Expiry is expressed as the local time (rather than UTC). This is a bug, left in for backward compatibility; new code should look at UTCExpiry instead. (If Expiry is "NEVER", UTCExpiry is omitted.)
Cached indicates whether the mapping will be stored until it expires, or if it is just a notification in response to a RESOLVE command.
StreamId is the global stream identifier of the stream or circuit from which the address was resolved.
Descriptors uploaded to us in our role as authoritative dirserver
[NOTE: This feature was removed in Tor 0.3.2.1-alpha.]
Tor generates this event when it's a directory authority, and somebody has just uploaded a server descriptor.
Syntax:
"650" "+" "AUTHDIR_NEWDESCS" CRLF Action CRLF Message CRLF
Descriptor CRLF "." CRLF "650" SP "OK" CRLF
Action = "ACCEPTED" / "DROPPED" / "REJECTED"
Message = Text
The Descriptor field is the text of the server descriptor; the Action field is "ACCEPTED" if we're accepting the descriptor as the new best valid descriptor for its router, "REJECTED" if we aren't taking the descriptor and we're complaining to the uploading relay about it, and "DROPPED" if we decide to drop the descriptor without complaining. The Message field is a human-readable string explaining why we chose the Action. (It doesn't contain newlines.)
Our descriptor changed
Syntax:
"650" SP "DESCCHANGED" CRLF
[First added in 0.1.2.2-alpha.]
Status events
Status events (STATUS_GENERAL, STATUS_CLIENT, and STATUS_SERVER) are sent based on occurrences in the Tor process pertaining to the general state of the program. Generally, they correspond to log messages of severity Notice or higher. They differ from log messages in that their format is a specified interface.
Syntax:
"650" SP StatusType SP StatusSeverity SP StatusAction
[SP StatusArguments] CRLF
StatusType = "STATUS_GENERAL" / "STATUS_CLIENT" / "STATUS_SERVER"
StatusSeverity = "NOTICE" / "WARN" / "ERR"
StatusAction = 1*ALPHA
StatusArguments = StatusArgument *(SP StatusArgument)
StatusArgument = StatusKeyword '=' StatusValue
StatusKeyword = 1*(ALNUM / "_")
StatusValue = 1*(ALNUM / '_') / QuotedString
StatusAction is a string, and StatusArguments is a series of
keyword=value pairs on the same line. Values may be space-terminated
strings, or quoted strings.
These events are always produced with EXTENDED_EVENTS and
VERBOSE_NAMES; see the explanations in the USEFEATURE section
for details.
Controllers MUST tolerate unrecognized actions, MUST tolerate
unrecognized arguments, MUST tolerate missing arguments, and MUST
tolerate arguments that arrive in any order.
Each event description below is accompanied by a recommendation for
controllers. These recommendations are suggestions only; no controller
is required to implement them.
Compatibility note: versions of Tor before 0.2.0.22-rc incorrectly generated "STATUS_SERVER" as "STATUS_SEVER". To be compatible with those versions, tools should accept both.
Actions for STATUS_GENERAL events can be as follows:
CLOCK_JUMPED
"TIME=NUM"
Tor spent enough time without CPU cycles that it has closed all
its circuits and will establish them anew. This typically
happens when a laptop goes to sleep and then wakes up again. It
also happens when the system is swapping so heavily that Tor is
starving. The "time" argument specifies the number of seconds Tor
thinks it was unconscious for (or alternatively, the number of
seconds it went back in time).
This status event is sent as NOTICE severity normally, but WARN
severity if Tor is acting as a server currently.
{Recommendation for controller: ignore it, since we don't really
know what the user should do anyway. Hm.}
DANGEROUS_VERSION
"CURRENT=version"
"REASON=NEW/OBSOLETE/UNRECOMMENDED"
"RECOMMENDED=\"version, version, ...\""
Tor has found that directory servers don't recommend its version of
the Tor software. RECOMMENDED is a comma-and-space-separated string
of Tor versions that are recommended. REASON is NEW if this version
of Tor is newer than any recommended version, OBSOLETE if
this version of Tor is older than any recommended version, and
UNRECOMMENDED if some recommended versions of Tor are newer and
some are older than this version. (The "OBSOLETE" reason was called
"OLD" from Tor 0.1.2.3-alpha up to and including 0.2.0.12-alpha.)
{Controllers may want to suggest that the user upgrade OLD or
UNRECOMMENDED versions. NEW versions may be known-insecure, or may
simply be development versions.}
TOO_MANY_CONNECTIONS
"CURRENT=NUM"
Tor has reached its ulimit -n or whatever the native limit is on file
descriptors or sockets. CURRENT is the number of sockets Tor
currently has open. The user should really do something about
this. The "current" argument shows the number of connections currently
open.
{Controllers may recommend that the user increase the limit, or
increase it for them. Recommendations should be phrased in an
OS-appropriate way and automated when possible.}
BUG
"REASON=STRING"
Tor has encountered a situation that its developers never expected,
and the developers would like to learn that it happened. Perhaps
the controller can explain this to the user and encourage her to
file a bug report?
{Controllers should log bugs, but shouldn't annoy the user in case a
bug appears frequently.}
CLOCK_SKEW
SKEW="+" / "-" SECONDS
MIN_SKEW="+" / "-" SECONDS.
SOURCE="DIRSERV:" IP ":" Port /
"NETWORKSTATUS:" IP ":" Port /
"OR:" IP ":" Port /
"CONSENSUS"
If "SKEW" is present, it's an estimate of how far we are from the
time declared in the source. (In other words, if we're an hour in
the past, the value is -3600.) "MIN_SKEW" is present, it's a lower
bound. If the source is a DIRSERV, we got the current time from a
connection to a dirserver. If the source is a NETWORKSTATUS, we
decided we're skewed because we got a v2 networkstatus from far in
the future. If the source is OR, the skew comes from a NETINFO
cell from a connection to another relay. If the source is
CONSENSUS, we decided we're skewed because we got a networkstatus
consensus from the future.
{Tor should send this message to controllers when it thinks the
skew is so high that it will interfere with proper Tor operation.
Controllers shouldn't blindly adjust the clock, since the more
accurate source of skew info (DIRSERV) is currently
unauthenticated.}
BAD_LIBEVENT
"METHOD=" libevent method
"VERSION=" libevent version
"BADNESS=" "BROKEN" / "BUGGY" / "SLOW"
"RECOVERED=" "NO" / "YES"
Tor knows about bugs in using the configured event method in this
version of libevent. "BROKEN" libevents won't work at all;
"BUGGY" libevents might work okay; "SLOW" libevents will work
fine, but not quickly. If "RECOVERED" is YES, Tor managed to
switch to a more reliable (but probably slower!) libevent method.
{Controllers may want to warn the user if this event occurs, though
generally it's the fault of whoever built the Tor binary and there's
not much the user can do besides upgrade libevent or upgrade the
binary.}
DIR_ALL_UNREACHABLE
Tor believes that none of the known directory servers are
reachable -- this is most likely because the local network is
down or otherwise not working, and might help to explain for the
user why Tor appears to be broken.
{Controllers may want to warn the user if this event occurs; further
action is generally not possible.}
Actions for STATUS_CLIENT events can be as follows:
BOOTSTRAP
"PROGRESS=" num
"TAG=" Keyword
"SUMMARY=" String
["WARNING=" String]
["REASON=" Keyword]
["COUNT=" num]
["RECOMMENDATION=" Keyword]
["HOST=" QuotedString]
["HOSTADDR=" QuotedString]
Tor has made some progress at establishing a connection to the
Tor network, fetching directory information, or making its first
circuit; or it has encountered a problem while bootstrapping. This
status event is especially useful for users with slow connections
or with connectivity problems.
"Progress" gives a number between 0 and 100 for how far through
the bootstrapping process we are. "Summary" is a string that can
be displayed to the user to describe the *next* task that Tor
will tackle, i.e., the task it is working on after sending the
status event. "Tag" is a string that controllers can use to
recognize bootstrap phases, if they want to do something smarter
than just blindly displaying the summary string; see Section 5
for the current tags that Tor issues.
The StatusSeverity describes whether this is a normal bootstrap
phase (severity notice) or an indication of a bootstrapping
problem (severity warn).
For bootstrap problems, we include the same progress, tag, and
summary values as we would for a normal bootstrap event, but we
also include "warning", "reason", "count", and "recommendation"
key/value combos. The "count" number tells how many bootstrap
problems there have been so far at this phase. The "reason"
string lists one of the reasons allowed in the ORCONN event. The
"warning" argument string with any hints Tor has to offer about
why it's having troubles bootstrapping.
The "reason" values are long-term-stable controller-facing tags to
identify particular issues in a bootstrapping step. The warning
strings, on the other hand, are human-readable. Controllers
SHOULD NOT rely on the format of any warning string. Currently
the possible values for "recommendation" are either "ignore" or
"warn" -- if ignore, the controller can accumulate the string in
a pile of problems to show the user if the user asks; if warn,
the controller should alert the user that Tor is pretty sure
there's a bootstrapping problem.
The "host" value is the identity digest (in hex) of the node we're
trying to connect to; the "hostaddr" is an address:port combination,
where 'address' is an ipv4 or ipv6 address.
Currently Tor uses recommendation=ignore for the first
nine bootstrap problem reports for a given phase, and then
uses recommendation=warn for subsequent problems at that
phase. Hopefully this is a good balance between tolerating
occasional errors and reporting serious problems quickly.
ENOUGH_DIR_INFO
Tor now knows enough network-status documents and enough server
descriptors that it's going to start trying to build circuits now.
[Newer versions of Tor (0.2.6.2-alpha and later):
If the consensus contains Exits (the typical case), Tor will build
both exit and internal circuits. If not, Tor will only build internal
circuits.]
{Controllers may want to use this event to decide when to indicate
progress to their users, but should not interrupt the user's browsing
to tell them so.}
NOT_ENOUGH_DIR_INFO
We discarded expired statuses and server descriptors to fall
below the desired threshold of directory information. We won't
try to build any circuits until ENOUGH_DIR_INFO occurs again.
{Controllers may want to use this event to decide when to indicate
progress to their users, but should not interrupt the user's browsing
to tell them so.}
CIRCUIT_ESTABLISHED
Tor is able to establish circuits for client use. This event will
only be sent if we just built a circuit that changed our mind --
that is, prior to this event we didn't know whether we could
establish circuits.
{Suggested use: controllers can notify their users that Tor is
ready for use as a client once they see this status event. [Perhaps
controllers should also have a timeout if too much time passes and
this event hasn't arrived, to give tips on how to troubleshoot.
On the other hand, hopefully Tor will send further status events
if it can identify the problem.]}
CIRCUIT_NOT_ESTABLISHED
"REASON=" "EXTERNAL_ADDRESS" / "DIR_ALL_UNREACHABLE" / "CLOCK_JUMPED"
We are no longer confident that we can build circuits. The "reason"
keyword provides an explanation: which other status event type caused
our lack of confidence.
{Controllers may want to use this event to decide when to indicate
progress to their users, but should not interrupt the user's browsing
to do so.}
[Note: only REASON=CLOCK_JUMPED is implemented currently.]
CONSENSUS_ARRIVED
Tor has received and validated a new consensus networkstatus.
(This event can be delayed a little while after the consensus
is received, if Tor needs to fetch certificates.)
DANGEROUS_PORT
"PORT=" port
"RESULT=" "REJECT" / "WARN"
A stream was initiated to a port that's commonly used for
vulnerable-plaintext protocols. If the Result is "reject", we
refused the connection; whereas if it's "warn", we allowed it.
{Controllers should warn their users when this occurs, unless they
happen to know that the application using Tor is in fact doing so
correctly (e.g., because it is part of a distributed bundle). They
might also want some sort of interface to let the user configure
their RejectPlaintextPorts and WarnPlaintextPorts config options.}
DANGEROUS_SOCKS
"PROTOCOL=" "SOCKS4" / "SOCKS5"
"ADDRESS=" IP:port
A connection was made to Tor's SOCKS port using one of the SOCKS
approaches that doesn't support hostnames -- only raw IP addresses.
If the client application got this address from gethostbyname(),
it may be leaking target addresses via DNS.
{Controllers should warn their users when this occurs, unless they
happen to know that the application using Tor is in fact doing so
correctly (e.g., because it is part of a distributed bundle).}
SOCKS_UNKNOWN_PROTOCOL
"DATA=string"
A connection was made to Tor's SOCKS port that tried to use it
for something other than the SOCKS protocol. Perhaps the user is
using Tor as an HTTP proxy? The DATA is the first few characters
sent to Tor on the SOCKS port.
{Controllers may want to warn their users when this occurs: it
indicates a misconfigured application.}
SOCKS_BAD_HOSTNAME
"HOSTNAME=QuotedString"
Some application gave us a funny-looking hostname. Perhaps
it is broken? In any case it won't work with Tor and the user
should know.
{Controllers may want to warn their users when this occurs: it
usually indicates a misconfigured application.}
Actions for STATUS_SERVER can be as follows:
EXTERNAL_ADDRESS
"ADDRESS=IP"
"HOSTNAME=NAME"
"METHOD=CONFIGURED/CONFIGURED_ORPORT/DIRSERV/RESOLVED/
INTERFACE/GETHOSTNAME"
Our best idea for our externally visible IP has changed to 'IP'. If
'HOSTNAME' is present, we got the new IP by resolving 'NAME'. If the
method is 'CONFIGURED', the IP was given verbatim as the Address
configuration option. If the method is 'CONFIGURED_ORPORT', the IP was
given verbatim in the ORPort configuration option. If the method is
'RESOLVED', we resolved the Address configuration option to get the IP.
If the method is 'GETHOSTNAME', we resolved our hostname to get the IP.
If the method is 'INTERFACE', we got the address of one of our network
interfaces to get the IP. If the method is 'DIRSERV', a directory
server told us a guess for what our IP might be.
{Controllers may want to record this info and display it to the user.}
CHECKING_REACHABILITY
"ORADDRESS=IP:port"
"DIRADDRESS=IP:port"
We're going to start testing the reachability of our external OR port
or directory port.
{This event could affect the controller's idea of server status, but
the controller should not interrupt the user to tell them so.}
REACHABILITY_SUCCEEDED
"ORADDRESS=IP:port"
"DIRADDRESS=IP:port"
We successfully verified the reachability of our external OR port or
directory port (depending on which of ORADDRESS or DIRADDRESS is
given.)
{This event could affect the controller's idea of server status, but
the controller should not interrupt the user to tell them so.}
GOOD_SERVER_DESCRIPTOR
We successfully uploaded our server descriptor to at least one
of the directory authorities, with no complaints.
{Originally, the goal of this event was to declare "every authority
has accepted the descriptor, so there will be no complaints
about it." But since some authorities might be offline, it's
harder to get certainty than we had thought. As such, this event
is equivalent to ACCEPTED_SERVER_DESCRIPTOR below. Controllers
should just look at ACCEPTED_SERVER_DESCRIPTOR and should ignore
this event for now.}
SERVER_DESCRIPTOR_STATUS
"STATUS=" "LISTED" / "UNLISTED"
We just got a new networkstatus consensus, and whether we're in
it or not in it has changed. Specifically, status is "listed"
if we're listed in it but previous to this point we didn't know
we were listed in a consensus; and status is "unlisted" if we
thought we should have been listed in it (e.g. we were listed in
the last one), but we're not.
{Moving from listed to unlisted is not necessarily cause for
alarm. The relay might have failed a few reachability tests,
or the Internet might have had some routing problems. So this
feature is mainly to let relay operators know when their relay
has successfully been listed in the consensus.}
[Not implemented yet. We should do this in 0.2.2.x. -RD]
NAMESERVER_STATUS
"NS=addr"
"STATUS=" "UP" / "DOWN"
"ERR=" message
One of our nameservers has changed status.
{This event could affect the controller's idea of server status, but
the controller should not interrupt the user to tell them so.}
NAMESERVER_ALL_DOWN
All of our nameservers have gone down.
{This is a problem; if it happens often without the nameservers
coming up again, the user needs to configure more or better
nameservers.}
DNS_HIJACKED
Our DNS provider is providing an address when it should be saying
"NOTFOUND"; Tor will treat the address as a synonym for "NOTFOUND".
{This is an annoyance; controllers may want to tell admins that their
DNS provider is not to be trusted.}
DNS_USELESS
Our DNS provider is giving a hijacked address instead of well-known
websites; Tor will not try to be an exit node.
{Controllers could warn the admin if the relay is running as an
exit node: the admin needs to configure a good DNS server.
Alternatively, this happens a lot in some restrictive environments
(hotels, universities, coffeeshops) when the user hasn't registered.}
BAD_SERVER_DESCRIPTOR
"DIRAUTH=addr:port"
"REASON=string"
A directory authority rejected our descriptor. Possible reasons
include malformed descriptors, incorrect keys, highly skewed clocks,
and so on.
{Controllers should warn the admin, and try to cope if they can.}
ACCEPTED_SERVER_DESCRIPTOR
"DIRAUTH=addr:port"
A single directory authority accepted our descriptor.
// actually notice
{This event could affect the controller's idea of server status, but
the controller should not interrupt the user to tell them so.}
REACHABILITY_FAILED
"ORADDRESS=IP:port"
"DIRADDRESS=IP:port"
We failed to connect to our external OR port or directory port
successfully.
{This event could affect the controller's idea of server status. The
controller should warn the admin and suggest reasonable steps to take.}
HIBERNATION_STATUS
"STATUS=" "AWAKE" | "SOFT" | "HARD"
Our bandwidth based accounting status has changed, and we are now
relaying traffic/rejecting new connections/hibernating.
{This event could affect the controller's idea of server status. The
controller MAY inform the admin, though presumably the accounting was
explicitly enabled for a reason.}
[This event was added in tor 0.2.9.0-alpha.]
Our set of guard nodes has changed
Syntax:
"650" SP "GUARD" SP Type SP Name SP Status ... CRLF
Type = "ENTRY"
Name = ServerSpec
(Identifies the guard affected)
Status = "NEW" | "UP" | "DOWN" | "BAD" | "GOOD" | "DROPPED"
The ENTRY type indicates a guard used for connections to the Tor network.
The Status values are:
"NEW" -- This node was not previously used as a guard; now we have
picked it as one.
"DROPPED" -- This node is one we previously picked as a guard; we
no longer consider it to be a member of our guard list.
"UP" -- The guard now seems to be reachable.
"DOWN" -- The guard now seems to be unreachable.
"BAD" -- Because of flags set in the consensus and/or values in the
configuration, this node is now unusable as a guard.
"BAD_L2" -- This layer2 guard has expired or got removed from the
consensus. This node is removed from the layer2 guard set.
"GOOD" -- Because of flags set in the consensus and/or values in the
configuration, this node is now usable as a guard.
Controllers must accept unrecognized types and unrecognized statuses.
Network status has changed
Syntax:
"650" "+" "NS" CRLF 1*NetworkStatus "." CRLF "650" SP "OK" CRLF
The event is used whenever our local view of a relay status changes. This happens when we get a new v3 consensus (in which case the entries we see are a duplicate of what we see in the NEWCONSENSUS event, below), but it also happens when we decide to mark a relay as up or down in our local status, for example based on connection attempts.
[First added in 0.1.2.3-alpha]
Bandwidth used on an application stream
The syntax is:
"650" SP "STREAM_BW" SP StreamID SP BytesWritten SP BytesRead SP
Time CRLF
BytesWritten = 1*DIGIT
BytesRead = 1*DIGIT
Time = ISOTime2Frac
BytesWritten and BytesRead are the number of bytes written and read by the application since the last STREAM_BW event on this stream.
Note that from Tor's perspective, reading a byte on a stream means that the application wrote the byte. That's why the order of "written" vs "read" is opposite for stream_bw events compared to bw events.
The Time field is provided only in versions 0.3.2.1-alpha and later. It records when Tor created the bandwidth event.
These events are generated about once per second per stream; no events are generated for streams that have not written or read. These events apply only to streams entering Tor (such as on a SOCKSPort, TransPort, or so on). They are not generated for exiting streams.
Per-country client stats
The syntax is:
"650" SP "CLIENTS_SEEN" SP TimeStarted SP CountrySummary SP
IPVersions CRLF
We just generated a new summary of which countries we've seen clients from recently. The controller could display this for the user, e.g. in their "relay" configuration window, to give them a sense that they are actually being useful.
Currently only bridge relays will receive this event, but once we figure out how to sufficiently aggregate and sanitize the client counts on main relays, we might start sending these events in other cases too.
TimeStarted is a quoted string indicating when the reported summary counts from (in UTCS).
The CountrySummary keyword has as its argument a comma-separated, possibly empty set of "countrycode=count" pairs. For example (without linebreak), 650-CLIENTS_SEEN TimeStarted="2008-12-25 23:50:43" CountrySummary=us=16,de=8,uk=8
The IPVersions keyword has as its argument a comma-separated set of "protocol-family=count" pairs. For example, IPVersions=v4=16,v6=40
Note that these values are rounded, not exact. The rounding algorithm is specified in the description of "geoip-client-origins" in dir-spec.txt.
New consensus networkstatus has arrived
The syntax is:
"650" "+" "NEWCONSENSUS" CRLF 1*NetworkStatus "." CRLF "650" SP
"OK" CRLF
A new consensus networkstatus has arrived. We include NS-style lines for every relay in the consensus. NEWCONSENSUS is a separate event from the NS event, because the list here represents every usable relay: so any relay not mentioned in this list is implicitly no longer recommended.
[First added in 0.2.1.13-alpha]
New circuit buildtime has been set
The syntax is:
"650" SP "BUILDTIMEOUT_SET" SP Type SP "TOTAL_TIMES=" Total SP
"TIMEOUT_MS=" Timeout SP "XM=" Xm SP "ALPHA=" Alpha SP
"CUTOFF_QUANTILE=" Quantile SP "TIMEOUT_RATE=" TimeoutRate SP
"CLOSE_MS=" CloseTimeout SP "CLOSE_RATE=" CloseRate
CRLF
Type = "COMPUTED" / "RESET" / "SUSPENDED" / "DISCARD" / "RESUME"
Total = Integer count of timeouts stored
Timeout = Integer timeout in milliseconds
Xm = Estimated integer Pareto parameter Xm in milliseconds
Alpha = Estimated floating point Paredo parameter alpha
Quantile = Floating point CDF quantile cutoff point for this timeout
TimeoutRate = Floating point ratio of circuits that timeout
CloseTimeout = How long to keep measurement circs in milliseconds
CloseRate = Floating point ratio of measurement circuits that are closed
A new circuit build timeout time has been set. If Type is "COMPUTED", Tor has computed the value based on historical data. If Type is "RESET", initialization or drastic network changes have caused Tor to reset the timeout back to the default, to relearn again. If Type is "SUSPENDED", Tor has detected a loss of network connectivity and has temporarily changed the timeout value to the default until the network recovers. If type is "DISCARD", Tor has decided to discard timeout values that likely happened while the network was down. If type is "RESUME", Tor has decided to resume timeout calculation.
The Total value is the count of circuit build times Tor used in computing this value. It is capped internally at the maximum number of build times Tor stores (NCIRCUITS_TO_OBSERVE).
The Timeout itself is provided in milliseconds. Internally, Tor rounds this value to the nearest second before using it.
[First added in 0.2.2.7-alpha]
Signal received
The syntax is:
"650" SP "SIGNAL" SP Signal CRLF
Signal = "RELOAD" / "DUMP" / "DEBUG" / "NEWNYM" / "CLEARDNSCACHE"
A signal has been received and actions taken by Tor. The meaning of each signal, and the mapping to Unix signals, is as defined in section 3.7. Future versions of Tor MAY generate signals other than those listed here; controllers MUST be able to accept them.
If Tor chose to ignore a signal (such as NEWNYM), this event will not be sent. Note that some options (like ReloadTorrcOnSIGHUP) may affect the semantics of the signals here.
Note that the HALT (SIGTERM) and SHUTDOWN (SIGINT) signals do not currently generate any event.
[First added in 0.2.3.1-alpha]
Configuration changed
The syntax is:
StartReplyLine *(MidReplyLine) EndReplyLine
StartReplyLine = "650-CONF_CHANGED" CRLF
MidReplyLine = "650-" KEYWORD ["=" VALUE] CRLF
EndReplyLine = "650 OK"
Tor configuration options have changed (such as via a SETCONF or RELOAD signal). KEYWORD and VALUE specify the configuration option that was changed. Undefined configuration options contain only the KEYWORD.
Circuit status changed slightly
The syntax is:
"650" SP "CIRC_MINOR" SP CircuitID SP CircEvent [SP Path]
[SP "BUILD_FLAGS=" BuildFlags] [SP "PURPOSE=" Purpose]
[SP "HS_STATE=" HSState] [SP "REND_QUERY=" HSAddress]
[SP "TIME_CREATED=" TimeCreated]
[SP "OLD_PURPOSE=" Purpose [SP "OLD_HS_STATE=" HSState]] CRLF
CircEvent =
"PURPOSE_CHANGED" / ; circuit purpose or HS-related state changed
"CANNIBALIZED" ; circuit cannibalized
Clients MUST accept circuit events not listed above.
The "OLD_PURPOSE" field is provided for both PURPOSE_CHANGED and CANNIBALIZED events. The "OLD_HS_STATE" field is provided whenever the "OLD_PURPOSE" field is provided and is a hidden-service-related purpose.
Other fields are as specified in section 4.1.1 above.
[First added in 0.2.3.11-alpha]
Pluggable transport launched
The syntax is:
"650" SP "TRANSPORT_LAUNCHED" SP Type SP Name SP TransportAddress SP Port
Type = "server" | "client"
Name = The name of the pluggable transport
TransportAddress = An IPv4 or IPv6 address on which the pluggable
transport is listening for connections
Port = The TCP port on which it is listening for connections.
A pluggable transport called 'Name' of type 'Type' was launched
successfully and is now listening for connections on 'Address':'Port'.
Bandwidth used on an OR or DIR or EXIT connection
The syntax is:
"650" SP "CONN_BW" SP "ID=" ConnID SP "TYPE=" ConnType
SP "READ=" BytesRead SP "WRITTEN=" BytesWritten CRLF
ConnType = "OR" / ; Carrying traffic within the tor network. This can
either be our own (client) traffic or traffic we're
relaying within the network.
"DIR" / ; Fetching tor descriptor data, or transmitting
descriptors we're mirroring.
"EXIT" ; Carrying traffic between the tor network and an
external destination.
BytesRead = 1*DIGIT
BytesWritten = 1*DIGIT
Controllers MUST tolerate unrecognized connection types.
BytesWritten and BytesRead are the number of bytes written and read by Tor since the last CONN_BW event on this connection.
These events are generated about once per second per connection; no events are generated for connections that have not read or written. These events are only generated if TestingTorNetwork is set.
[First added in 0.2.5.2-alpha]
Bandwidth used by all streams attached to a circuit
The syntax is:
"650" SP "CIRC_BW" SP "ID=" CircuitID SP "READ=" BytesRead SP
"WRITTEN=" BytesWritten SP "TIME=" Time SP
"DELIVERED_READ=" DeliveredBytesRead SP
"OVERHEAD_READ=" OverheadBytesRead SP
"DELIVERED_WRITTEN=" DeliveredBytesWritten SP
"OVERHEAD_WRITTEN=" OverheadBytesWritten SP
"SS=" SlowStartState SP
"CWND=" CWNDCells SP
"RTT=" RTTMilliseconds SP
"MIN_RTT=" RTTMilliseconds CRLF
BytesRead = 1*DIGIT
BytesWritten = 1*DIGIT
OverheadBytesRead = 1*DIGIT
OverheadBytesWritten = 1*DIGIT
DeliveredBytesRead = 1*DIGIT
DeliveredBytesWritten = 1*DIGIT
SlowStartState = 0 or 1
CWNDCells = 1*DIGIT
RTTMilliseconds= 1*DIGIT
Time = ISOTime2Frac
BytesRead and BytesWritten are the number of bytes read and written on this circuit since the last CIRC_BW event. These bytes have not necessarily been validated by Tor, and can include invalid cells, dropped cells, and ignored cells (such as padding cells). These values include the relay headers, but not circuit headers.
Circuit data that has been validated and processed by Tor is further broken down into two categories: delivered relay message bodies, and overhead. DeliveredBytesRead and DeliveredBytesWritten are the total length of the relay message bodies transmitted since the last CIRC_BW event, not counting relay cell headers or circuit headers. OverheadBytesRead and OverheadBytesWritten are the extra unused bytes at the end of each cell in order for it to be the fixed CELL_LEN bytes long.
The sum of DeliveredBytesRead and OverheadBytesRead MUST be less than BytesRead, and the same is true for their written counterparts. This sum represents the total relay cell bytes on the circuit that have been validated by Tor, not counting relay headers and cell headers. Subtracting this sum (plus relay cell headers) from the BytesRead (or BytesWritten) value gives the byte count that Tor has decided to reject due to protocol errors, or has otherwise decided to ignore.
The Time field is provided only in versions 0.3.2.1-alpha and later. It records when Tor created the bandwidth event.
The SS, CWND, RTT, and MIN_RTT fields are present only if the circuit has negotiated congestion control to an onion service or Exit hop (any intermediate leaky pipe congestion control hops are not examined here). SS provides an indication if the circuit is in slow start (1), or not (0). CWND is the size of the congestion window in terms of number of cells. RTT is the N_EWMA smoothed current RTT value, and MIN_RTT is the minimum RTT value of the circuit. The SS and CWND fields apply only to the upstream direction of the circuit. The slow start state and CWND values of the other endpoint may be different.
These events are generated about once per second per circuit; no events are generated for circuits that had no attached stream writing or reading.
[First added in 0.2.5.2-alpha]
[DELIVERED_READ, OVERHEAD_READ, DELIVERED_WRITTEN, and OVERHEAD_WRITTEN were added in Tor 0.3.4.0-alpha]
[SS, CWND, RTT, and MIN_RTT were added in Tor 0.4.7.5-alpha]
Per-circuit cell stats
The syntax is:
"650" SP "CELL_STATS"
[ SP "ID=" CircuitID ]
[ SP "InboundQueue=" QueueID SP "InboundConn=" ConnID ]
[ SP "InboundAdded=" CellsByType ]
[ SP "InboundRemoved=" CellsByType SP
"InboundTime=" MsecByType ]
[ SP "OutboundQueue=" QueueID SP "OutboundConn=" ConnID ]
[ SP "OutboundAdded=" CellsByType ]
[ SP "OutboundRemoved=" CellsByType SP
"OutboundTime=" MsecByType ] CRLF
CellsByType, MsecByType = CellType ":" 1*DIGIT
0*( "," CellType ":" 1*DIGIT )
CellType = 1*( "a" - "z" / "0" - "9" / "_" )
Examples are:
650 CELL_STATS ID=14 OutboundQueue=19403 OutboundConn=15
OutboundAdded=create_fast:1,relay_early:2
OutboundRemoved=create_fast:1,relay_early:2
OutboundTime=create_fast:0,relay_early:0
650 CELL_STATS InboundQueue=19403 InboundConn=32
InboundAdded=relay:1,created_fast:1
InboundRemoved=relay:1,created_fast:1
InboundTime=relay:0,created_fast:0
OutboundQueue=6710 OutboundConn=18
OutboundAdded=create:1,relay_early:1
OutboundRemoved=create:1,relay_early:1
OutboundTime=create:0,relay_early:0
ID is the locally unique circuit identifier that is only included if the circuit originates at this node.
Inbound and outbound refer to the direction of relay cell flow through the circuit which is either to origin (inbound) or from origin (outbound).
InboundQueue and OutboundQueue are identifiers of the inbound and outbound circuit queues of this circuit. These identifiers are only unique per OR connection. OutboundQueue is chosen by this node and matches InboundQueue of the next node in the circuit.
InboundConn and OutboundConn are locally unique IDs of inbound and outbound OR connection. OutboundConn does not necessarily match InboundConn of the next node in the circuit.
InboundQueue and InboundConn are not present if the circuit originates at this node. OutboundQueue and OutboundConn are not present if the circuit (currently) ends at this node.
InboundAdded and OutboundAdded are total number of cells by cell type added to inbound and outbound queues. Only present if at least one cell was added to a queue.
InboundRemoved and OutboundRemoved are total number of cells by cell type processed from inbound and outbound queues. InboundTime and OutboundTime are total waiting times in milliseconds of all processed cells by cell type. Only present if at least one cell was removed from a queue.
These events are generated about once per second per circuit; no events are generated for circuits that have not added or processed any cell. These events are only generated if TestingTorNetwork is set.
[First added in 0.2.5.2-alpha]
Token buckets refilled
The syntax is:
"650" SP "TB_EMPTY" SP BucketName [ SP "ID=" ConnID ] SP
"READ=" ReadBucketEmpty SP "WRITTEN=" WriteBucketEmpty SP
"LAST=" LastRefill CRLF
BucketName = "GLOBAL" / "RELAY" / "ORCONN"
ReadBucketEmpty = 1*DIGIT
WriteBucketEmpty = 1*DIGIT
LastRefill = 1*DIGIT
Examples are:
650 TB_EMPTY ORCONN ID=16 READ=0 WRITTEN=0 LAST=100
650 TB_EMPTY GLOBAL READ=93 WRITTEN=93 LAST=100
650 TB_EMPTY RELAY READ=93 WRITTEN=93 LAST=100
This event is generated when refilling a previously empty token bucket. BucketNames "GLOBAL" and "RELAY" keywords are used for the global or relay token buckets, BucketName "ORCONN" is used for the token buckets of an OR connection. Controllers MUST tolerate unrecognized bucket names.
ConnID is only included if the BucketName is "ORCONN".
If both global and relay buckets and/or the buckets of one or more OR connections run out of tokens at the same time, multiple separate events are generated.
ReadBucketEmpty (WriteBucketEmpty) is the time in millis that the read (write) bucket was empty since the last refill. LastRefill is the time in millis since the last refill.
If a bucket went negative and if refilling tokens didn't make it go positive again, there will be multiple consecutive TB_EMPTY events for each refill interval during which the bucket contained zero tokens or less. In such a case, ReadBucketEmpty or WriteBucketEmpty are capped at LastRefill in order not to report empty times more than once.
These events are only generated if TestingTorNetwork is set.
[First added in 0.2.5.2-alpha]
HiddenService descriptors
The syntax is:
"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" / "QUERY_RATE_LIMITED"
Replica = 1*DIGIT
HSDirIndex = 64*HEXDIG
These events will be triggered when required HiddenService descriptor is
not found in the cache and a fetch or upload with the network is performed.
If the fetch was triggered with only a DescriptorID (using the HSFETCH
command for instance), the HSAddress only appears in the Action=RECEIVED
since there is no way to know the HSAddress from the DescriptorID thus
the value will be "UNKNOWN".
If we already had the v0 descriptor, the newly fetched v2 descriptor
will be ignored and a "HS_DESC" event with "IGNORE" action will be
generated.
For HsDir, LongName is always preferred. If HsDir cannot be found in node
list at the time event is sent, Fingerprint will be used instead.
If Action is "FAILED", Tor SHOULD send Reason field as well. Possible
values of Reason are:
- "BAD_DESC" - descriptor was retrieved, but found to be unparsable.
- "QUERY_REJECTED" - query was rejected by HS directory.
- "UPLOAD_REJECTED" - descriptor was rejected by HS directory.
- "NOT_FOUND" - HS descriptor with given identifier was not found.
- "UNEXPECTED" - nature of failure is unknown.
- "QUERY_NO_HSDIR" - No suitable HSDir were found for the query.
- "QUERY_RATE_LIMITED" - query for this service is rate-limited
For "QUERY_NO_HSDIR" or "QUERY_RATE_LIMITED", the HsDir will be set to
"UNKNOWN" which was introduced in tor 0.3.1.0-alpha and 0.4.1.0-alpha
respectively.
If Action is "CREATED", Tor SHOULD send Replica field as well. The Replica
field contains the replica number of the generated descriptor. The Replica
number is specified in rend-spec.txt section 1.3 and determines the
descriptor ID of the descriptor.
For hidden service v3, the following applies:
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 "DescriptorID" key 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".
[HS v3 support added 0.3.3.1-alpha]
HiddenService descriptors content
The syntax is:
"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.txt section 1.3 (v2) or rend-spec-v3.txt
section 2.4 (v3) or empty string on failure.
This event is triggered when a successfully fetched HS descriptor is received. The text of that descriptor is then replied. If the HS_DESC event is enabled, it is replied just after the RECEIVED action.
If a fetch fails, the Descriptor is an empty string and HSAddress is set to "UNKNOWN". The HS_DESC event should be used to get more information on the failed request.
If the fetch fails for the QUERY_NO_HSDIR or QUERY_RATE_LIMITED reason from the HS_DESC event, the HsDir is set to "UNKNOWN". This was introduced in 0.3.1.0-alpha and 0.4.1.0-alpha respectively.
It's expected to receive a reply relatively fast as in it's the time it takes to fetch something over the Tor network. This can be between a couple of seconds up to 60 seconds (not a hard limit). But, in any cases, this event will reply either the descriptor's content or an empty one.
[HS_DESC_CONTENT was added in Tor 0.2.7.1-alpha] [HS v3 support added 0.3.3.1-alpha]
Network liveness has changed
Syntax:
"650" SP "NETWORK_LIVENESS" SP Status CRLF
Status = "UP" / ; The network now seems to be reachable.
"DOWN" / ; The network now seems to be unreachable.
Controllers MUST tolerate unrecognized status types.
[NETWORK_LIVENESS was added in Tor 0.2.7.2-alpha]
Pluggable Transport Logs
Syntax:
"650" SP "PT_LOG" SP PT=Program SP Message
Program = The program path as defined in the *TransportPlugin
configuration option. Tor accepts relative and full path.
Message = The log message that the PT sends back to the tor parent
process minus the "LOG" string prefix. Formatted as
specified in pt-spec.txt section "3.3.4. Pluggable
Transport Log Message".
This event is triggered when tor receives a log message from the PT.
Example:
PT (obfs4): LOG SEVERITY=debug MESSAGE="Connected to bridge A"
the resulting control port event would be:
Tor: 650 PT_LOG PT=/usr/bin/obs4proxy SEVERITY=debug MESSAGE="Connected to bridge A"
[PT_LOG was added in Tor 0.4.0.1-alpha]
Pluggable Transport Status
Syntax:
"650" SP "PT_STATUS" SP PT=Program SP TRANSPORT=Transport SP Message
Program = The program path as defined in the *TransportPlugin
configuration option. Tor accepts relative and full path.
Transport = This value indicates a hint on what the PT is such as the
name or the protocol used for instance.
Message = The status message that the PT sends back to the tor parent
process minus the "STATUS" string prefix. Formatted as
specified in pt-spec.txt section "3.3.5 Pluggable
Transport Status Message".
This event is triggered when tor receives a log message from the PT.
Example:
PT (obfs4): STATUS TRANSPORT=obfs4 CONNECT=Success
the resulting control port event would be:
Tor: 650 PT_STATUS PT=/usr/bin/obs4proxy TRANSPORT=obfs4 CONNECT=Success
[PT_STATUS was added in Tor 0.4.0.1-alpha]