SSL Pinning原理以及网络知识笔记
一、前言
有时候,你会发现某个app或许抓不了包,很有可能就是pinning在作祟。
这里我整理了相关知识以及原理,希望对你有所帮助。
二、发起请求后的流程
概括就是:访问www.91.com ->DNS进行解析拿到ip地址 -> 进行tcp三次握手建立通道 -> TLS握手(取决于是否用了https) -> 加密传入http包和响应
有四点值得关注:
- CA / 证书链验证:我能否信任对方提供的证书?
- Hostname Verification:证书是否是签给我正在访问的主机名?
- Certificate/Public-Key Pinning:除了系统信任链外,我是否只接受预先指定的证书或公钥?
- mTLS 客户端认证:服务器是否要求客户端也出示证书,并证明自己持有对应私钥?
三、名词解析
1.DNS是什么
DNS(Domain Name System,域名系统)负责把类似 api.example.com
的域名解析成 IP 地址。它类似互联网的”电话簿”,但不负责加密 HTTP
内容,也不负责证明服务器身份。
几个要点:
- DNS 通常发生在 TCP/TLS 握手之前。
- DNS 返回一个 IP,不等于这个 IP 上的服务就可信。
- HTTPS 的服务器证书仍需要验证证书链、有效期、用途和主机名。
- DNS 出错可能让客户端连到错误地址,但正确的 HTTPS 主机名验证通常会阻止冒充服务器。
- DNS 查询本身是否加密,取决于使用的是传统 DNS、DoT(DNS over TLS)、DoH(DNS over HTTPS)等方式。
- 直接访问 IP 时,证书主机名校验可能失败,因为证书通常签给域名而不是该 IP。
这里出现了几个名词,Dot以及Doh,来看看他们出现的原因吧。
传统 DNS 通常通过 UDP 53 端口查询,也可以使用 TCP 53。它默认不加密,因此同一网络路径上的观察者可能看到你查询的域名,也可能篡改响应。
DOT
DoT = DNS over TLS,也就是“通过 TLS 传输 DNS”。
它保留 DNS 查询的内容和语义,但在 DNS 数据外面增加 TLS 加密保护。
特点:
- 通常使用 TCP 853 端口。
- DNS 查询和响应在传输过程中受到 TLS 加密保护。
- 网络路径上的旁观者通常无法直接读取 DNS 查询内容。
- 网络观察者仍可能看到你连接了哪个 DNS 服务器,以及连接的时间、流量大小等元数据。
DOH
DoH = DNS over HTTPS,也就是“通过 HTTPS 传输 DNS”。
它同样保护 DNS 查询,但不是使用专门的 DoT 协议端口,而是把 DNS 查询放进 HTTPS 请求中发送。
特点:
- 常见情况下使用 HTTPS 的 443 端口。
- DNS 查询被封装在 HTTPS 请求中。
- 因为和普通 HTTPS 共用常见的 Web 传输方式,单靠端口号通常无法判断某个连接是不是 DoH。
- 和 DoT 一样,连接本身的元数据仍可能暴露;加密也不会阻止 DNS 服务提供商看到它处理的查询。
2.Https和tls
HTTPS 可以理解为 HTTP 运行在 TLS 安全通道之上。TLS(Transport Layer Security)负责建立安全连接,并在握手后加密保护应用数据。
TLS 主要提供:
- 机密性:旁观者不能直接读出加密后的 HTTP 内容。
- 完整性:数据被修改时通常会被检测到。
- 服务器身份认证:客户端通过证书链等机制验证服务器。
- 可选的客户端身份认证:mTLS 中服务器也验证客户端证书。
TLS 不会自动让应用逻辑安全,也不保证服务器业务行为可信。若 App 主动忽略证书错误,或把秘密写进日志,TLS 本身无法解决这些问题。
3.TLS握手流程
4.啥是证书、ca、证书链
比如X.509证书,有下面这些内容
- Subject:证书主体,例如
CN=api.example.com。 - Issuer:签发者名称。
- Subject Public Key:主体公钥。
- Validity:有效起止时间。
- Subject Alternative Name(SAN):证书适用的 DNS 名称或 IP。
- Key Usage / Extended Key Usage:允许的用途,例如服务器认证、客户端认证。
- Serial Number、签名算法、签名值等。
Subject: CN=api.example.comIssuer: CN=Example Intermediate CASerial Number: 01:A2:B3:C4Validity: Not Before: 2026-01-01 Not After: 2027-01-01
Subject Public Key: Algorithm: RSA Key Size: 2048 bits
Subject Alternative Name: DNS:api.example.com
Extended Key Usage: TLS Web Server Authentication
Signature Algorithm: SHA256withRSA
Signature: [一段数字签名数据]总结一下:证书里藏了重要的公钥和签名算法,他可以是任意一方颁发并用于身份自证以及通信的工具。
CA(Certificate Authority,证书颁发机构)负责签发和管理证书。客户端通过本地信任锚(通常是根CA 证书)验证一条证书链。
所以CA做了啥事?
服务器生成密钥对(私钥揣兜里,公钥公开)->向 CA 提交申请,证明对域名或身份具有相应控制权->CA 对证书内容生成数字签名->客户端验证签名链、有效期、用途和主机名总结就是套娃,CA相当于中介(草泥马的黑心中介!),他做的事情也和服务端一样。用自己的私钥对服务端给的证书进行签名,而客户端天生是信任CA的,手里有着CA的公钥,所以能够拿到服务端的证书。
CA常见来源(浏览器也是一个套路)包括:
- Android 系统预置的受信任 CA。
- 用户手动安装的 CA(现代 Android 的应用是否信任用户 CA,取决于系统版本和应用 Network Security Config 等配置)。
- App 自己加载的 CA 或证书。
- 自定义 TrustManager / TrustStore。
5.TLS里的几个Manager
一句话概括:KeyManager 负责“证明自己”,TrustManager 负责“信任别人”,HostnameVerifier 负责“核对名字”。
| 维度 | KeyManager(密钥管理器) | TrustManager(信任管理器) | HostnameVerifier(主机名验证器) |
|---|---|---|---|
| 核心职责 | 管理本地身份凭证,向对端”证明自己” | 管理信任材料,决定”是否信任对方” | 核对证书中的身份标识与实际连接目标是否匹配 |
| 处理的数据 | 本地私钥 + 证书链(KeyStore 密钥库) | 受信任的 CA 根证书(TrustStore 信任库) | 对端证书中的 SAN/CN + 实际连接的主机名 |
| 回答的问题 | ”我该用哪套证书向对方证明我是谁?" | "对方出示的证书链是否可信?" | "这张(已可信的)证书是不是发给这个主机的?“ |
| 在 Java 中的接口 | javax.net.ssl.KeyManager | javax.net.ssl.TrustManager | javax.net.ssl.HostnameVerifier |
| 典型实现/工厂 | KeyManagerFactory + KeyStore | TrustManagerFactory + TrustStore(默认 cacerts) | HttpsURLConnection 默认实现,或自定义 |
| 何时被调用 | 握手需要出示本地证书时(服务器端、或 mTLS 客户端) | 收到对端证书链、需要验证时 | TrustManager 验证通过之后,再校验主机名 |
| 客户端场景是否必需 | 通常不需要(除非 mTLS) | 必需 | 必需(HTTPS 场景) |
| 服务器端场景是否必需 | 必需(出示服务器证书) | 可选(仅 mTLS 验证客户端时) | 不适用(服务器一般不校验客户端主机名) |
| 校验失败后果 | 无法出示证书,握手失败 | 证书链不可信,握手失败 | 连接被拒绝(防中间人/证书错配) |
| 其他语言的对应机制 | Go:tls.Config.Certificates;OpenSSL:SSL_CTX_use_certificate / use_PrivateKey | Go:RootCAs、VerifyPeerCertificate;OpenSSL:SSL_CTX_load_verify_locations、verify 回调 | Go:tls.Config.ServerName 隐式校验;OpenSSL:X509_VERIFY_PARAM_set1_host |
| 一句话记忆 | 证明自己 | 信任别人 | 核对名字 |
6.什么是SSL pinning
“SSL Pinning”是常见叫法,更准确地说通常是证书固定或公钥固定(Certificate Pinning / Public-Key Pinning)。
常规 HTTPS 验证大致问:
这张证书能否沿着有效的证书链追溯到我信任的 CA?它是否有效、用途正确、主机名匹配?
Pinning 则额外问:
这个证书或公钥,是否正是应用预先指定、允许接受的那一个?
即使代理工具生成的证书由手机信任的 Charles CA 签发,App 的 Pinning 仍可能拒绝它,因为该证书的公钥或证书指纹与 App 预期值不同。
所以这里是抓包工具被检测的关键。
Charles / mitmproxy 等 HTTPS解密代理会在客户端与代理之间呈现一张代理生成的证书,并在代理与服务器之间另建连接。即使Android 信任 Charles 根CA,代理证书的公钥也通常与服务器原始公钥不同,因此 Pinning 会失败。
7.常见的pinning
- 证书指纹固定:比较整个证书的哈希值。
- 公钥 / SPKI 固定:提取证书中的 Subject Public Key Info,再做哈希比较。
- 自定义固定逻辑:应用自己解析证书、比较摘要、维护状态或在失败时拒绝请求。
本项目案例中看到的代码会对公钥 SPKI 数据做 SHA-256,再编码成 Base64 与预期 pin 比较。这属于公钥固定思路。
实际 App 可能使用 OkHttp 的CertificatePinner,也可能自己实现这套逻辑。
具体流程如下
8.双向TLS是什么?
普通 HTTPS的典型情况是客户端验证服务器;服务器通常通过账号密码、Token、会话 Cookie等方式识别用户。
mTLS 在 TLS握手中增加客户端证书认证:服务器要求客户端提供证书,并验证客户端是否持有对应私钥。
客户端证书常见如client.12
PKCS#12(常见扩展名 .p12 / .pfx)通常是一个容器,可能包含:
- 客户端证书;
- 与证书匹配的私钥;
- 一条或多条中间 CA 证书;
- 保护容器内容的密码。
容器密码用于保护文件中的秘密,不是客户端证书,也不是 CA 证书。
9.抓包工具是如何工作的
抓包常被混为两类:网络包捕获,以及 HTTPS 中间人代理(MITM Proxy)。它们不是一回事。
普通网络抓包是Wireshark、tcpdump 等工具捕获网络接口上的数据包。对明文HTTP,可能直接看到请求和响应;对 HTTPS,通常只能看到IP、端口、连接元数据以及部分握手信息,应用内容是加密的。
https解密代理是Charles、mitmproxy、Burp Suite 等在代理模式下,通常会拆成两条独立的 TLS连接:
可以看到,抓包工具做了一个中间人,与客户端,服务端都进行了TLS链接。
mTLS 代理面对的是两段连接:
- App → Charles:App 验证 Charles 的证书。
- Charles → 服务器:服务器可能要求 Charles 提供客户端证书。
所以这里显而易见的,客户端需要信任代理抓包软件的CA,这个需要手动放到手机的信任证书里。
但要弄清几点:安装 CA 并不代表: - App 一定信任用户安装的 CA; - Pinning一定会通过; - 所有 App 流量都会自动进入代理; - mTLS的服务器端客户端证书要求会自动满足。
10.代理和vpn
都讲抓包了,这两个也记个笔记。
区别如下
- 代理的定义是应用或系统把指定的网络请求交给代理服务器,再由代理转发到目标服务器。例如 Charles、HTTP 代理、SOCKS5 代理。
- VPN是在设备与 VPN 服务端之间建立加密隧道,再按路由规则把流量送进隧道。例如 WireGuard、OpenVPN、IPsec VPN。
- 出口ip是目标网站看到的网络连接来源 IP。它可能是家庭宽带、移动网络、数据中心或 VPN 服务商的出口。
概括一下
- 代理:你请中间人帮你转交某类信件。
- VPN:你修了一条通往远端网络的加密隧道。
- 出口 IP:对方在信件上看到的寄件地址。
VPN 服务本身也可能通过代理、NAT 或其他网络设备转发流量;它们不是完全互斥的技术。
代理的几大份分类:
方式A:显示代理
比如 Android 的 Wi-Fi 代理设置为:
代理服务器:192.168.1.10代理端口:8888
当支持系统代理的应用访问网站时,会根据代理配置把请求发给 192.168.1.10:8888,由代理再连接目标服务器。方式 B:透明转发
透明代理或网关可以通过网络路由、防火墙规则等手段,把符合规则的流量转发到中间设备。应用未必需要显式配置代理。
但“透明转发”不等于自动解密 HTTPS:没有客户端与中间设备之间合适的 TLS 处理和信任配置,代理通常仍然看不到 HTTPS 的明文内容。
方式 C:VPN 隧道
VPN 常通过操作系统的虚拟网络接口接收流量,再把它封装进隧道发送给远端 VPN 服务器。
App ↓系统网络栈 ↓VPN 虚拟网卡 ↓加密隧道 ↓VPN 服务器 ↓互联网目标服务器在 Android 上,VPN 应用通常使用 VpnService 创建虚拟接口,并通过路由规则决定哪些流量进入隧道。
VPN 是否承载全部流量,要看它的路由配置;分流 VPN 可能只接管某些应用或某些目标网段。
代理的分类
代理可以从不同角度分类,不是只有一种分类方法。
- 按代理协议分类
| 类型 | 工作方式 | 常见用途 |
|---|---|---|
| HTTP 代理 | 转发 HTTP 请求;HTTPS 通常通过 CONNECT 建立隧道 | Web 访问、调试抓包 |
| HTTPS 代理 | 通常指客户端到代理这段连接本身使用 TLS 加密的代理 | 保护客户端与代理之间的通信 |
| SOCKS4 / SOCKS5 | 在更底层转发连接,不局限于 HTTP 请求格式 | 通用 TCP 代理;SOCKS5 还支持 UDP |
| 透明代理 | 通过网络基础设施拦截或转发符合规则的流量 | 企业网关、网络管理 |
| 反向代理 | 代理位于服务器前方,代表后端服务器接收请求 | Nginx、负载均衡、CDN |
特别注意:HTTPS 代理和 HTTPS 解密代理不是同一个概念。
- HTTPS 代理可以只加密客户端到代理的连接。
- Charles 这类解密代理,可以在配置允许的情况下,作为 TLS 中间端点分别与客户端和目标服务器握手,进而查看 HTTP 明文。
- 正向代理与反向代理
正向代理代表客户端访问外部服务器。客户端通常知道自己在使用代理。
例:Charles、SOCKS5 出口代理
反向代理代表后端服务器接收客户端请求,客户端通常只看到代理入口。
例:Nginx、CDN、负载均衡器
四、加餐小补充
都唠到这份上了,再加点料。
1.端口转发
这里最重要的基础是:一个网络连接通常由 协议、目标 IP、目标端口 等信息确定。
- IP 地址:找到哪台设备或网络接口。
- 端口:找到这台设备上哪个网络服务。
- 监听(listen):某个程序在特定地址和端口等待连接。
- 转发(forward):把到达某个入口的连接或数据送往另一个目标。
端口转发(Port Forwarding)可以理解为:给某个网络入口安排一条通往另一个地址和端口的路线。
常见的是adb的两个操作:
# 电脑连接设备上的 8444adb forward tcp:18444 tcp:8444
# 设备连接电脑上的 18444,设备侧入口为 8444adb reverse tcp:8444 tcp:18444
# 查看已建立的映射adb forward --listadb reverse --list
# 删除指定映射adb reverse --remove tcp:84442.SSH 远程连接和 SSH 隧道
SSH(Secure Shell)最初主要用于安全地远程登录另一台计算机。它不仅能执行命令、管理服务器,还能通过端口转发建立加密隧道。
执行下面的命令:
ssh user@192.0.2.10通常发生以下过程:
- 客户端连接远程主机的 SSH 服务,默认 TCP 端口是
22。 - 双方协商加密算法和会话密钥。
- 客户端验证服务器主机密钥;首次连接时,通常需要核对指纹。
- 用户通过密码、公钥等方式完成身份认证。
- SSH 在加密连接里传递终端命令和输出。
需要区分两种密钥:
- 服务器主机密钥:帮助客户端确认连接的是预期的 SSH 服务器。
- 用户身份密钥:例如客户端的 SSH 私钥,用来证明用户有登录权限。
SSH 加密保护的是 SSH 会话。它不意味着远端计算机上的所有网络流量都会自动经过 SSH。
3.Nat
NAT 是 Network Address Translation,也就是网络地址转换。它通常运行在路由器或网关上,修改经过它的 IP 地址,有时也会修改 TCP/UDP 端口。
比如家庭网络,通过NAT(也就是路由器)把源地址和端口转换为公网侧映射
内网:192.168.1.20:51000 ↓ NAT公网:203.0.113.5:62001NAT 和端口转发的区别
这两个概念很容易混淆。
| 对比 | NAT | 端口转发 |
|---|---|---|
| 主要作用 | 转换网络地址或端口 | 把特定入口导向指定目标 |
| 常见用途 | 内网设备访问互联网 | 外部访问内网服务 |
| 是否一定要手动配置 | 不一定 | 静态端口转发通常需要 |
| 是否加密数据 | 不会 | 不会 |
比如在路由器这么配置:公网地址:8443 → 192.168.1.20:443
那么访问公网地址的 8443 端口,流量会被送到内网服务器的 443 端口。这通常叫静态端口转发,常用于 NAT 网关后的服务器。
但要注意:如果你的网络处于运营商级 NAT(CGNAT)之后,即使在自家路由器配置了端口转发,互联网用户也可能无法直接连进来。
这时可能需要公网 IP、VPN、反向隧道或具有公网入口的中继服务器。
4.桥接模式
桥接(Bridge)主要解决的是把不同的网络接口连接起来,让它们在同一个二层网络中通信。
可以先把它理解成交换机:设备插在同一个交换网络里,能够通过 MAC 地址转发以太网帧。
桥接和 NAT 的差别
- 桥接:主要在二层转发帧,通常不做三层地址转换。
- 路由:根据 IP 路由表,在不同 IP 网络之间转发数据包。
- NAT:在转发过程中修改地址或端口信息。
虚拟机或模拟器网络常见几种模式:
- NAT 模式:虚拟设备通过宿主机访问外网,外部设备通常不能直接主动连接虚拟设备。
- 桥接模式:虚拟设备像局域网中的独立设备一样获得地址,具体能力取决于虚拟化软件和网络环境。
- 端口映射:为虚拟设备或宿主机上的某个服务建立特定入口。
- ADB 转发:通过 ADB 调试连接建立端口通道。
5.CDN乱入
CDN 是 Content Delivery Network,中文叫内容分发网络。
它把网站内容缓存或部署在多个地理位置的边缘节点上,让用户通常可以从较近的节点获取内容。
访问流程大致是:
- 客户端解析域名,得到一个或多个可用地址。
- 客户端连接某个 CDN 边缘节点。
- 如果节点有缓存,可能直接返回内容。
- 如果没有缓存,节点可能从源站获取内容,再返回给客户端。
实际调度不一定只由 DNS 决定,也可能结合 Anycast、负载均衡和 CDN 自身的路由机制。
CDN 与反向代理两者有关联,但不是同义词。
- 反向代理:代表后端服务器接收客户端请求,再转发给后端。
- CDN:重点在分布式边缘节点、内容缓存、加速和流量调度。
- 源站(Origin):实际提供原始内容或业务数据的后端服务。
CDN 也能代理动态 API 请求,因此它不只是图片、视频的缓存服务。
6.SOCKS 是什么?和 HTTP 代理有什么区别?
SOCKS 是一种代理协议。客户端把“我要连接哪个目标地址和端口”的请求交给代理服务器,由代理服务器代表客户端建立连接。
最常见的是 SOCKS5。
| 项目 | SOCKS5 | HTTP 代理 | VPN |
|---|---|---|---|
| 工作层次(概念上) | 通用代理接口 | HTTP 应用代理 | IP 层隧道为主 |
| 转发内容 | TCP,也可支持 UDP | HTTP;HTTPS 通常使用 CONNECT 隧道 | IP 数据包 |
| 是否自动加密 | 不会 | 不会自动加密代理链路 | 通常加密设备到 VPN 端点的隧道 |
| 需要应用配合 | 通常需要 | 通常需要或由系统代理配置 | 常由系统网络路由接管 |
SOCKS5 本身不负责加密。 如果你把 TLS 连接交给 SOCKS5 代理,TLS 仍然可以在客户端与最终服务器之间建立;代理通常只是转发 TLS 字节流。
比如
App │ TLS 加密 ▼SOCKS5 代理 │ 转发加密数据 ▼HTTPS 服务器7.WebSocket 是什么?
WebSocket 是一种支持双向通信的协议。连接建立后,客户端和服务器双方都可以主动发送消息,不必每次都重新发起一个 HTTP 请求。
它常见于实时聊天、在线状态、游戏、行情推送和实时控制。
普通 WebSocket 常用 ws://,加密 WebSocket 常用 wss://。
ws://:通常使用普通 TCP 连接。wss://:在 WebSocket 通信外使用 TLS 加密。
经典 WebSocket 建连会先发送一个 HTTP Upgrade 请求,然后把连接升级为 WebSocket 协议。现代 HTTP/2 和 HTTP/3 也有相应的 WebSocket 扩展机制,因此并非所有 WebSocket 都必须采用 HTTP/1.1 Upgrade 方式。
典型的 HTTP/1.1 握手看起来像这样:
GET /chat HTTP/1.1Host: example.comUpgrade: websocketConnection: UpgradeSec-WebSocket-Key: ...Sec-WebSocket-Version: 13服务器同意后返回 101 Switching Protocols,连接随即进入 WebSocket 数据交换阶段。
部分信息可能已经过时









