有个问题困扰了我很久,情景如下:
我们使用“嵌入”的方式在Tor启动前运行一段基于stem库的Python代码,用于选择我们自主部署的节点并建立circuit,但在测试中发现,只要将Tor作为proxy并有流量传输时,Tor会自动建立新的链路用以中转流量,而我们自建的链路却始终被晾在一旁。
首先我在stem库中寻找方法,确实有将特定流量导入自定义链路的例子:https://stem.torproject.org/tutorials/to_russia_with_love.html#custom-path-selection
它的关键是配置了Tor的一个配置项__LeaveStreamsUnattached
,如果该配置项设为1,除了被捕捉并导入到我们链路的数据流之外,其他数据流都会被丢弃。核心代码如下:
circuit_id = controller.new_circuit(path, await_build = True)
def attach_stream(stream):
if stream.status == 'NEW':
controller.attach_stream(stream.id, circuit_id)
controller.add_event_listener(attach_stream, stem.control.EventType.STREAM)
try:
controller.set_conf('__LeaveStreamsUnattached', '1') # leave stream management to us
# 通过tor代理访问页面
check_page = query('https://check.torproject.org/')
...
finally:
controller.remove_event_listener(attach_stream)
controller.reset_conf('__LeaveStreamsUnattached')
但是这样实现有很大的局限性,就是代理操作只能写死在python代码中,python代码运行完毕,add_event_listener
也随即失效,用户通过将Tor设置为代理后产生的流量仍然不会导入自建链路。
于是我猜测可能是我们自主部署的节点的问题。
我们选节点构建链路有个原则,就是Guard和Exit必须是自主可控的,而我们自主部署的节点都没有配置ExitPolicy
,也没有Exit
这个标识符。很可能是这个原因,导致Tor的Path Selection Algorithm觉得链路的Exit节点不安全,所以直接选择新建一条安全链路来中转数据流。
根据这个猜想,我查了Tor节点获得Exit
标识符的条件:
A router is called an \’Exit’ iff it allows exits to at least two of the ports 80, 443, and 6667 and allows exits to at least one /8 address space.
所以我为每个节点都设置了ExitPolicy
并修改了相应的端口(在torrc中):
DirPort 80
ORPort 443
ExitRelay 1
ExitPolicy reject 0.0.0.0/8:*
ExitPolicy reject 169.254.0.0/16:*
ExitPolicy reject 127.0.0.0/8:*
ExitPolicy reject 192.168.0.0/16:*
ExitPolicy reject 10.0.0.0/8:*
ExitPolicy reject 172.16.0.0/12:*
ExitPolicy accept *:20-21
ExitPolicy accept *:22
ExitPolicy accept *:23
ExitPolicy accept *:43
ExitPolicy accept *:53
ExitPolicy accept *:79
ExitPolicy accept *:80-81
ExitPolicy accept *:88
ExitPolicy accept *:110
ExitPolicy accept *:143
ExitPolicy accept *:194
ExitPolicy accept *:220
ExitPolicy accept *:389
ExitPolicy accept *:443
ExitPolicy accept *:464
ExitPolicy accept *:531
ExitPolicy accept *:543-544
ExitPolicy accept *:554
ExitPolicy accept *:563
ExitPolicy accept *:636
ExitPolicy accept *:706
ExitPolicy accept *:749
ExitPolicy accept *:853
ExitPolicy accept *:873
ExitPolicy accept *:902-904
ExitPolicy accept *:981
ExitPolicy accept *:989-990
ExitPolicy accept *:991
ExitPolicy accept *:992
ExitPolicy accept *:993
ExitPolicy accept *:994
ExitPolicy accept *:995
ExitPolicy accept *:1194
ExitPolicy accept *:1220
ExitPolicy accept *:1293
ExitPolicy accept *:1500
ExitPolicy accept *:1533
ExitPolicy accept *:1677
ExitPolicy accept *:1723
ExitPolicy accept *:1755
ExitPolicy accept *:1863
ExitPolicy accept *:2082
ExitPolicy accept *:2083
ExitPolicy accept *:2086-2087
ExitPolicy accept *:2095-2096
ExitPolicy accept *:2102-2104
ExitPolicy accept *:3128
ExitPolicy accept *:3389
ExitPolicy accept *:3690
ExitPolicy accept *:4321
ExitPolicy accept *:4643
ExitPolicy accept *:5050
ExitPolicy accept *:5190
ExitPolicy accept *:5222-5223
ExitPolicy accept *:5228
ExitPolicy accept *:5900
ExitPolicy accept *:6660-6669
ExitPolicy accept *:6679
ExitPolicy accept *:6697
ExitPolicy accept *:8000
ExitPolicy accept *:8008
ExitPolicy accept *:8074
ExitPolicy accept *:8080
ExitPolicy accept *:8082
ExitPolicy accept *:8087-8088
ExitPolicy accept *:8232-8233
ExitPolicy accept *:8332-8333
ExitPolicy accept *:8443
ExitPolicy accept *:8888
ExitPolicy accept *:9418
ExitPolicy accept *:9999
ExitPolicy accept *:10000
ExitPolicy accept *:11371
ExitPolicy accept *:19294
ExitPolicy accept *:19638
ExitPolicy accept *:50002
ExitPolicy accept *:64738
ExitPolicy reject *:*
RunAsDaemon 1
当然为了配置更安全的ExitPolicy可以参考如下四项配置:
- Passive ExitPolicy
- Browser Only ExitPolicy
- NON-EXIT (RELAY ONLY) Policy
- Bridge Only (Unlisted Bridge) Policy
配置完后等待一段时间,发现节点已经拥有Exit
标识符,再次测试流量中转,发现流量已经可以正常走我们自建的链路,这也验证了我前面的猜想是正确的。
发表评论