v2ray / discussion

For general discussion over Project V development and usage.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

v2ray的TLS流量可被简单特征码匹配精准识别(附PoC)

p4gefau1t opened this issue · comments

这个issue应该不能算bug report,但是也没有找到合适的模板,所以没有使用模板,抱歉。

先说结论:仅凭tls client hello的cipher suite字段,就可以非常准确地将v2ray流量和正常浏览器流量区分开来。

PoC(来自@DuckSoft),此iptables规则可封禁所有v2ray的allowInsecureCiphers设置为false(默认设置)的出站TLS流量,而其他TLS流量不受影响:

iptables -I OUTPUT -m string --algo kmp --hex-string "|001ecca8cca9c02fc02bc030c02cc027c013c023c009c014c00a130113031302|" -j DROP

在新的版本释出之前,个人建议的缓解措施是客户端将allowInsecureCiphers设置为true。服务端建议可以拒绝所有具有此特征的TCP连接,以强迫所有客户端更新版本(但此举可能导致服务器遭到主动探测)。


下面是发现的过程和分析。

实验的启发来自下面这篇文章,其中提到了使用机器学习训练的模型可对v2ray的tls+ws流量进行识别,准确率高达0.9999

https://fr33land.net/2020/03/12/can-enable-tls-in-v2ray-help/

他训练的模型已经开源,仓库如下

https://github.com/rickyzhang82/V2Ray-Deep-Packet-Inspection

经过本地测试,可以复现。并且不限于tls+ws,对tls+vmess等组合也同样有效。其他tls流量如浏览器流量等,全程没有出现误报情况。

因此初步怀疑是v2ray使用的utls进行client hello伪造出现的问题。

https://github.com/v2ray/v2ray-core/blob/edb4fed387d27890902e7ee97aae0d97292f912b/transport/internet/tls/config.go#L176-L230

此处使用的cipher suite,可能出于安全目的,使用了一组特殊的组合,而与绝大多数浏览器不同 。为了对比,下面是utls模拟的chrome的client hello。

https://github.com/refraction-networking/utls/blob/43c36d3c1f57546d5cbb05c066df7b5a78686c51/u_parrots.go#L141-L214

抓包可以发现,对比真实的chrome与utls的client hello,两者基本一致,但与v2ray的存在较大差别,其中包括suite和extension的差别。此后,我们将utls的chrome的cipher suite patch到v2ray中后,此模型无法识别v2ray的tls流量

所以我们可以初步认为,模型很可能是学习了tls client hello的特征,导致流量被识别。

但实际上,识别tls client hello并不需要使用机器学习的方法,简单的DPI即可实现,因此在gfw部署的成本很低。并且,由于这组cipher suites太过特殊,我们可以仅凭cipher suites进行准确识别。

顺带一提,cipher suites列表在代码中的顺序,和实际的发送的client hello中的顺序似乎是相反的,不知这是有意为之还是bug。

个人建议,客户端依旧使用utls,但应该伪造chrome/firefox的浏览器client hello,AllowInsecureCiphers仅对服务器生效,由服务器限制不安全的cipher suites。

因为 Cipher Suite 特征过于明显,随手撸一个从 0x90 偏移量开始的 memcmp 都能精准高效识别:
图片

“特征码”:cca8cca9c02fc02bc030c02cc027c013c023c009c014c00a130113031302

甚至可以利用 iptables 进行明文匹配……其他的 PoC 方式请大家自己开动脑筋……

代码参考:

iptables -I OUTPUT -m string --algo kmp --hex-string "|001ecca8cca9c02fc02bc030c02cc027c013c023c009c014c00a130113031302|" -j DROP

Upvote, and similar to v2ray/v2ray-core#1660, v2ray/v2ray-core#2098

Confirmed with V2ray 4.23 on Archlinux:

image

image

EVEN The server is not being configured to use TLS.
The issue occurs on the INITIAL TLS handshake packet. Which means the buggy Client Hello Message will always be sent if AllowInsecureCiphers is set to false, which is the default value

I suggest this issue go top priority.

This issue has been addressed by Tor and Naiveproxy. It's great that someone realize this undermined problem in v2ray. However, it's not that easy to completely remove the attack surface unless we integrate related components of a popular browsers and keep it up-to-date, like what Tor and Naiveproxy do. (Because if we take a closer look, the connection behavior could be a strong fingerprint).

Btw, generally speaking, it's simply a fingerprint of most go programs. So it depends on what we want mock. Apparently go programs have different connection behavior than Firefox, for example.

IMO, use TLS library's default setting would resolve this problem: We're same as other Go program in this condition.

Btw, generally speaking, it's simply a fingerprint of most go programs. So it depends on what we want mock. Apparently go programs have different connection behavior from Firefox, for example.

IMO, use TLS library's default setting would resolve this problem: We're same as other Go program in this condition.

Agreed

There is an utls enabled version for fingerprint issue, you need to inspect the codes by yourself to ensure it's safe.
https://github.com/emc2314/v2ray-core

you don't need machine learning to find something unique in plain words. TLS protocol itself is plaintext in the network.

Different browser/version has their own unique fingerprints. There's a project collecting TLS fingerprints and do the statistic works. see https://tlsfingerprint.io/

IMO, use TLS library's default setting would resolve this problem: We're same as other Go program in this condition.

Btw, generally speaking, it's simply a fingerprint of most go programs. So it depends on what we want mock. Apparently go programs have different connection behavior from Firefox, for example.

Agreed. V2ray misused utls library, and blocked some "insecure" ciphers, and make it easy to detect.

The easiest way to solve this is to use net/tls default settings. But I think the best way to fix this is to use utls anti-fingerprinting features correctly.

https://github.com/refraction-networking/utls

我倒是好奇当初是基于何种考虑,要增加这么一个默认的CipherSuites列表呢?

如果客户端与服务器都处于自己控制之下, 不管CipherSuites改不改,协商出来的只会是TLS 1.3的那三件套。如果服务器本身不安全,那改这么个CipherSuites列表又能起到什么鸟用?

我怀疑当初加进这个的人,根本就没弄清楚TLS握手的过程。 v2ray/v2ray-core#2477 就是个最近的例子。

另外我再补充一点,golang默认设置里面,ClientSessionCache也是没有的,建议一并拿掉。光把那个CipherSuites列表拿掉,还是会比一般的golang客户端的ClientHello多一个session_ticket的extension。

补充第二点,目前的alpn设置也非常奇葩。好几个地方设置成单有h2。试问有哪些主流应用会在客户端设置单有h2的alpn?这也可算是一个显著特征。

@klzgrad you may be interested

图片
v2ws + tls(apache2) 复现成功,本来还以为套 apache2 没事,没想到直接传递了......

图片
v2ws + tls(apache2) 复现成功,本来还以为套 apache2 没事,没想到直接传递了......

所以说,这次的问题是客户端当了猪队友,发了一个特征极强的 Client Hello 给服务器

图片
v2ws + tls(apache2) 复现成功,本来还以为套 apache2 没事,没想到直接传递了......

所以说,这次的问题是客户端当了猪队友,发了一个特征极强的 Client Hello 给服务器

确实,可以考虑把 v2 换掉了,TLS 的替换方案也不少(指比较冷门的)

@studentmain But since very few apps using Go, it is still kind of easy to detect from it's TLS fingerprint.

确实,可以考虑把 v2 换掉了,TLS 的替换方案也不少(指比较冷门的)

This defect also applies to Trojan which openssl + customized client TLS configuration.

Traditional Https proxy is also potentially detectable because of small handshake packages in TLS.

用 V2rayN v3.18 + V2ray-core v4.23.1 测试
使用 TLS 的多种配置中,仅发现 vmess+h2+tls 默认没有 Client Hello
服务端抓包命令 tcpdump -ni eth0 "tcp port 443 and (tcp[((tcp[12] & 0xf0) >> 2)] = 0x16)"

目前的问题不在于使用 Go 或者是其它语言/库来实现 TLS

V2ray-Core 当前的问题是: 在不开 AllowInsecureCiphers 时,硬编码了几个安全的 TLS 加密套件导致 Client Hello 中的 Ciphers 成为 V2ray 的流量指纹

问题的本身不在于 TLS 握手包特征,而是 V2ray 错误地使用了 TLS 库

顺带一提,cipher suites列表在代码中的顺序,和实际的发送的client hello中的顺序似乎是相反的,不知这是有意为之还是bug。
-->
这个应该是为了优先使用TLS1.3

现在的情况是V2用的TLS的库是Go语言的TLS库,所以肯定在行为上和OpenSSL有一定区别。现在可以做的就是首先先改成使用Go语言默认的加密套件。
长期的来看,如果想解决这个问题比较容易的方法还是在客户端本地用使用了OpenSSL库的程序转发一下这个流量。比如 ncat -l localhost 1234 --sh-exec "ncat --ssl v2ray.example.com 1234"

私以为使用Go的默认TLS库已经足够,毕竟考虑到Go的默认TLS库的使用范围足够广,理应不会直接将所有Go程序一并干掉……所以只要和其他广泛使用的Go程序的TLS特征一致或相似,就足够了。不过本地整个OpenSSL当然是更好的。

reproduced
image

@p4gefau1t @DuckSoft

Great jobs, guys! I'm not an expert on TLS. I really appreciate your finding this!

  • IMO, V2ray uses the stock version TLS implementation from Golang. It doesn't use utls.
  • The V2Ray client side needs to blend in its TLS traffic as whatever popular web browser client in mainland China. In this way, people have a better chance to circumvent GFW.
  • The V2Ray server side needs to defend active probe from CCP, which is reported by shadowshock researcher in here. The gfw.report is down now. But you can access it from archive.

So far, I see the proposal only address the client side. Any concern on server side that can be probed by CCP due to TLS handshake leaking?

@p4gefau1t @DuckSoft

Great jobs, guys! I'm not an expert on TLS. I really appreciate your finding this!

* IMO, V2ray uses the stock version TLS implementation from Golang. It doesn't use [utls](https://github.com/refraction-networking/utls).

* The V2Ray client side needs to blend in its TLS traffic as whatever popular web browser client in mainland China. In this way, people have a better chance to circumvent GFW.

* The V2Ray server side needs to defend active probe from CCP, which is reported by [shadowshock researcher in here](https://web.archive.org/web/20200416083158/https://gfw.report/). The gfw.report is down now. But you can access it from archive.

So far, I see the proposal only address the client side. Any concern on server side that can be probed by CCP due to TLS handshake leaking?

To be honest, I contributed only to validation and implementation, and the original idea was from @p4gefau1t, so he's the very superb man. Server side may also be probed, but under the shelter of nginx/caddy, the fingerprint will be eliminated. As long as you keep your endpoint address secret, GFW can't discover any difference.

But the cruel thing is: It's not server's fault. So far it seems that, it's your client that stirred trouble and shout at your server: "come on boy, I need to circumvent GFW!" I don't know how can this affect servers, but I can see someone will broadcast this very payload to scan competitors' servers. That shall also be considered.

Websocket + TLS +Nginx路径分流,也受影响吗?

Websocket + TLS +Nginx路径分流,也受影响吗

影响。

看了下我的本地配置
"tlsSettings": {
"serverName": "123",
"allowInsecure": false,
"allowInsecureCiphers": true,
"alpn": [
"http/1.1"
],
"certificates": [],
"disableSystemRoot": false
}
},

还好以前就加了"allowInsecureCiphers": true, 第三方gui工具貌似一般不会生成这个配置项

如果本地配置了"allowInsecureCiphers": true ,流量就不会有上面说的特征,服务端因为墙不知道Nginx分流的路径,没法主动探测,可以这样理解么?

看了下我的本地配置
"tlsSettings": {
"serverName": "123",
"allowInsecure": false,
"allowInsecureCiphers": true,
"alpn": [
"http/1.1"
],
"certificates": [],
"disableSystemRoot": false
}
},

还好以前就加了"allowInsecureCiphers": true, 第三方gui工具貌似一般不会生成这个配置项

如果本地配置了"allowInsecureCiphers": true ,流量就不会有上面说的特征,服务端因为墙不知道Nginx分流的路径,没法主动探测,可以这样理解么?

GUI 工具,就我目前所知,似乎只有 Qv2ray 有这个配置选项。
流量特征还是有的,会降级成一般 Golang 程序的特征,比之前的巨扎眼的特征会好很多。
主动探测不知道路径没法探测,这个是对的。

问题的本身不在于 TLS 握手包特征,而是 V2ray 错误地使用了 TLS 库

True. As long as we use a no-handshake, encrypted, and obfuscated protocol over TLS, the only attack surface will be reduced to the plaintext handshake package of TLS.

We don't necessarily need to mimic a popular browser in China, since it's expensive to keep the behavior up-to-date. The default configuration of Go is sufficient.

Note: if you choose to allowinsecurecipher, it's highly recommended to enable the encryption of the capsulated protocol (i.e. vmess).

吃我一记洛阳铲:
https://gist.github.com/clowwindy/5947691#file-ssl-md

The identification of server is needed IMO. We don't want our traffic passing through an impersonated server.

Clowwindy's assumption was based on that switching IP addresses was much easier than switching certificates, which was true in 2013 but not quite so in 2020 when we have let's encrypt. It's not quite possible to ban the Let's Encrypt's root certificate. But it does make your traffic more suspicious.

为了方便大部分 v2ray 用户, 我刚刚编译了一个基于 4.23.1 的 utls 魔改版的 windows release 出来. 使用了 ChromeSafari 的 ClientHello 信息, 在 tlsfingerprint 的统计上分别排名第一和第五. 欢迎大家抓包测试.

为了方便大部分 v2ray 用户, 我刚刚编译了一个基于 4.23.1 的 utls 魔改版的 windows release 出来. 使用了 ChromeSafari 的 ClientHello 信息, 在 tlsfingerprint 的统计上分别排名第一和第五. 欢迎大家抓包测试.

LGTM, but uTLS probably still leaks some info from its dynamic behavior (cipher negotiation, key exchange).

我刚刚在 go 1.14.3 环境下编译最新的 v2ray-core 版本 4.23.2,用于 Windows 系统下的二进制文件,内含最新版本 geoip.dat 和 geosite.dat,已打包成 zip 文件可供下载。

用于 32 位 windows 系统的下载地址:
https://dl.lamp.sh/files/v2ray_windows_386.zip

用于 64 位 windows 系统的下载地址:
https://dl.lamp.sh/files/v2ray_windows_amd64.zip

欢迎用新版本继续测试。

与此同时,我已经提交了 pull request 给下面的 2 个项目,升级了 v2ray-core 到 4.23.2:
https://github.com/shadowsocks/v2ray-plugin (Merged)
https://github.com/p4gefau1t/trojan-go (Merged)

Does the merge v2ray/v2ray-core#2512 changes behaviour on the server side? I mean, allowInsecureCiphers should take effect on the server side to maintain security, while client side acts like other Go applications.

commented

Does the merge v2ray/v2ray-core#2512 changes behaviour on the server side? I mean, allowInsecureCiphers should take effect on the server side to maintain security, while client side act like other Go applications.

Yes, Now you can't use. This part needs to be redesigned

Websocket + TLS +Nginx路径分流,也受影响吗

影响。

如果tls走nginx呢,就是一个真的https的网站,顺便开一个websocket反向代理到v2ray上面,应该就无法识别了吧。

Websocket + TLS +Nginx路径分流,也受影响吗

影响。

如果tls走nginx呢,就是一个真的https的网站,顺便开一个websocket反向代理到v2ray上面,应该就无法识别了吧。

这是网络协议方面的问题,不单纯是应用方面的问题。即使是nginx反向代理到v2ray上面也会有这个流量特征的。

与此同时,我已经提交了 pull request 给下面的 2 个项目,升级了 v2ray-core 到 4.23.2:
https://github.com/shadowsocks/v2ray-plugin (Merged)
https://github.com/p4gefau1t/trojan-go (Waiting Merge)

感谢,已合并。但是实际上trojan-go仅仅使用了geoip和geosite的protobuf格式,trojan-go和v2ray的TLS实现无关,并且在早期版本trojan-go就做了client hello的伪造工作,所以其实并不受这个问题的影响。

这个特征是不是只能用来反向阻断墙内的访问,不能作为封禁墙外服务器的依据。

这个特征是不是只能用来反向阻断墙内的访问,不能作为封禁墙外服务器的依据。

不正确。两者皆可。

为了方便大部分 v2ray 用户, 我刚刚编译了一个基于 4.23.1 的 utls 魔改版的 windows release 出来. 使用了 ChromeSafari 的 ClientHello 信息, 在 tlsfingerprint 的统计上分别排名第一和第五. 欢迎大家抓包测试.

LGTM, but uTLS probably still leaks some info from its dynamic behavior (cipher negotiation, key exchange).

Could you give me more information about it?

为了方便大部分 v2ray 用户, 我刚刚编译了一个基于 4.23.1 的 utls 魔改版的 windows release 出来. 使用了 ChromeSafari 的 ClientHello 信息, 在 tlsfingerprint 的统计上分别排名第一和第五. 欢迎大家抓包测试.

LGTM, but uTLS probably still leaks some info from its dynamic behavior (cipher negotiation, key exchange).

Could you give me more information about it?

He is talking about a very old debate between me and @klzgrad. I have to admit there are some concern there but I do think the risk is quite acceptable.

这个特征是不是只能用来反向阻断墙内的访问,不能作为封禁墙外服务器的依据。

不正确。两者皆可。

原文的表述有点绕口,但它确实不能作为封禁国外 IP 的依据,因为你可以向任意国外 IP 发送这种特定的 ClientHello,从而误伤任何无关网站。@p4gefau1t

但是可作为封禁的依据之一。例如检测到大量IP发出具有此特征的连接到服务器上,结合主动探测,可以判断IP是否是v2ray节点。

事实上,在久远以前,就有大量向一个主机发送包含敏感词的连接,借GFW之手完成DDoS的攻击方法。

为了方便大部分 v2ray 用户, 我刚刚编译了一个基于 4.23.1 的 utls 魔改版的 windows release 出来. 使用了 ChromeSafari 的 ClientHello 信息, 在 tlsfingerprint 的统计上分别排名第一和第五. 欢迎大家抓包测试.

LGTM, but uTLS probably still leaks some info from its dynamic behavior (cipher negotiation, key exchange).

Could you give me more information about it?

He is talking about a very old debate between me and @klzgrad. I have to admit there are some concern there but I do think the risk is quite acceptable.

So there seems to be 2 solutions for this.

  1. Use original Go TLS fingerprint
  2. Use uTLS with Safari fingerprint (since all websocket package can't use h2 due to issues in Golang net/http package) Ref: v2ray/v2ray-core#2098 (comment)
    Actually none of them are perfect, so we could wait until websocket+h2 being implemented.

请问tcp+tls是否会被识别出来?

请问tcp+tls是否会被识别出来?

只要使用到了tls,那就会有这样的特征

请问有办法在server端禁止 allowInsecureCiphers:false 的连接吗?

请问有办法在server端禁止 allowInsecureCiphers:false 的连接吗?

没有。这是握手第一个包。

请问有办法在server端禁止 allowInsecureCiphers:false 的连接吗?

开头那个 iptables 改改就可以了

@cjwddtc

如果tls走nginx呢,就是一个真的https的网站,顺便开一个websocket反向代理到v2ray上面,应该就无法识别了吧。

这个特征是client发给server的握手包的特征,跟你服务器是什么配置没关系。

quic+tls有人试过有类似特征吗

commented

有人总结下吗, 怎么办,, 新的release版本(v4.23.2) 修复了没.
另: 感谢付出

commented

有人总结下吗, 怎么办,, 新的release版本(v4.23.2) 修复了没.
另: 感谢付出

v2ray/v2ray-core#2510
v2ray/v2ray-core#2512
v2ray/v2ray-core#2518
可以理解为新版本把特征改成和大多数Golang程序一样了,初步解决
下一步应该会引入uTLS,特征向主流浏览器靠拢

这个特征是不是只能用来反向阻断墙内的访问,不能作为封禁墙外服务器的依据。

不正确。两者皆可。

原文的表述有点绕口,但它确实不能作为封禁国外 IP 的依据,因为你可以向任意国外 IP 发送这种特定的 ClientHello,从而误伤任何无关网站。@p4gefau1t

但是可作为封禁的依据之一。例如检测到大量IP发出具有此特征的连接到服务器上,结合主动探测,可以判断IP是否是v2ray节点。

我想说的是,向双方发送 TCP RST 关闭可疑的连接,其实是非常高效的,而不会有上述误伤,也不必进行我们尚不可知的主动探测。

事实上,在久远以前,就有大量向一个主机发送包含敏感词的连接,借GFW之手完成DDoS的攻击方法。

(off-topic)没有理解上下文的关系。但你可能记错了,这个攻击是伪造源 IP 进行 DNS 反射攻击:https://gfwrev.blogspot.com/2009/11/gfwdns.html

感谢科普。但是我个人观点还是认为,gfw非常可能利用此特征(或者已经在利用此特征),在敏感时期,采取激进策略封禁大量IP地址。

如果tls走nginx呢,就是一个真的https的网站,顺便开一个websocket反向代理到v2ray上面,应该就无法识别了吧。

你已经离题了,客户端发送的 ClientHello 不取决于服务端。@cjwddtc

所以是不是等着客户端更新修复就可以了?

如果tls走nginx呢,就是一个真的https的网站,顺便开一个websocket反向代理到v2ray上面,应该就无法识别了吧。

你已经离题了,客户端发送的 ClientHello 不取决于服务端。@cjwddtc

所以是不是等着客户端更新修复就可以了?

v2rayNG已经更新了

commented

如果tls走nginx呢,就是一个真的https的网站,顺便开一个websocket反向代理到v2ray上面,应该就无法识别了吧。

你已经离题了,客户端发送的 ClientHello 不取决于服务端。@cjwddtc

所以是不是等着客户端更新修复就可以了?

v2rayN更新方法 2dust/v2rayN#844

对于PC上的其它客户端,更新方法类似

如果tls走nginx呢,就是一个真的https的网站,顺便开一个websocket反向代理到v2ray上面,应该就无法识别了吧。

你已经离题了,客户端发送的 ClientHello 不取决于服务端。@cjwddtc

所以是不是等着客户端更新修复就可以了?

v2rayN更新方法 2dust/v2rayN#844

对于PC上的其它客户端,更新方法类似

嗯 刚看到了 谢谢 路由和服务器已经全部更新了

shadowsocks+v2ray-plugin+tls+ws是否有这个问题呢

@tomac4t 的表格也证明了,v4.23.2并没有真正解决TLS指纹独特性的问题。v4.23.2指纹的出现次数小于100,估计都是v2ray用户提交的。原因如我前面提到过的,alpn采用了特殊值,以及使用了ClientSessionCache。

以下iptables规则可以精准阻断使用了TLS连接方式的最新v4.23.2版本v2ray(无论是ws还是h2还是tcp模式),并且不影响其他golang程序:

iptables -N GOLANG
iptables -A GOLANG -m string --algo bm ! --hex-string "|0010000e000c02683208687474702f312e31|" -j DROP
iptables -A OUTPUT -m string --algo bm --hex-string "|0026c02fc030c02bc02ccca8cca9c013c009c014c00a009c009d002f0035c012000a130113031302|" -j GOLANG

有兴趣的同学可以试试。

鉴于是否使用uTLS还在讨论/测试中,期盼官方能尽快合并 v2ray/v2ray-core#2521 或类似的补丁,先解燃眉之急。毕竟敏感日期将至,谁都不知道墙更新规则的速度有多快。

@nicholascw

感觉是客户端发出来的,,只要客户端不升级就没办法彻底解决吧

而且,,vmess有相同的问题吧,用不到半天就被墙了,换WS用了几天就没事

@tomac4t 的表格也证明了,v4.23.2并没有真正解决TLS指纹独特性的问题。v4.23.2指纹的出现次数小于100,估计都是v2ray用户提交的。原因如我前面提到过的,alpn采用了特殊值,以及使用了ClientSessionCache。

以下iptables规则可以精准阻断使用了TLS连接方式的最新v4.23.2版本v2ray(无论是ws还是h2还是tcp模式),并且不影响其他golang程序:

iptables -N GOLANG
iptables -A GOLANG -m string --algo bm ! --hex-string "|0010000e000c02683208687474702f312e31|" -j DROP
iptables -A OUTPUT -m string --algo bm --hex-string "|0026c02fc030c02bc02ccca8cca9c013c009c014c00a009c009d002f0035c012000a130113031302|" -j GOLANG

有兴趣的同学可以试试。

鉴于是否使用uTLS还在讨论/测试中,期盼官方能尽快合并 v2ray/v2ray-core#2521 或类似的补丁,先解燃眉之急。毕竟敏感日期将至,谁都不知道墙更新规则的速度有多快。

@nicholascw

4.23.2成功复现

commented

感觉是客户端发出来的,,只要客户端不升级就没办法彻底解决吧

客户端是会升级的 解决的思路应该是尽量分散特征 #706

commented

而且,,vmess有相同的问题吧,用不到半天就被墙了,换WS用了几天就没事

ws不也是vmess吗

而且,,vmess有相同的问题吧,用不到半天就被墙了,换WS用了几天就没事

ws不也是vmess吗

只是用語不統一的問題,他說的 vmess 應該是 vmess over tcp。(換成說 tcp 也會有人問:ws 不也是 tcp 嗎?)

ws = web socket

commented

而且,,vmess有相同的问题吧,用不到半天就被墙了,换WS用了几天就没事

ws不也是vmess吗

只是用語不統一的問題,他說的 vmess 應該是 vmess over tcp。(換成說 tcp 也會有人問:ws 不也是 tcp 嗎?)

应该是,他指的可能是vmess over tcp换成vmess over ws

ws倒也是tcp,只是很有可能是vmess over ws over tls over tcp

ws倒也是tcp,只是很有可能是vmess over ws over tls over tcp

討論 V2Ray 的承載方式時,一般說 tcp 和 ws 就夠了,因為 streamSettings 裡就是這兩個字。
vmess over "ws over tls" over tcp 可以簡寫為 vmess over wss

而且,, vmess有相同的问题吧,用不到半天就被墙了,换WS用了几天就没事

ws不也是vmess吗

只是用语不统一的问题,他说的vmess应该是vmess over tcp。(换成说tcp也会有人问:ws不也是tcp吗?)

应该是,他指的可能是vmess over tcp换成vmess over ws

ws倒也是tcp,只是很有可能是vmess over ws over tls over tcp

是,就是vmess的tcp模式换ws模式就好了

commented

ws = web socket

我指的是在v2ray中ws=vmess over ws,所以“ws不也是vmess吗”。。。

这个issue我很早之前就提过,但当时被开发者忽略了,就很无语😓。详见:#128

我在 Android 上使用 v2ray ,客户端是 Kitsunebi ,因为开发者很久没更新了,本来想参考 @xiaokangwang 的方法使用 ncat 转发 tls ,但我没找到使用 ncat 为域名指定 ip 的方法,直接连接 cloudflare 默认给出的 ip 又太慢了,于是想到在 Termux 中运行 Nginx 反代 ws over tls , tls 数据由 Nginx 加密/解密, v2ray 只负责处理 ws 部分,这样应该可以防止被识别了吧
Nginx 的配置如下

worker_processes auto;
events {}
http {
    upstream v2ray {
	server 源站或cdnip:443;
	#可以加入多个 cdnip 达到负载均衡的效果
    }
    server {
	listen 8080;
	server_name _;
	location / {
	    proxy_ssl_protocols TLSv1.3;
	    proxy_http_version 1.1;
	    proxy_ssl_server_name on;
	    proxy_ssl_name 源站域名;
	    proxy_set_header Host 源站域名;
	    proxy_pass https://v2ray/v2ray路径;
	    proxy_redirect off;
	    proxy_set_header Upgrade $http_upgrade;
	    proxy_set_header Connection "upgrade";
	    #proxy_ssl_ciphers 自定义ciphers;
	}
    }
}

v2ray 需要放行源站域名,使用纯 ws 连接到 127.0.0.1:8080 即可

@rhjdvsgsgks 对,这样用的话,截取到的TLS ClientHello是nginx的特征。

@darhwa 我试了下上面的,,,还是原来的啊,没有用,测试版本4.23.1
这个是客户端发起就是这样子了,感觉和服务器用什么关系不大,等于说未来的话,墙的话是直接给你墙了,你服务器都收不到数据,或者墙了回程,服务器收到数据,返回的响应被墙吞了,客户端收不到来自服务器的响应数据内容
image

TLS 1.3->以TLS_AES_128_GCM_SHA256优先
TLS 1.2->以TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256优先
这样的Handshake确实特征明显。
另外V2RayNG和Trojan Igniter似乎没调用AArch64 AES指令集,导致这两个VPN App很耗电。我在shadowsocks-android开了Issue提醒,shadowsocks-android才在最新版加入AArch64 AES指令集支持。
Chrome for Android 在CPU不支持AES指令集的情况下,优先使用ChaCha20;在CPU支持AES指令集的情况下,优先使用AES-128-GCM。
难怪最近V2Ray TLS和Trojan Igniter的速度都慢了下来。

,,手机cpu就不支持aes这个指令集吧我记得,所以手机默认用的是chacha20

,,手机cpu就不支持aes这个指令集吧我记得,所以手机默认用的是chacha20

执行cat /proc/cpuinfo,有aes是支持。

我看了下我的手机没有
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt evtstrm

Android 10和最新版Chrome的Cipher suites是这样的。
Screenshot_20200601-024510_Chrome

我看了下我的手机没有
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt evtstrm

如果CPU不支持AES,那么Chrome for Android的TLS握手应该是这样的,就是ChaCha20算法优先:
// TLS 1.3
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
//TLS 1.2

如果你想知道它的指纹如何,这就是:https://tlsfingerprint.io/id/4091e07593dd138c (nginx/1.18.0 built with OpenSSL 1.1.1d)同样非常罕见,cc @rhjdvsgsgks

@tomac4t 我刚才试了我用的浏览器的指纹( macOS 10.15.4 + edge chromium 83.0.478.37),发现不算特别流行的指纹,而且只要作业系统版本和浏览器版本不同,指纹就会不一样。我想问题不在罕见而在于 "固定",V2Ray 只要模彷一个常见浏览器的指纹加上使用者各自的作业系统特征就足以形成混淆。至于浏览器指纹是否与最新版一致则无所谓,只要地球上还有人在用那个版本就行。

@tomac4t 简单地说,"合理"的指纹是前提,我想表达的是不必執着于是否罕见,只要能形成混淆就好。

@tomac4t 的表格也证明了,v4.23.2并没有真正解决TLS指纹独特性的问题。v4.23.2指纹的出现次数小于100,估计都是v2ray用户提交的。原因如我前面提到过的,alpn采用了特殊值,以及使用了ClientSessionCache。

以下iptables规则可以精准阻断使用了TLS连接方式的最新v4.23.2版本v2ray(无论是ws还是h2还是tcp模式),并且不影响其他golang程序:

iptables -N GOLANG
iptables -A GOLANG -m string --algo bm ! --hex-string "|0010000e000c02683208687474702f312e31|" -j DROP
iptables -A OUTPUT -m string --algo bm --hex-string "|0026c02fc030c02bc02ccca8cca9c013c009c014c00a009c009d002f0035c012000a130113031302|" -j GOLANG

有兴趣的同学可以试试。

鉴于是否使用uTLS还在讨论/测试中,期盼官方能尽快合并 v2ray/v2ray-core#2521 或类似的补丁,先解燃眉之急。毕竟敏感日期将至,谁都不知道墙更新规则的速度有多快。

@nicholascw

@darhwa

"0010000e000c02683208687474702f312e31" 这一段是alpn的"特征码"? 同样是v4.23.2,但是并没有这一段.

Cipher Suites 的 这一段 0026c02fc030c02bc02ccca8cca9c013c009c014c00a009c009d002f0035c012000a130113031302 倒是有的.

Windows 7+最新版Chrome的Cipher suites如下:
// 不支援TLS 1.3
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_256_GCM_SHA384
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
Windows 7+最新版Firefox:
TLS_AES_128_GCM_SHA256
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBCSHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA

v2ray/v2ray-core#2510
Go TLS 1.2的TLS_ECDHE_RSA和TLS_RSA,優先使用3DES-SHA,其次使用AES-128-CBC-SHA。3DES省電但性能很低。在Windows 10+i5 2300執行openssl speed desopenssl speed aes-128-cbc,3des的加密速度僅有40MB/秒。AES尤其是AES-GCM計算量大,需要x86/ARM AES指令集的輔助。許多VPN App,如Igniter,V2RayNG,AnyConnect都沒有使用AArch64 AES指令集,導致計算AES(尤其是AES-GCM)非常耗電。

@darhwa 我试了下上面的,,,还是原来的啊,没有用,测试版本4.23.1
这个是客户端发起就是这样子了,感觉和服务器用什么关系不大,等于说未来的话,墙的话是直接给你墙了,你服务器都收不到数据,或者墙了回程,服务器收到数据,返回的响应被墙吞了,客户端收不到来自服务器的响应数据内容

@1265578519 阅读理解,请阅读理解。他的流量是 v2ray-client --> nginx --> 受审查的网络 --> v2ray-server

如果你想知道它的指纹如何,这就是:https://tlsfingerprint.io/id/4091e07593dd138c (nginx/1.18.0 built with OpenSSL 1.1.1d)同样非常罕见,cc @rhjdvsgsgks (Edited: 严格来说,我只设置了 proxy_pass https://example.com/,没有设置 proxy_ssl_name,也造成了指纹的不同。这是标准的 OpenSSL 指纹:https://tlsfingerprint.io/id/c68a41a8040cfe06 ;这是对比 https://tlsfingerprint.io/compare/4091e07593dd138c/c68a41a8040cfe06 ,细小的参数的不同其结果是完全不同的)

Nginx Version: nginx/1.14.2

Nginx Config:

location /url/ {
      proxy_redirect off;
      proxy_pass https://upstream-name/url/;
      proxy_http_version 1.1;
      proxy_ssl_protocols TLSv1.2 TLSv1.3;
      proxy_ssl_server_name on;
      proxy_ssl_name www.example.com;
      proxy_set_header Host www.example.com;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_read_timeout 600s;
      proxy_send_timeout 600s;
      proxy_connect_timeout 600s;
    }

TLS fingerprint:
https://tlsfingerprint.io/id/c68a41a8040cfe06

It is exactly the STD OpenSSL fingerprint.

是否可以將特徵碼使用randomchoice來進行隨機發送來混淆呢?

是否可以將特徵碼使用randomchoice來進行隨機發送來混淆呢?

Randomly generated sequence is never intended for obfuscation but for encryption.

@icebluey

"0010000e000c02683208687474702f312e31" 这一段是alpn的"特征码"? 同样是v4.23.2,但是并没有这一段.

你观察到的现象没错。所以,请再想想第二行的感叹号的作用。

You can use https://clienttest.ssllabs.com:8443/ssltest/viewMyClient.html to test the Cipher Suites that your browser uses.

是否可以將特徵碼使用randomchoice來進行隨機發送來混淆呢?

Randomly generated sequence is never intended for obfuscation but for encryption.

I think maybe you misunderstand I mean.
I want to show I mean use the random Client Hello to obfuscate GFW.

@hzlmy2002 向吹哨人致敬一下

@tomac4t 的表格也证明了,v4.23.2并没有真正解决TLS指纹独特性的问题。v4.23.2指纹的出现次数小于100,估计都是v2ray用户提交的。原因如我前面提到过的,alpn采用了特殊值,以及使用了ClientSessionCache。

以下iptables规则可以精准阻断使用了TLS连接方式的最新v4.23.2版本v2ray(无论是ws还是h2还是tcp模式),并且不影响其他golang程序:

iptables -N GOLANG
iptables -A GOLANG -m string --algo bm ! --hex-string "|0010000e000c02683208687474702f312e31|" -j DROP
iptables -A OUTPUT -m string --algo bm --hex-string "|0026c02fc030c02bc02ccca8cca9c013c009c014c00a009c009d002f0035c012000a130113031302|" -j GOLANG

有兴趣的同学可以试试。

鉴于是否使用uTLS还在讨论/测试中,期盼官方能尽快合并 v2ray/v2ray-core#2521 或类似的补丁,先解燃眉之急。毕竟敏感日期将至,谁都不知道墙更新规则的速度有多快。

@nicholascw

http/1.1 only 的代碼:
0010000b000908687474702f312e31
h2+http/1.1 的代碼:
0010000e000c02683208687474702f312e31

你說的alpn采用了特殊值應該是http/1.1 only的情況吧。
https://tlsfingerprint.io/alpn 看,http/1.1 only 的情況也不少,爲什麼能當做特徵看?
新發布的 4.23.3 和 4.23.2 一樣的,都是http/1.1,似乎沒有要改的意思啊。

@darhwa

@icebluey 使用http/1.1 only的确实不少,但那基本都是旧版本的浏览器。golang程序使用http/1.1 only的又有多少呢?更准确地说,启用了TLS 1.3的golang程序还在用http/1.1 only的有多少呢?

我特么看着就来气,人家研究怎么上太空送人去外星,咱就天天内耗在了这些破事上!

整个页面都是在讨论技术问题,这个问题也是技术人员发现并主动提出的,并没有被gfw封锁(至少我依然在用这个问题爆出之前的版本,也没有事),我希望你不要再技术网站上讨论这种话题。

我特么看着就来气,人家研究怎么上太空送人去外星,咱就天天内耗在了这些破事上!

Why not discuss this topic?

I devote my time to this research because I'm against censorship.

My time can spend somewhere else which I think I may help create a better world.

In the absence of free speech and academic freedom, there is no way to do any scientific research.