padding-machines-for-tor

Tor 的电路填充框架

填充机是一种存在于每个电路中的状态机,因此被称为 "电路填充框架"。填充机器注入虚假(填充)单元,目的各有不同,例如向被动网络对手隐藏电路的目的(例如区分 "常规 "电路和洋葱服务)。

circuitpadding.h 是自下而上的,因此要回答什么是机器,我们在这里更多地是自上而下的。机器有三个主要结构:

  • circpad_machine_spec_t 机器的全局规范,不可变。
  • circpad_state_t 全局不可变的状态描述,以及作为机器一部分的可能转换。
  • circpad_machine_runtime_t 状态机当前状态的每个电路描述,包含可变数据,尽可能小,以减少内存使用。

因此,一台机器由一个 circpad_machine_spec_t 组成,它指定了若干状态及其转换(circpad_state_t),所有状态均不可变。对于每个电路,一个 circpad_machine_runtime_t 包含可变数据,例如电路上机器的当前状态。

circpad_machine_spec_t详细信息

最重要的字段是条件和状态,states 是一个状态数组,最大大小为CIRCPAD_STATENUM_MAX,目前为 UINT16_MAX,为状态提供了足够的空间(作为比较,WTF-PAD 有三个状态)。

circpad_state_t详细信息

  • IAT 直方图或概率分布。
  • 为 IAT 使用 RTT 估计值的标志。
  • 具有最小-最大参数的长度(以发送(填充)单元数为单位)概率分布。
  • 导致从当前状态过渡到相同或其他状态的事件数组。

circpad_machine_sample_delay() 使用 IAT 直方图/分布来采样调度单个填充单元的延迟(以微秒为单位)。作为参考,调整直方图是 WTF-PAD 防御的难点问题,也是电路填充框架设计的灵感来源。

circpad_machine_runtime_t详细信息

运行时结构体包含大量用于内部记账的变量,涉及计时器、当前状态、直方图(如果使用)、发送的填充量等。据我所知,这些变量在创建机器时都是透明的。

从零开始构建padding machine

本文档描述了在tor的新电路填充框架中从头开始构建“填充机”的过程。 将早期自适应填充 (APE) 从 basket2 移植到电路填充框架的过程中记下了注释。 我们的目标只是记录整个过程并提供有用的指导,而不是创建一个有用的机器。

  • 克隆并编译
  • 在 Tor浏览器中使用新建的 Tor,并在我们运行的小型(非出口)中继中使用
  • 添加一个简单的 APE 填充机
  • 运行机器,检查活动日志
  • 端口 APE 的状态机,无需考虑太多参数

1.克隆并编译

git clone https://git.torproject.org/tor.git
cd tor
git checkout tor-0.4.1.5

上面使用了 tor-0.4.1.5 的标签,其中发布了电路填充框架,请随意使用更新的东西(尽管避免 HEAD,可能会有错误)。 

sh autogen.sh 
./configure
make

当运行 ./configure 时,会被告知缺少在基于 debian 的发行版上安装的依赖项和软件包。 重要提示:如果您计划在中继上运行 Tor 作为真实 Tor 网络的一部分,并且您的服务器运行使用 systemd 的发行版,那么建议

apt install dpkg dpkg-dev libevent-dev libssl-dev asciidoc quilt dh -apparmor libseccomp-dev dh-systemd libsystemd-dev pkg-config dh-autoreconf libfakeroot zlib1g zlib1g-dev automake liblzma-dev libzstd-dev

并确保 Tor 已启用 systemd 支持:

./configure --enable-systemd

如果没有这个,在最近的 Ubuntu 上,我的 tor 服务每五分钟就会被 systemd 强制重新启动(SIGINT 中断)。如果您想在本地系统上安装,请运行 make install。 对于我们的例子,我们只需要 src/app/tor 中的 tor 二进制文件。

 2.在 Tor 浏览器和中继中使用 Tor

从 torproject.org 下载并安装新的 Tor 浏览器 (TB)。 确保它有效。 从命令行,相对于提取 TB 时创建的文件夹,运行./Browser/start-tor-browser --verbose 以获取一些基本日志输出。 请注意 Tor 的版本,在我的例子中,Tor 0.4.0.5 (git-bf071e34aa26e096) 作为 TB 8.5.4 的一部分。 关闭 TB,复制您之前编译的 tor 二进制文件并替换 Browser/TorBrowser/Tor/tor。 再次从命令行启动 TB,您应该看到不同的版本,在我的例子中是 Tor 0.4.1.5 (git-439ca48989ece545)。

我们运行的relay也是在linux上,tor位于/usr/bin/tor。 要查看自上次启动以来的相关日志,请执行 sudo Journalctl -b /usr/bin/tor,其中我们发现 Tor 0.4.0.5 在 Linux 上运行。 将本地编译的 tor 复制到中继的临时位置,然后确保其所有权和访问权限与 /usr/bin/tor 相同。 接下来,使用 sudo service tor stop 关闭正在运行的 tor 服务,等待其停止(通常为 30 秒),复制我们本地编译的 tor 替换 /usr/bin/tor 然后再次启动该服务。 检查我们看到的日志或 0.4.1.5 (git-439ca48989ece545)。

{反复关闭中继对网络有害,应避免。 对于那个很抱歉。}

在继续操作机器之前,我们还剩下一步:配置 TB 以始终使用我们的中间继电器。 编辑 Browser/TorBrowser/Data/Tor/torrc 并设置 MiddleNodes <fingerprint>,其中 <fingerprint> 是中继的指纹。 启动TB,访问一个网站,通过查看电路显示手动确认中间是否被使用。

3.添加一台简单的 APE 填充机

现在是有趣的部分。 我们有多种资源可供使用(请注意,链接将来可能会损坏,只需搜索标题即可):

  • 官方电路填充开发人员文档。
  • 我们对电路填充框架的实现做了注释。
  • Tor 中当前电路填充机的实现:CircuitPadding.c 和 CircuitPadding_machines.h。

详情请参阅上述链接。 展望未来,重点是描述所做的事情,而不一定解释所有细节。

由于我们计划对 tor 进行更改,因此创建一个新分支。

git checkout -b circuit-padding-ape-machine tor-0.4.1.5

我们首先在 circuitpadding_machines.h 中声明两个函数,一个用于客户端的机器,一个用于中继:

void circpad_machine_relay_wf_ape(smartlist_t *machines_sl);
void circpad_machine_client_wf_ape(smartlist_t *machines_sl);

定义进入 circuitpadding_machines.c:

/**************** Adaptive Padding Early (APE) machine ****************/

/** 
 * Create a relay-side padding machine based on the APE design. 
 */
void
circpad_machine_relay_wf_ape(smartlist_t *machines_sl)
{
  circpad_machine_spec_t *relay_machine
  = tor_malloc_zero(sizeof(circpad_machine_spec_t));

  relay_machine->name = "relay_wf_ape";
  relay_machine->is_origin_side = 0; // relay-side

  // Pad to/from the middle relay, only when the circuit has streams
  relay_machine->target_hopnum = 2;
  relay_machine->conditions.min_hops = 2;
  relay_machine->conditions.state_mask = CIRCPAD_CIRC_STREAMS;

  // limits to help guard against excessive padding
  relay_machine->allowed_padding_count = 1;
  relay_machine->max_padding_percent = 1;

  // one state to start with: START (-> END, never takes a slot in states)
  circpad_machine_states_init(relay_machine, 1);
  relay_machine->states[CIRCPAD_STATE_START].
    next_state[CIRCPAD_EVENT_NONPADDING_SENT] =
    CIRCPAD_STATE_END;

  // register the machine
  relay_machine->machine_num = smartlist_len(machines_sl);
  circpad_register_padding_machine(relay_machine, machines_sl);
  
  log_info(LD_CIRC,
           "Registered relay WF APE padding machine (%u)",
           relay_machine->machine_num);
}

/** 
 * Create a client-side padding machine based on the APE design. 
 */
void
circpad_machine_client_wf_ape(smartlist_t *machines_sl)
{
    circpad_machine_spec_t *client_machine
  = tor_malloc_zero(sizeof(circpad_machine_spec_t));

  client_machine->name = "client_wf_ape";
  client_machine->is_origin_side = 1; // client-side

  /** Pad to/from the middle relay, only when the circuit has streams, and only
  * for general purpose circuits (typical for web browsing)
  */
  client_machine->target_hopnum = 2;
  client_machine->conditions.min_hops = 2;
  client_machine->conditions.state_mask = CIRCPAD_CIRC_STREAMS;
  client_machine->conditions.purpose_mask =
    circpad_circ_purpose_to_mask(CIRCUIT_PURPOSE_C_GENERAL);

  // limits to help guard against excessive padding
  client_machine->allowed_padding_count = 1;
  client_machine->max_padding_percent = 1;

  // one state to start with: START (-> END, never takes a slot in states)
  circpad_machine_states_init(client_machine, 1);
  client_machine->states[CIRCPAD_STATE_START].
    next_state[CIRCPAD_EVENT_NONPADDING_SENT] =
    CIRCPAD_STATE_END;

  client_machine->machine_num = smartlist_len(machines_sl);
  circpad_register_padding_machine(client_machine, machines_sl);
  log_info(LD_CIRC,
           "Registered client WF APE padding machine (%u)",
           client_machine->machine_num);
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

我们还必须修改 circuitpadding.c 中的 circpad_machines_init() 来注册我们的机器:

  /* Register machines for the APE WF defense */
  circpad_machine_client_wf_ape(origin_padding_machines);
  circpad_machine_relay_wf_ape(relay_padding_machines);

我们运行 make 来获取新的 Tor 二进制文件并将其复制到本地 TB。

4.运行机器

为了能够在启动 TB 时在控制台中查看电路信息事件,我们将 Log [circ]info notice stdout添加到 TB 的 torrc 中。

运行TB访问example.com我们首先在日志中发现:

Aug 30 18:36:43.000 [info] circpad_machine_client_hide_intro_circuits(): Registered client intro point hiding padding machine (0)
Aug 30 18:36:43.000 [info] circpad_machine_relay_hide_intro_circuits(): Registered relay intro circuit hiding padding machine (0)
Aug 30 18:36:43.000 [info] circpad_machine_client_hide_rend_circuits(): Registered client rendezvous circuit hiding padding machine (1)
Aug 30 18:36:43.000 [info] circpad_machine_relay_hide_rend_circuits(): Registered relay rendezvous circuit hiding padding machine (1)
Aug 30 18:36:43.000 [info] circpad_machine_client_wf_ape(): Registered client WF APE padding machine (2)
Aug 30 18:36:43.000 [info] circpad_machine_relay_wf_ape(): Registered relay WF APE padding machine (2)

一切顺利,我们的机器正在运行。 进一步观察我们发现:

Aug 30 18:36:55.000 [info] circpad_setup_machine_on_circ(): Registering machine client_wf_ape to origin circ 2 (5)
Aug 30 18:36:55.000 [info] circpad_node_supports_padding(): Checking padding: supported
Aug 30 18:36:55.000 [info] circpad_negotiate_padding(): Negotiating padding on circuit 2 (5), command 2
Aug 30 18:36:55.000 [info] circpad_machine_spec_transition(): Circuit 2 circpad machine 0 transitioning from 0 to 65535
Aug 30 18:36:55.000 [info] circpad_machine_spec_transitioned_to_end(): Padding machine in end state on circuit 2 (5)
Aug 30 18:36:55.000 [info] circpad_circuit_machineinfo_free_idx(): Freeing padding info idx 0 on circuit 2 (5)
Aug 30 18:36:55.000 [info] circpad_handle_padding_negotiated(): Middle node did not accept our padding request on circuit 2 (5) 

我们看到我们的中间支持填充(自从我们升级到 tor-0.4.1.5),我们尝试协商,我们的机器在客户端上启动,转换到最终状态,然后被释放。 最后一行表明中间没有可以运行的垫料机。

接下来,我们遵循与之前相同的步骤,并在中间中继处替换修改后的 tor。 我们不会更新那里的日志记录,以避免登录实时网络上的信息级别。 再次查看客户端日志,我们发现协商工作与以前一样,除了最后一行:它丢失了,因此机器也在中间运行。

5.实现 APE 状态机

移植相当简单:定义所有机器的状态,再添加两台机器(用于 WTFP-PAD 的接收部分,超出 AP),并为分布选择合理的参数(我现在完全控制它,就像实现 APE 时一样)。 circuit-padding-ape-machine 分支包含完整机器的提交以及大量评论。

对这个过程的一些评论:

  • tor-0.4.1.5 不支持同一线路上的两台机器,必须进行以下修复:https://trac.torproject.org/projects/tor/ticket/31111 。 好消息是,在修复程序进行微小更改后,其他一切似乎都有效。
  • APE 随机化其分布。 目前,这只能在 Tor 启动期间完成。 这在审查规避设置 (obfs4) 中有意义,但对于 WF 防御来说意义不大:进一步随机化每个电路可能对攻击者来说是一个 PITA,几乎没有什么缺点。
  • 令人烦恼的是,我编译的 Tor 中缺乏 systemd 支持导致 systemd 每五分钟在中间中继中断(SIGINT)我的 Tor 进程。 更新了上面的构建步骤,希望可以减轻其他人的痛苦。
  • 当过早发送填充单元时,中继肯定存在一些错误(?)。 由于 circpad_machine_relay_wf_ape_send(),APE 实现中可能会发生这种情况。 接下来会调查。
  • 正如电路填充文档草案中所建议的那样,将机器的注册从机器的定义移动到 circpad_machines_init() 是有意义的。

请记住,APE 只是一个概念验证,我们对其抵御 WF 攻击的能力做出零声明,特别是基于深度学习的攻击。

如何收集大量痕迹

基本使用 python、shell 脚本和容器。 这个想法是在容器中运行许多无头 Tor 浏览器客户端,这些客户端反复从收集服务器获取工作。 该作品由一个可访问的 URL 组成。 当访问 URL 时,客户端会记录其 Tor 日志并将其上传到服务器。

修改 Tor 浏览器

首先从 torproject.org 下载此文件夹和全新的 Linux Tor 浏览器安装。 编辑 Browser/start-tor-browser,第 12 行,将其更改为:

if [ "x$DISPLAY" = "x" ] && [[ "$*" != *--headless* ]]; then 

这使得在无头模式下运行 Tor 浏览器成为可能,而无需完整的 X 安装。

无头模式下的 Tor 浏览器不会显示 Tor 启动器启动提示,并且会无限期挂起。 要跳过提示,请在 TB 附带的 Firefox 配置文件中创建一个首选项文件:Browser/TorBrowser/Data/Browser/profile.default/user.js,并添加以下一行:

user_pref("extensions.torlauncher.prompt_at_startup", false); 

编辑 Browser/TorBrowser/Data/Tor/torrc 并设置任何必要的限制,例如 EntryNodesMiddleNodesUseEntryGuards,具体取决于要运行的实验。 如果您使用的是 Circuitpadding 模拟器(下面有详解),请构建自定义 tor 二进制文件,将其添加到位于 Browser/TorBrowser/Tor/ 的 TB,并将“Log [circ]info notification stdout”添加到 torrc

当我们收集 Goodenough 数据集的踪迹时,我们使用了以下 torrc

Log [circ]info notice stdout
UseEntryGuards 0 

Circuit Padding Simulator 

Tor电路填充框架中填充机器的最小模拟器。由两个存储库组成。 该存储库包含 python 粘合代码,可从 Tor 日志文件中提取跟踪并合成新的跟踪。电路填充模拟器由两个存储库组成。 该存储库包含 python 粘合代码,可从 Tor 日志文件中提取跟踪并合成新的跟踪。此外,它还提供了一个单元测试,可以获取输入跟踪文件并对它们应用电路填充机,从而生成受保护的跟踪。将这两部分结合在一起,您的 Tor 客户端和 Tor 中继可以记录未防御(非填充)的跟踪,然后将填充机应用于这些跟踪,从而在模拟中或在实时 Tor 网络上生成受防御的跟踪。

快速入门和测试示例

假设您已在名为 circpad-sim 的目录中签出此存储库,并且您当前位于该目录中,则执行以下操作:

cd ..                                 # from circpad-sim checkout, go up
git clone https://github.com/mikeperry-tor/tor.git
cd tor
git checkout -t origin/circpad-sim-v4 # Adjust origin and branches as needed

然后像平常一样构建tor。 模拟器作为 tor 单元测试框架的一部分进行测试,您可以按如下方式检查:

./src/test/test circuitpadding_sim/..
circuitpadding_sim/circuitpadding_sim_main: [forking] OK
1 tests ok.  (0 skipped)

构建docker容器

1. 在要用于收集的计算机上,安装 docker。
2. 在 docker-debian docker-ubuntu 中构建 Dockerfile,具体取决于构建自定义 tor 二进制 的环境。 您可以通过运行以下命令来构建容器: docker build -t wf-collect . (注意点)。 

启动容器

在每台机器上:

1. 将您之前修改的 tor-browser_en-US 复制到 exp 中。
2. 运行./set_tb_permissions.sh
编辑 run.sh 然后运行它。

在我们的实验中,我们创建了三个具有不同安全级别/设置的 Tor 浏览器 zip 文件,并将它们全部放在 exp 文件夹中。 然后我们使用以下命令在每台机器上轮换:

rm -rf collect/exp/tor-browser_en-US && cd collect/exp/ && unzip tor-browser_en-US-safest.zip && cd ../ && ./set_tb_permissions.sh && ./run.sh 

 设置采集服务器

在可以从 docker 容器访问的服务器上运行 circpad-server.py。 该脚本的参数很大程度上是不言自明的: 

usage: circpad-server.py [-h] -l L -n N -d D [-m M] [-s S]

optional arguments:
  -h, --help  show this help message and exit
  -l L        file with list of sites to visit, one site per line
  -n N        number of samples
  -d D        data folder for storing results
  -m M        minimum number of lines in torlog to accept
  -s S        stop collecting at this many logs collected, regardless of
              remaining sites or samples (useful for unmonitored sites)

所有客户端都将尝试从服务器获取工作,如果失败,则在重试之前休眠指定的超时时间(默认值:60 秒)。 在我们的实验中,我们使用了 7 台带有 20 个容器的机器,每台机器都与具有单个适度核心的服务器进行通信,没有太多麻烦。 所有机器,包括服务器,都位于同一个集群中。 在单独的物理机器上运行服务器可能意味着由于单线程,服务器在收集过程中成为太大的瓶颈。 

从数据集中提取痕迹

收集原始数据集后,下一步是提取有用的日志并获取一些 circpad 跟踪。 extract 文件夹包含您需要的所有内容:extract.py 脚本将验证日志是否包含访问预期网站的痕迹,并按照我们的 Goodenough 数据集构建数据集。

usage: extract.py [-h] -i I -o O -t T -l L [--monitored] [--unmonitored]
                  [-c C] [-s S] [-m M]

optional arguments:
  -h, --help     show this help message and exit
  -i I           input folder of logs
  -o O           output folder for logs
  -t T           output folder for traces
  -l L           file with list of sites to visit, one site per line
  --monitored    extract monitored
  --unmonitored  extract unmonitored
  -c C           the number of monitored classes
  -s S           the number of samples
  -m M           minimum number of lines in a trace

有关如何使用 extract.py 的示例,请参阅 helper all.sh 脚本。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值