关于 http2-header-impersonation
http2-header-impersonation 是用于匹配浏览器 HTTP/2 设置、伪标头顺序和请求标头的安全测试技能,适合调查会区分自动化请求与浏览器流量的系统。
主要功能
- 01伪装 HTTP/2 SETTINGS 帧
- 02匹配伪标头顺序
- 03应用浏览器专属标头
- 04使用 Chrome、Firefox、Safari iOS 和 OkHttp 配置
- 05通过 impit 配置配置文件
适用场景
- 01测试基于 HTTP/2 的机器人检测
- 02为端点测试匹配浏览器请求配置
- 03将 HTTP/2 配置与 TLS 伪装结合
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill http2-header-impersonation安装后在 Claude Code 中输入/http2-header-impersonation确认已加载。
详细介绍
HTTP/2 标头伪装
伪造 HTTP/2 SETTINGS 帧、伪标头顺序和浏览器专属 HTTP 标头,在协议层面匹配真实浏览器。针对 TLS 指纹(ClientHello)与 JavaScript 指纹识别之间的检测盲区——反机器人系统会分析 HTTP/2 连接设置和标头结构。精确匹配 Chrome、Firefox、Safari iOS 和 OkHttp(Android)的配置文件,包括窗口大小、标头列表限制和标头顺序。
适用场景
- TLS 指纹正确,但目标仍能检测到非浏览器 HTTP 行为。
- 目标使用 HTTP/2 专属检测(SETTINGS 帧分析、伪标头顺序)。
- 需要符合浏览器特征的
sec-ch-ua、Accept、Accept-Encoding、Priority和sec-fetch-*标头。 - 移动 API 端点需要 Android OkHttp 标头配置文件。
- 与 TLS 伪装结合,构建完整的网络层浏览器配置文件。
前置条件
- 带有 python3 的
terminal。 pip install impit(包含通过修补版 h2 库实现的 HTTP/2 伪装)。- 或单独使用:用下方的标头列表手动配置 curl/httpx。
快速检测
# Check if target sends different responses based on HTTP headers
# Compare browser-like headers vs curl defaults
python3 -c "
import requests
# curl default headers
r1 = requests.get('https://target.com')
print(f'Default: {r1.status_code}')
# Browser-like headers
r2 = requests.get('https://target.com', headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/[REDACTED_IP] Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br, zstd',
'sec-ch-ua': '\"Chromium\";v=\"142\", \"Google Chrome\";v=\"142\"',
'sec-ch-ua-platform': '\"Windows\"',
'sec-ch-ua-mobile': '?0',
})
print(f'Browser: {r2.status_code}')
"
操作流程
阶段 1 — 使用 impit 配置完整浏览器配置文件
impit 库可通过单个配置文件应用 HTTP/2 SETTINGS、伪标头顺序和 HTTP 标头:
from impit import Impit
# Chrome 142 — complete HTTP/2 + TLS + headers profile
impit = (
Impit.builder()
.with_fingerprint("chrome142")
.build()
)
response = impit.get("https://target.com")
# Headers sent: sec-ch-ua, User-Agent, Accept, Accept-Encoding, Accept-Language,
# sec-ch-ua-platform, sec-ch-ua-mobile, Priority, sec-fetch-*
# HTTP/2 SETTINGS: stream_window=6291456, conn_window=15663105, max_header=262144
# Pseudo-header order: :method :authority :scheme :path :protocol :status
阶段 2 — 手动配置标头
对于不使用 impit 的 curl/httpx,请手动配置标头以匹配浏览器配置文件:
Chrome 142 桌面版标头
curl --max-time 30 --connect-timeout 10 -sk "https://target.com" \
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/[REDACTED_IP] Safari/537.36" \
-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7" \
-H "Accept-Language: en-US,en;q=0.9" \
-H "Accept-Encoding: gzip, deflate, br, zstd" \
-H "sec-ch-ua: \"Chromium\";v=\"142\", \"Google Chrome\";v=\"142\", \"Not?A_Brand\";v=\"99\"" \
-H "sec-ch-ua-arch: \"x86\"" \
-H "sec-ch-ua-bitness: \"64\"" \
-H "sec-ch-ua-full-version-list: \"Chromium\";v=\"142.0.7444.176\", \"Google Chrome\";v=\"142.0.7444.176\", \"Not?A_Brand\";v=\"[REDACTED_IP]\"" \
-H "sec-ch-ua-mobile: ?0" \
-H "sec-ch-ua-model: \"\"" \
-H "sec-ch-ua-platform: \"Windows\"" \
-H "sec-ch-ua-platform-version: \"15.0.0\"" \
-H "sec-ch-ua-wow64: ?0" \
-H "sec-fetch-dest: document" \
-H "sec-fetch-mode: navigate" \
-H "sec-fetch-site: none" \
-H "sec-fetch-user: ?1" \
-H "Upgrade-Insecure-Requests: 1" \
-H "Priority: u=0, i"
Firefox 144 桌面版标头
curl --max-time 30 --connect-timeout 10 -sk "https://target.com" \
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:144.0) Gecko/20100101 Firefox/144.0" \
-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8" \
-H "Accept-Language: en-US,en;q=0.5" \
-H "Accept-Encoding: gzip, deflate, br, zstd" \
-H "sec-ch-ua: \"Firefox\";v=\"144\", \"Not?A_Brand\";v=\"99\"" \
-H "sec-ch-ua-mobile: ?0" \
-H "sec-ch-ua-platform: \"Windows\"" \
-H "sec-fetch-dest: document" \
-H "sec-fetch-mode: navigate" \
-H "sec-fetch-site: none" \
-H "sec-fetch-user: ?1" \
-H "TE: trailers" \
-H "Upgrade-Insecure-Requests: 1" \
-H "Priority: u=0, i"
Safari iOS 18 标头
curl --max-time 30 --connect-timeout 10 -sk "https://target.com" \
-H "User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.7 Mobile/15E148 Safari/604.1" \
-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" \
-H "Accept-Language: en-US,en;q=0.9" \
-H "Accept-Encoding: gzip, deflate, br" \
-H "sec-fetch-dest: document" \
-H "sec-fetch-mode: navigate" \
-H "sec-fetch-site: none"
OkHttp 4(Android)标头
curl --max-time 30 --connect-timeout 10 -sk "https://target.com" \
-H "User-Agent: okhttp/4.12.0" \
-H "Accept: application/json, text/plain, */*" \
-H "Accept-Language: en-US,en;q=0.9" \
-H "Accept-Encoding: gzip, deflate, br" \
-H "Connection: Keep-Alive"
阶段 3 — 伪造 HTTP/2 SETTINGS 帧
HTTP/2 SETTINGS 帧会在连接设置期间发送。curl 不提供设置这些帧的接口——请使用 impit 或修补过的 HTTP 客户端:
from impit import Impit
# Chrome HTTP/2 SETTINGS:
# SETTINGS_MAX_CONCURRENT_STREAMS: 1000
# SETTINGS_INITIAL_WINDOW_SIZE: 6291456
# SETTINGS_MAX_HEADER_LIST_SIZE: 262144
# Firefox HTTP/2 SETTINGS:
# SETTINGS_MAX_CONCURRENT_STREAMS: 125
# SETTINGS_INITIAL_WINDOW_SIZE: 131072
impit = Impit.builder().with_fingerprint("chrome142").build()
response = impit.get("https://target.com")
阶段 4 — 伪标头顺序
浏览器会按特定顺序发送 HTTP/2 伪标头。这由 h2 库层强制执行:
| 浏览器 | 伪标头顺序 |
|---|---|
| Chrome | :method、:authority、:scheme、:path、:protocol、:status |
| Firefox | :method、:path、:authority、:scheme、:protocol、:status |
| Safari iOS | :method、:scheme、:authority、:path、:protocol、:status |
| OkHttp | :method、:path、:authority、:scheme、:protocol、:status |
检测: 某些反向代理会检查伪标头顺序,以区分不同浏览器。Firefox 会将 :path 放在 :authority 之前,这是独特的指纹。Safari 会将 :scheme 放在第二位,这是另一项区分特征。
阶段 5 — 标头优先级
为避免冲突,自定义标头的优先级高于指纹默认值:
impit = Impit.builder().with_fingerprint("chrome142").build()
# Custom headers WIN over fingerprint defaults for same header name
response = impit.get("https://target.com", headers={
"Authorization": "Bearer custom-token",
"X-Custom-Header": "value",
})
# Authorization is added; all fingerprint headers still applied for unset names
阶段 6 — Accept-Encoding 策略
不同浏览器的 Accept-Encoding 值差异明显:
| 浏览器 | Accept-Encoding |
|---|---|
| Chrome 142 | gzip, deflate, br, zstd |
| Chrome 100-116 | gzip, deflate, br |
| Firefox | gzip, deflate, br, zstd |
| Safari iOS | gzip, deflate, br |
| OkHttp 4 | gzip, deflate, br |
检测: 某些 CDN 会根据 Accept-Encoding 返回不同内容(通过 brotli 与 zstd 能力配置文件进行识别)。请根据目标浏览器匹配编码能力。
注意事项
- curl 无法伪造 HTTP/2 SETTINGS 帧。 仅在 HTTP/1.1 目标上,或主要关注 TLS 指纹而非 HTTP/2 时,才使用基于 curl 的标头。
- HTTP/2 中的标头顺序很重要。 某些检测器会检查标头字段的顺序,而不只是检查字段是否存在。
sec-ch-ua必须与 User-Agent 匹配。 使用 Chrome 标头搭配 Firefox UA 会产生不一致,容易被检测器发现。sec-ch-ua的格式取决于版本。 Chrome 100+ 使用的品牌字符串与 Chrome 124+ 不同。- 移动端标头与 TLS 不匹配时会被检测到。 通过桌面 TLS 指纹使用 Safari iOS 标头会触发检测。
- 自定义标头会按大小写不敏感方式去重。 将
User-Agent添加为自定义标头会覆盖指纹中的 User-Agent。
验证
- 使用
https://httpbin.org/headers测试——确认所有发送的标头都与预期的浏览器配置一致。 - 若要验证 HTTP/2 SETTINGS,请使用
https://nghttp2.org/httpbin/headers或本地 nghttp2 服务。 - 比较 browser-impostor 与真实浏览器的响应大小/内容——响应完全相同表示这些标头已被接受。
- 检查 Cloudflare
cf-ja4标头——它会编码 HTTP/2 指纹和 TLS 信息。
相关技能
tls-fingerprint-impersonation——TLS ClientHello 和 JA3/JA4 指纹伪装。stealth-browser-launch——通过 C++ 指纹补丁实现完整的浏览器自动化。