Win10下使用Tor创建.onion域名网站的可行性分析笔记

By 张怀义 at 2020-04-05

我在发了

https://2049bbs.xyz/t/4017

这个帖子后,打算自己在电脑上搭建一个onion网站。

经过Google,发现都是在Linux下的。我不想重装系统,就测试下win10下的可能性。

第一步,我按照Linux的方法,修改torrc文件,重启tor,报错!

一头黑线。。。

想想也是,既然需要生成公钥和私钥,肯定需要openssl啊!我win10下没装openssl,当然会报错!

但是除了openssl,onion还需要什么呢?下次估计我就没有这么好运气能猜出来缺什么了

我当然知道你们Linux下工具都是齐全的,不像我是windows,需要自己安装开源工具加到path环境变量

Tor, Win10, onion, 域名, 可行性


第二步,我开始看源码!为什么看源码?因为不看源码,我不知道缺什么东西!!!

C:\Users\张怀义\tor-alpha-3.04.1\src\feature\hs\hs_config.c

如果是版本2,看函数rend_config_service

如果是版本3,看函数config_service_v3

一头黑线。。。

默认是什么版本啊?算了,我强制用配置项设置为版本3吧,怎么想都是版本3更好一些

张怀义 at 2020-04-05
1

第三步,根据第二步,我们知道了配置项有哪些。现在开始看服务具体做什么。

C:\Users\张怀义\tor-alpha-3.04.1\src\feature\hs\hs_service.c

hs_service_init 会new一个smartlist

service_free_all会free刚才的smartlist

hs_service_load_all_keys 加载或生成key

我感觉我就是卡在上面这个函数

hs_check_service_private_dir 创建目录并修改权限???Windows下这段代码是不是有问题,因为用户权限

ed_key_init_from_file 这个应该会生成公钥和私钥,但是看源码,不是用的openssl,而是自己实现了!

hs_build_address 会生成我们的onion地址

write_address_to_file 最后写到网上说的两个文件,一个是公钥和私钥文件,一个是hostname文件

load_client_keys载入代码,完成服务注册,注册服务代码是register_service

hs_service_map_has_changed通知服务map发生了变化

张怀义 at 2020-04-05
2

被打脸了,不是缺少openssl造成的。。。

而且从代码看,使用的是椭圆曲线算法,而不是我以为的RSA算法

意外收获是这里居然还有DoS防御等相关代码,我继续研究下为什么win10无法创建onion

张怀义 at 2020-04-05
3

ed25519_keypair_generate生成了公钥和私钥的密钥对

然后调用tor_cert_create传入刚才的公钥,得到证书

TOR作者是真心大神中的大神啊,全能型天才啊

先用ed25519_secret_key_generate产生了私钥

再用ed25519_public_key_generate产生了公钥

有两个实现impl_donna 或者 impl_ref10

不管是哪个实现,我们只看ed25519_ref10_seckey_expand和ed25519_ref10_pubkey

或者ed25519_donna_seckey_expand和ed25519_donna_pubkey

我自己的理解,TOR的onion只需要做数字签名,不分发公钥,因为不需要交换AES密钥!

所以在修改torrc的时候,增加一个User 你的用户名,就可以在windows下创建onion域名了

到此,win10下,建立onion站点是可行的!

张怀义 at 2020-04-05
4

说了这么多,干脆把TOR代码讲一遍好了。。。

入口函数叫tor_run_main,在

C:\Users\张怀义\tor-alpha-3.04.1\src\app\main\main.c

C:\Users\张怀义\tor-alpha-3.04.1\src\app\main\subsystem_list.c 遍历这文件里所有的子系统,调用子系统的initialize函数和add_pubsub函数。和linux内核的子系统类似,使用了订阅发布模式,golang用的是CSP模型,这里是actor模型!

我假设你们学过actor模型,现在只看mainloop_event_new和mainloop_event_postloop_new相关代码!

张怀义 at 2020-04-05
5

说了这么多,干脆把TOR代码讲一遍好了。。。

入口函数叫tor_run_main,在

C:\Users\张怀义\tor-alpha-3.04.1\src\app\main\main.c

C:\Users\张怀义\tor-alpha-3.04.1\src\app\main\subsystem_list.c 遍历这文件里所有的子系统,调用子系统的initialize函数和add_pubsub函数。和linux内核的子系统类似,使用了订阅发布模式,golang用的是CSP模型,这里是actor模型!

我假设你们学过actor模型,现在只看mainloop_event_new和mainloop_event_postloop_new相关代码!

张怀义 at 2020-04-05
6

列个提纲:

TOR如何去连目录服务器?

TOR如何建立环路?环路三要素【守卫节点】【中间节点】【出口节点】

【可选】网桥是什么?meek,obfs4等

onion站点,DNS处理逻辑

自己喜欢的讲解内容方向

1.TOR 启动监听端口9150 等【HS服务会启动其他端口】

2.TOR的监听端口accept以后,通知readable,调用了read handle函数

3.TOR的read以后,去调用对应的write handle

4.把得到的数据,按link返回

5.如果涉及到了onion域名,如何访问的呢?

张怀义 at 2020-04-05
7

参考资料:https://tor.stackexchange.com/questions/672/how-do-onion-addresses-exactly-work

1.服务器通过ed25519算法得到一对密钥【非对称加密算法】

2.服务器随机选取n个tor节点作为介绍点

3.服务器通过TOR回路,告诉这些节点自己的公钥【介绍点没法知道服务器地址】

4.服务器把自己的公钥和这些介绍点打包成一个匿名服务描述符

5.服务器用自己的私钥签名这个描述符

6.服务器上传描述符到目录服务器【DHT】

7.客户端,从其他途径知道了具体的onion地址

8.客户端发送请求给DHT

9.如果这个hash存在,返回服务器的公钥和介绍点IP

10.客户端随机选择一个tor节点作为会和点,并告诉这个汇合点一次性密钥。

11.客户端创建一个介绍信,包含汇合点的地址 和一次性密钥并用服务器的公钥加密

12.客户端通过TOR回路,发给介绍点,并要求它转发给服务器【介绍点不能知道客户端地址,会和点IP】

13.服务器收到介绍信,用自己的私钥解密,知道会和点地址和一次性密钥。

14.服务器通过TOR回路,发送一次性密钥给会合点【汇合点即不知道客户端IP,也不知道服务器IP】

15.汇合点告诉客户端,连接完成

16.客户端和服务端可以互相通信了【一共6跳,服务器和客户端互相不知道对方的IP】

思考题:如果介绍点都挂了,不在线怎么办?

如果服务器重启的话,介绍点是不是就找不到服务器地址,需要重新生成.onion了?

张怀义 at 2020-04-05
8

以上就是onion地址如何工作的

张怀义 at 2020-04-05
9

参考资料:https://github.com/Yawning/obfs4/blob/master/doc/obfs4-spec.txt

obfs4网桥协议规范

重点看第四节和第五节,分别是握手阶段和传输阶段,整个过程类似TLS1.3协议,我不再啰嗦了

大致过程讲下,

客户端和服务端通过curve25519椭圆曲线算法,计算PSK得到对称密钥secretInput,

通过HKDF 算法计算secretInput, 得到对称加密的密钥 记作sec_key,

数据传输阶段,使用了secretbox加密,使用密钥 sec_key

只需要看代码 https://github.com/Yawning/obfs4/blob/master/transports/obfs4/obfs4.go 就可以了

从 newObfs4ClientConn函数看起,clientHandshake函数会发起握手

hs.generateHandshake()生成握手请求,发送给服务端

服务端收到请求hs.parseClientHandshake得到PSK 也就是seed

okm := ntor.Kdf(seed, framing.KeyLength*2) 根据seed 计算HKDF,作为对称加密的密钥

返回severhello,客户端解析n, seed, err := hs.parseServerHandshake(conn.receiveBuffer.Bytes()) 得到相同的seed,并和上面一样计算HKDF,作为对称加密的密钥

张怀义 at 2020-04-05
11

@2read #11 谢谢,我在研究.onion的工作机制和相关代码实现而已,不需要自己发布一个网站

张怀义 at 2020-04-05
12

参考资料:https://trac.torproject.org/projects/tor/wiki/doc/meek

meek网桥协议规范

大致原理讲下,通过CDN来隐藏自己的真实IP,用CDN来转发我的代理请求。在外界看来,就是普通的https浏览网页。

重点看下Amazon CloudFront 这个章节,根据这个章节配置服务端

ClientTransportPlugin meek exec ./meek-client –url=https://d111111abcdef8.cloudfront.net/ –front=d36cz9buwru1tt.cloudfront.net –log meek-client.log

记得最后要执行这样的一句话!!!并把生成的meek 网桥信息,填入客户端,看 How to change the front domain 这个章节,客户端需要修改网桥为自定义网桥!!!

张怀义 at 2020-04-05
13

onion域名的官方文档规范V3

https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt

tor的资料很少有中文的,我都是在tor的wiki上自己大概翻译了一下

好像也没有翻译多少,更多是告诉大家,哪些是重点,没必要一行行去读了

张怀义 at 2020-04-05
14

后生可畏。。。

看了这么多?

霏艺Faye at 2020-04-05
15

@立紗Lisa #16 谢谢lisa大神的夸奖!!!

张怀义 at 2020-04-06
16