Skip to content

Xray-core: Dynamic Chrome User-Agent for all HTTP requests by default (overwriteable through config)#5658

Merged
RPRX merged 28 commits intomainfrom
copilot/set-default-user-agent
Feb 6, 2026
Merged

Xray-core: Dynamic Chrome User-Agent for all HTTP requests by default (overwriteable through config)#5658
RPRX merged 28 commits intomainfrom
copilot/set-default-user-agent

Conversation

Copy link
Contributor

Copilot AI commented Feb 5, 2026

功能:为所有 HTTP 请求设置动态 Chrome User-Agent

将 Xray-core 中所有 HTTP 请求的 User-Agent 设为 Chrome 风格,版本号随日期动态变化。

主要改动

新增 common/utils/browser.go

  • 添加 ChromeVersion() 函数计算当前 Chrome 版本号
  • 添加 ChromeUA 变量,启动时初始化一次,供其他包直接使用
  • 策略:
    • 仅以 CPU 信息(Family + Model + PhysicalCores + LogicalCores + CacheLine)作为种子初始化伪随机数生成器
    • 从 2026.1.13(Chrome 144)开始,每次随机 25-45 天版本 +1
    • 一直往上加直到超过当前日期,然后版本 -1

添加 User-Agent 的地方

  • app/dns/nameserver_doh.go - DoH 客户端
  • app/observatory/burst/ping.go - Burst Observatory
  • app/observatory/observer.go - 普通 Observatory
  • infra/conf/transport_authenticators.go - RAW 的 HTTP 伪装
  • proxy/http/client.go - HTTP 代理客户端
  • transport/internet/grpc/dial.go - gRPC
  • transport/internet/httpupgrade/dialer.go - HTTPUpgrade
  • transport/internet/reality/reality.go - REALITY 的 SpiderX
  • transport/internet/splithttp/config.go - XHTTP/SplitHTTP
  • transport/internet/tls/ech.go - ECH DNS 查询
  • transport/internet/websocket/config.go - WebSocket

附:uTLS Chrome 指纹使用情况总结

✅ 默认使用 uTLS Chrome 指纹

位置 说明
TCP/gRPC/HTTPUpgrade/SplitHTTP/REALITY/WSS 空 fingerprint 时默认 HelloChrome_Auto
TLS ping 命令 硬编码 HelloChrome_Auto
ECH DNS 查询 硬编码 HelloChrome_Auto
DoH 客户端 硬编码 HelloChrome_Auto

❌ 使用 Go 标准 TLS

位置
Observatory (普通和 Burst)
Original prompt

将 Xray-core 里所有 HTTP 请求的 User-Agent 都设为默认 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36,其中 143 代表 2026 年 1 月,每个月增加 1


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@RPRX
Copy link
Member

RPRX commented Feb 5, 2026

@copilot XHTTP(SplitHTTP)、gRPC、WebSocket、HTTPUpgrade 被你吃了??

Copilot AI and others added 2 commits February 5, 2026 19:33
…date

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
@RPRX
Copy link
Member

RPRX commented Feb 5, 2026

@Fangliding 话说这个为啥是 proxy/http/server.go

@Fangliding
Copy link
Member

@copilot 把这个功能移到 common/utils 包下面去 用 var ChromeUA = getChromeUA() 初始化一个导出的字符串 其他包直接用这个字符串就行 省去每次计算

@Fangliding
Copy link
Member

@Fangliding 话说这个为啥是 proxy/http/server.go

plain http的正常处理流程 它要把收到的 plain http 请求头稍作修改传出去 其实这里不该改的 原样转发就好 是空就空着

@RPRX
Copy link
Member

RPRX commented Feb 5, 2026

@Fangliding 还有它对于 observatory 只改了 burst,普通的需要改吗还是说代码复用了

Copilot AI changed the title [WIP] Set default User-Agent for all HTTP requests in Xray-core feat: dynamic Chrome User-Agent for all HTTP requests Feb 5, 2026
Copilot AI requested a review from RPRX February 5, 2026 19:50
@Fangliding
Copy link
Member

它用了个.get 估计bot用grep找的关键字没看到 等它弄完我改改吧 就三行

@RPRX
Copy link
Member

RPRX commented Feb 5, 2026

没事先让它改改看看,这么说的话 observatory TLS 似乎是没用 Chrome 指纹

@copilot 撤回 proxy/http/server.go 的修改,而应当修改 HTTP proxy 的 client

除了 burst 外还要修改普通 observatory 的 UA,另外把两个 observatory 的 TLS 指纹都改为 uTLS Chrome

…de/gRPC, revert proxy/http

Co-authored-by: Fangliding <63339210+Fangliding@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 5, 2026

@copilot XHTTP(SplitHTTP)、gRPC、WebSocket、HTTPUpgrade 被你吃了??

Added User-Agent support for XHTTP (SplitHTTP), gRPC, WebSocket, and HTTPUpgrade in commit a7c0037.

@copilot 把这个功能移到 common/utils 包下面去 用 var ChromeUA = getChromeUA() 初始化一个导出的字符串 其他包直接用这个字符串就行 省去每次计算

Moved to common/utils/browser.go with var ChromeUA = ... that's initialized once at startup. Commit a7c0037.

Co-authored-by: Fangliding <63339210+Fangliding@users.noreply.github.com>
@RPRX
Copy link
Member

RPRX commented Feb 5, 2026

@copilot 顺便把你那 browserVersion() 改成 ChromeVersion()

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 5, 2026

没事先让它改改看看,这么说的话 observatory TLS 似乎是没用 Chrome 指纹

@copilot 撤回 proxy/http/server.go 的修改,而应当修改 HTTP proxy 的 client
...

Added User-Agent to HTTP proxy client and regular observatory in commit 0bb8481.

Regarding TLS fingerprint: Observatory connections go through the outbound handler via tagged.Dialer, so TLS fingerprint is determined by outbound configuration. Adding Chrome fingerprint directly to observatory would require significant changes to how probes work. Could you clarify if this is the desired approach, or should the TLS be configured at the outbound level?

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 5, 2026

@copilot 顺便把你那 browserVersion() 改成 ChromeVersion()

Renamed browserVersion() to ChromeVersion() in commit e3fb267.

@RPRX
Copy link
Member

RPRX commented Feb 6, 2026

@copilot 不要以月计算了,Chrome 144 的发布日期为 2026.1.13,假设此后每 45 天发布一个新版本,用户升级周期也是

因为看了下 Chrome 有可能有个月不发版本,可以落后点但不能出现未发布的版本

… (2026.1.13)

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 6, 2026

@copilot 不要以月计算了,Chrome 144 的发布日期为 2026.1.13,假设此后每 45 天发布一个新版本,用户升级周期也是

~~因为看了下 Chrome 有可能有个月不发��...

已修改为 45 天周期:Chrome 144 发布日期为 2026.1.13,此后每 45 天发布新版本,用户升级周期也是 1-45 天。Commit be9e60a

@RPRX
Copy link
Member

RPRX commented Feb 6, 2026

只剩个小特征是在 CDN 看来每 45 天后才会开始出现新版本

@RPRX
Copy link
Member

RPRX commented Feb 6, 2026

@copilot 再次推倒重来,使用新策略,往上加:

  1. 仅以尽可能多的 CPU 信息作为 seed,弄个伪随机数生成器
  2. 每次随机 25-45 天版本 +1,从 2026.1.13 开始一直往上加,直到超过当前日期,然后版本 -1

解决了升级 Xray 的问题和固定 45 天的问题,虽然时间长了 avg=35 不过短期内还好,每年修正一下就行

…s from 2026.1.13

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 6, 2026

@copilot 再次推倒重来,使用新策略,往上加:

  1. 仅以尽可能多的 CPU 信息作为 seed,弄个伪随机数生成器
    ...

已实现新策略:仅以 CPU 信息作为种子初始化 PRNG,从 2026.1.13 开始每次随机 25-45 天版本 +1,直到超过当前日期后返回版本 -1。Commit 1427b20

@RPRX
Copy link
Member

RPRX commented Feb 6, 2026

取消了用户升级周期是因为重启 Xray 就视为重启 Chrome 就视为升级,毕竟自动更新

又有个小问题是 CPU 这些参数仅相加感觉随机性不够,for hash 可能更好,不过若真基于独一无二的指纹可能暴露 CPU 信息

先这样吧,毕竟 Xray 不一定天天重启,也没有 CDN 会闲到搞出类似彩虹表的东西来匹配这个“随机性不够”吧,毕竟不够精确

@RPRX
Copy link
Member

RPRX commented Feb 6, 2026

如果有人随机到 25 那快炸了,不过想了下有极少数人更新到 Canary 也不是不合理,就这样吧打算合了

@RPRX RPRX marked this pull request as ready for review February 6, 2026 01:16
@RPRX RPRX changed the title feat: dynamic Chrome User-Agent for all HTTP requests Xray-core: Dynamic Chrome User-Agent for all HTTP requests by default (overwriteable) Feb 6, 2026
@RPRX RPRX changed the title Xray-core: Dynamic Chrome User-Agent for all HTTP requests by default (overwriteable) Xray-core: Dynamic Chrome User-Agent for all HTTP requests by default (overwriteable through config) Feb 6, 2026
@RPRX
Copy link
Member

RPRX commented Feb 6, 2026

#4516 (comment) https://developers.google.com/speed/public-dns/docs/doh?hl=zh-cn 提到了 DoH 发 UA 不妥不过 Xray 以前发的也是 Golang,既然不是禁止就发吧,又没真的泄露 UA 毕竟是假的,兼容性可能强一些((自建)DoH behind CDN)

@RPRX RPRX merged commit 1f8515e into main Feb 6, 2026
RPRX added a commit that referenced this pull request Feb 6, 2026
… (overwriteable through config) (#5658)

#4996 (comment)
#5658 (comment)

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
Co-authored-by: Fangliding <63339210+Fangliding@users.noreply.github.com>
@paqx
Copy link
Contributor

paqx commented Feb 6, 2026

Simply specify an array and roll it. The user agent
(UA) information is too limited, just a few numbers. It's better to use this to track unusually high-frequency requests, including headers/query strings where each request has a key-value pair but the value is constantly changing.

If we use a roll, it becomes completely random again. Let's stick with CPU-only.

If a CDN were to block XHTTP, it would definitely require multiple dimensions; here, we'll focus on addressing the user agent (UA) characteristics.Leave the rest to@paqxAlthough Russia doesn't seem to be Chrome

A popular Russian browser is called Yandex Browser. @hxehex created a TLS fingerprint for Yandex Browser (refraction-networking/utls#380). I helped improve and test it. However, my tests show that Yandex Browser has the same fingerprint as Google Chrome, which makes sense because Yandex Browser is based on the same engine.

@RPRX
Copy link
Member

RPRX commented Feb 6, 2026

@paqx TLS 指纹一样是正常的,不过 HTTP UA 呢?比如 Edge 在 Chrome 的基础上加了 Edge 字样

@RPRX
Copy link
Member

RPRX commented Feb 6, 2026

@paqx Chrome 浏览器在俄罗斯的市占率如何,不会特别小众吧

@RPRX
Copy link
Member

RPRX commented Feb 6, 2026

@Fangliding 这个 AI 生成的 Co-authored-by 是 63339210+Fangliding 和我的数字一样,我就说咋怪怪的

@paqx
Copy link
Contributor

paqx commented Feb 6, 2026

@paqxTLS fingerprinting works fine, but what about HTTP User Agent (UA)? For example, Edge adds the "Edge" name to Chrome's interface.

Sorry. I confused a TLS fingerprint and user-agent header.

No, Google Chrome is quite popular. According to Yandex (https://radar.yandex.ru/browsers), it has a 31% market share in Russia. Yandex Browser has a 38% market share.

However, there's a chance that the government might try to gradually push everyone toward using Yandex Browser, so the Yandex Browser user agent is a better option in Russia.

Examples:
https://useragents.io/explore/browsers/types/browser/maker/yandex-llc-0b6

@RPRX
Copy link
Member

RPRX commented Feb 6, 2026

那就还是默认 Chrome 吧,好在 XHTTP 可以通过 extra 分享 UA,有需要的话可以自己改

@RememberOurPromise
Copy link

伊朗的cloudflare流量90%以上被识别为bot,可能就是UA导致的,另一说是伊朗政府用bot刷流量制造假象,不过我觉得不是

如果Xray指定UA而SB和其他代理客户端没有,可能导致从Bot流量占比的变化推断Xray新客户端的占比
不过这可能不是问题,顺便进行市占率统计?

@RPRX
Copy link
Member

RPRX commented Feb 6, 2026

这还用统计?国外的客户端市占率大概 Xray-core 70%,sing-box 20%,mihomo 0%,服务端市占率大概 Xray-core 90%

@RPRX
Copy link
Member

RPRX commented Feb 6, 2026

另外伊朗正处于特殊时期连 Xray 都少了很多,他们正流行频繁更换不同的极小众翻墙软件,特征是很明显的所以也就活一周

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants