要检查一个服务器是否支持 HTTP/2、`h2c`(明文 HTTP/2)、以及是否支持 ALPN 协议协商,可以使用以下几种专业工具进行检测。
---
## ✅ 一、检查是否支持 HTTP/2 + ALPN
### 方法 1:使用 `curl`
```bash
curl -I -k --http2 https://example.com
```
### 输出示例:
```http
HTTP/2 200
...
```
如果返回 `HTTP/2` 则说明支持 HTTP/2,同时使用 TLS 就说明通过 ALPN 协商了。
> 查看 ALPN 协商是否成功,使用 `-v` 参数:
```bash
curl -v --http2 https://example.com
```
看这部分内容:
```text
* ALPN, offering h2
* ALPN, offering http/1.1
* ALPN, server accepted to use h2
```
---
## ✅ 二、检查是否支持 `h2c`(HTTP/2 明文)
### 方法 1:使用 `curl`(明文端口)
```bash
curl -v --http2-prior-knowledge http://example.com:80/
```
注意:
* 不能加 `https://`,要用 `http://`
* `--http2-prior-knowledge` 直接使用 h2c,不经过 upgrade
---
### 方法 2:手动 Upgrade 请求(更标准方式)
```bash
curl -v http://example.com:80/ \
-H "Connection: Upgrade, HTTP2-Settings" \
-H "Upgrade: h2c" \
-H "HTTP2-Settings: AAMAAABkAAQAAP__"
```
如果服务器响应类似如下,说明支持 h2c:
```http
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c
```
---
## ✅ 三、使用 `openssl` 检查 ALPN 协商
```bash
openssl s_client -connect example.com:443 -alpn "h2,http/1.1"
```
### 关键输出:
```text
ALPN protocol: h2
```
说明成功协商到了 HTTP/2。
如果是:
```text
ALPN protocol: http/1.1
```
说明 ALPN 协商只支持 HTTP/1.1。
---
## ✅ 四、使用浏览器开发者工具
打开浏览器(Chrome 或 Firefox)开发者工具 → 网络(Network) → 任一请求 → 查看 “协议” 字段:
* `h2` → 说明是 HTTP/2
* `http/1.1` → 非 HTTP/2
* 没有 `ALPN` 字段,需要通过 Wireshark 查看
---
## ✅ 五、使用 Wireshark 抓包查看 ALPN 和协议
### 过滤表达式:
```text
tls.handshake.extension.alpn
```
查看 Client Hello 中是否发送了 `h2`,Server Hello 中是否返回了 ALPN 协议。
---
## ✅ 六、推荐工具总结
| 工具 | 能力 | 备注 |
| ------------------ | ------------------------ | --------------- |
| `curl` | ✅ HTTP/2 / h2c / ALPN 检查 | 强大且简单 |
| `openssl s_client` | ✅ ALPN 检查 | 手动交互,适合 TLS 层分析 |
| `Wireshark` | ✅ 最详细 | 可观察握手细节 |
| `browser` | ✅ 查看实际协议 | 不适合测试 h2c |
---
是否希望我写一个 Python 脚本自动检测这三种支持情况(HTTP/2, h2c, ALPN)?
好的,这里我将从协议标准角度出发,给出 **ALPN 协商中与 HTTP 相关的协议字段(Protocol Identifiers)**,并结合实际使用(如浏览器、Envoy、NGINX、gRPC)解释它们的含义和作用。
---
## ✅ 一、ALPN 协议协商字段简介(IANA标准)
在 TLS 握手中,客户端通过 `ALPN` 扩展字段声明它支持的应用层协议,字段是一个字符串列表,例如:
```text
["h2", "http/1.1"]
```
这些字符串称为 **ALPN 协议标识符(Protocol IDs)**,它们是 IANA 注册的标准标识。
---
## ✅ 二、常用 HTTP 系列协议标识符
| ALPN 协议标识符 | 说明 | 是否加密(TLS) | 用途场景 |
| ----------------- | ----------------------------- | --------- | ------------------------------ |
| `http/1.0` | HTTP/1.0 协议 | 是 | 非常老,几乎不用 |
| `http/1.1` | HTTP/1.1 协议 | 是 | 最常见基本协议,广泛支持 |
| `h2` | HTTP/2 over TLS | ✅ 是 | 浏览器/服务优先使用,支持多路复用 |
| `h2-14` 到 `h2-16` | 早期草案版本(废弃) | ✅ 是 | 不再使用 |
| `h3` | HTTP/3(基于 QUIC) | ❌ 非 TLS | 使用 QUIC 代替 TLS,UDP 协议 |
| `h2c` | HTTP/2 over Cleartext (无 TLS) | ❌ 否 | 不用于 ALPN,仅用于明文协议协商,如 gRPC 内部通信 |
| `acme-tls/1` | Let’s Encrypt TLS-SNI 验证协议 | 是 | 仅用于 ACME 协议身份验证 |
| `ftp` / `smtp` | 其他应用协议 | 是 | 非 HTTP 类 |
---
## ✅ 三、举例说明(客户端设置 & 服务端响应)
### 🔸 客户端发送:
```plaintext
ALPN Extension (RFC 7301):
Protocol Name List:
Protocol Name: h2
Protocol Name: http/1.1
```
### 🔸 服务端响应:
```plaintext
ALPN Selected Protocol: h2
```
表示协商成功,双方将使用 HTTP/2 进行通信。
---
## ✅ 四、h2 与 h2c 的关键区别
| 协议字段 | 场景 | 是否在 ALPN 中使用 | 备注 |
| ----- | ------------------ | ------------ | ------------------------------------- |
| `h2` | HTTP/2 over TLS | ✅ 是 | 浏览器、Envoy、NGINX |
| `h2c` | HTTP/2 over 明文 TCP | ❌ 否 | 不适用于 ALPN,需另用 Upgrade 机制或 magic frame |
> ⚠️ ALPN 是 TLS 扩展,因此 `h2c` 根本不会出现于 ALPN 协商中。
---
## ✅ 五、在常见环境中的 ALPN 字段支持
| 环境/组件 | 默认支持 ALPN | 默认支持 h2 | 支持 h2c |
| -------------- | --------- | ------- | --------------- |
| Chrome/Firefox | ✅ | ✅ | ❌ 不支持 h2c |
| Envoy Proxy | ✅ | ✅ | ✅ |
| NGINX (>1.9.5) | ✅ | ✅ | ❌(需特殊配置) |
| gRPC 客户端 | ✅ | ✅ | ✅(通过 h2c 协议魔法头) |
---
## ✅ 六、相关标准和引用
* **ALPN RFC**: [RFC 7301](https://datatracker.ietf.org/doc/html/rfc7301)
* **HTTP/2 RFC**: [RFC 7540](https://datatracker.ietf.org/doc/html/rfc7540)
* **HTTP/3 + QUIC**: [RFC 9114 / 9000](https://datatracker.ietf.org/doc/html/rfc9114)
---
是否希望我提供 Wireshark 抓包示例,展示 ALPN 协商过程(Client Hello 和 Server Hello)中的具体字段?