{"id":27268756,"url":"https://github.com/shadow/oniontrace","last_synced_at":"2025-07-06T01:04:05.170Z","repository":{"id":44754262,"uuid":"170739968","full_name":"shadow/oniontrace","owner":"shadow","description":"Extracts and logs information from Tor's control port. Records and plays back Tor circuit building and stream assignment.","archived":false,"fork":false,"pushed_at":"2023-05-11T14:54:33.000Z","size":93,"stargazers_count":9,"open_issues_count":1,"forks_count":6,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-04-11T12:04:58.253Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shadow.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-02-14T18:39:04.000Z","updated_at":"2025-03-12T07:02:05.000Z","dependencies_parsed_at":"2025-04-11T11:39:24.814Z","dependency_job_id":"3739eba4-4cad-4c10-96bd-4151794d1d9a","html_url":"https://github.com/shadow/oniontrace","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/shadow/oniontrace","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadow%2Foniontrace","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadow%2Foniontrace/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadow%2Foniontrace/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadow%2Foniontrace/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shadow","download_url":"https://codeload.github.com/shadow/oniontrace/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadow%2Foniontrace/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263833416,"owners_count":23517373,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-11T11:31:58.481Z","updated_at":"2025-07-06T01:04:05.064Z","avatar_url":"https://github.com/shadow.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"## OnionTrace\n\n![](https://github.com/shadow/oniontrace/workflows/Builds/badge.svg)\n\nThis program records and plays back Tor circuit building and stream assignment.\nIt can also register for several asynchronous Tor events and logs the events\nas they are received from Tor over time.\n\n## Setup\n\nDependencies in Fedora/RedHat:\n\n    sudo yum install cmake glib2 glib2-devel\n\nDependencies in Ubuntu/Debian:\n\n    sudo apt-get install cmake libglib2.0-0 libglib2.0-dev\n\nBuild with a custom install prefix:\n\n    mkdir build \u0026\u0026 cd build\n    cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local\n    make\n\nOptionally install to the prefix:\n\n    make install\n\n## Usage\n\noniontrace arguments should be configured as follows:\n\targuments=\"oniontrace key=value ...\"\n\nThe valid keys and the type of the valid values are listed below, along with\nany defaults. The format is:  \n + `key`:ValueType (default=`val`) [Mode=`ValidMode`] - explanation\n\nSpecifying the run mode is **optional**, the default mode is `log`:\n\n + `Mode`:String (default=`log`) [Mode=`record`,`play`,`log`]  \n    Valid values for the running mode are `record`, `play`, and `log`.  \n    `record` mode records circuit creation and stream assignment schedules.  \n    `play` mode creates circuits and assigns streams according to a  \n    schedule as previously recorded with `record` mode.\n    `log` mode registers for async events and logs them to stdout as they occur.\n\nThe following are **required** arguments (default values do not exist):\n\n + `TorControlPort`:Integer [Mode=`record`,`play`,`log`]  \n    The Tor Control server port, set in the torrc file of the Tor instance that  \n    you want to trace.\n\nThe following are **optional** arguments (default values exist):\n\n + `LogLevel`:String (default=`info`) [Mode=`record`,`play`,`log`]  \n    The log level to use while running oniontrace. Valid values are:  \n    `debug` \u003e `info` \u003e `message` \u003e `warning`  \n    Messages logged at a higher level than the one configured will be filtered.\n    \n + `TraceFile`:String (default=`oniontrace.csv`) [Mode=`record`,`play`]  \n   The filename to write the trace when in `record` mode, or read a previously  \n   recorded trace when in `play` mode.\n\n + `RunTime`:Integer (default=`0`) [Mode=`record`,`play`]  \n   If positive, OnionTrace will stop running after the number of seconds  \n   specified in this value. In `record` mode, this has the effect of recording  \n   all circuits that are being tracked even if those circuits have not yet  \n   been closed by Tor.  \n\n + `Events`:String (default=`BW`) [Mode=`log`]  \n   The asynchronous Tor events for which we should listen and log when  \n   we receive them from Tor. The value string should be a comma-delimited list  \n   of events, e.g., 'BW,CIRC,STREAM'. See Section 4.1 of the  \n   'Tor control protocol' specification for a full list of acceptable events.  \n   (https://gitweb.torproject.org/torspec.git/tree/control-spec.txt)\n\n## Tor Changes Required for record Mode\n\nIn order for the `record` mode to work correctly, we need Tor to export the\nsocks username in all stream control events. That will allow us to keep the\nthe same streams on the correct circuits when using `playback` mode to play\nback a recorded trace file.\n\nIf the original stream control event is this:\n\n```\n650 STREAM 21 NEW 0 11.0.0.6:18080 SOURCE_ADDR=127.0.0.1:21437\n```\n\nWe need to change Tor so that it outputs events like:\n\n```\n650 STREAM 21 NEW 0 11.0.0.6:18080 SOURCE_ADDR=127.0.0.1:21437 USERNAME=MYUSER\n```\n\nWhere `MYUSER` is the SOCKS username in use to tie that stream to a circuit.\nHere is a patch that was created to do this for `tor-0.3.5.8`, which may help\nyou understand how to change a newer version of Tor to export the correct info.\n\n```\ndiff --git a/src/feature/control/control.c b/src/feature/control/control.c\nindex cc7ecff2f..fac51eb38 100644\n--- a/src/feature/control/control.c\n+++ b/src/feature/control/control.c\n@@ -5904,16 +5904,28 @@ control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,\n       purpose = \" PURPOSE=USER\";\n   }\n \n+  /* send socks username along with stream events. */\n+  char user[64];\n+  int do_user = (conn-\u003esocks_request \u0026\u0026 conn-\u003esocks_request-\u003eusername) ? 1 : 0;\n+\n+  if(do_user) {\n+    char* u_null_term = tor_memdup_nulterm(conn-\u003esocks_request-\u003eusername,\n+        conn-\u003esocks_request-\u003eusernamelen);\n+    tor_snprintf(user, 64, \" USERNAME=%s\", u_null_term);\n+    free(u_null_term);\n+  }\n+\n   circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn));\n   if (circ \u0026\u0026 CIRCUIT_IS_ORIGIN(circ))\n     origin_circ = TO_ORIGIN_CIRCUIT(circ);\n   send_control_event(EVENT_STREAM_STATUS,\n-                        \"650 STREAM %\"PRIu64\" %s %lu %s%s%s%s\\r\\n\",\n+                        \"650 STREAM %\"PRIu64\" %s %lu %s%s%s%s%s\\r\\n\",\n                      (ENTRY_TO_CONN(conn)-\u003eglobal_identifier),\n                      status,\n                         origin_circ?\n                            (unsigned long)origin_circ-\u003eglobal_identifier : 0ul,\n-                        buf, reason_buf, addrport_buf, purpose);\n+                        buf, reason_buf, addrport_buf, purpose,\n+                        do_user ? user : \"\");\n \n   /* XXX need to specify its intended exit, etc? */\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshadow%2Foniontrace","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshadow%2Foniontrace","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshadow%2Foniontrace/lists"}