CrazyDailyQuestion
CrazyDailyQuestion copied to clipboard
OKhhtp3 如何反抓包
我们在看OKhttp源码的时候,其们可以看到TLS 握手的过程connectTls 方法
private void connectTls(ConnectionSpecSelector connectionSpecSelector) throws IOException {
Address address = route.address();
SSLSocketFactory sslSocketFactory = address.sslSocketFactory();
boolean success = false;
SSLSocket sslSocket = null;
try {
// 基于之前建立的Socket建立一个包装对象SSLSocket
sslSocket = (SSLSocket) sslSocketFactory.createSocket(
rawSocket, address.url().host(), address.url().port(), true /* autoClose */);
// 对TLS相关信息进行配置
ConnectionSpec connectionSpec = connectionSpecSelector.configureSecureSocket(sslSocket);
if (connectionSpec.supportsTlsExtensions()) {
Platform.get().configureTlsExtensions(
sslSocket, address.url().host(), address.protocols());
}
// 进行握手
sslSocket.startHandshake();
// 获取SSLSession
SSLSession sslSocketSession = sslSocket.getSession();
Handshake unverifiedHandshake = Handshake.get(sslSocketSession);
// 验证证书对该主机是否有效
if (!address.hostnameVerifier().verify(address.url().host(), sslSocketSession)) {
List<Certificate> peerCertificates = unverifiedHandshake.peerCertificates();
if (!peerCertificates.isEmpty()) {
X509Certificate cert = (X509Certificate) peerCertificates.get(0);
throw new SSLPeerUnverifiedException(
"Hostname " + address.url().host() + " not verified:"
+ "\n certificate: " + CertificatePinner.pin(cert)
+ "\n DN: " + cert.getSubjectDN().getName()
+ "\n subjectAltNames: " + OkHostnameVerifier.allSubjectAltNames(cert));
} else {
throw new SSLPeerUnverifiedException(
"Hostname " + address.url().host() + " not verified (no certificates)");
}
}
address.certificatePinner().check(address.url().host(),
unverifiedHandshake.peerCertificates());
String maybeProtocol = connectionSpec.supportsTlsExtensions()
? Platform.get().getSelectedProtocol(sslSocket)
: null;
socket = sslSocket;
// 获取source及sink
source = Okio.buffer(Okio.source(socket));
sink = Okio.buffer(Okio.sink(socket));
handshake = unverifiedHandshake;
protocol = maybeProtocol != null
? Protocol.get(maybeProtocol)
: Protocol.HTTP_1_1;
success = true;
} catch (AssertionError e) {
if (Util.isAndroidGetsocknameError(e)) throw new IOException(e);
throw e;
} finally {
if (sslSocket != null) {
Platform.get().afterHandshake(sslSocket);
}
if (!success) {
closeQuietly(sslSocket);
}
}
}
- 基于之前建立的 Socket 建立包装类 SSLSocket
- 对 TLS 相关信息进行配置
- 通过 SSLSocket 进行握手 最后 验证一些证书相关信息 ,我们在这个步骤,进行证书的锁定,给我们的域名 域名host 添加 sha256的证书,配置后,这个域名的请求就不能被抓包了。因为开启抓包后,根证书是 charles 的公钥,跟期望的 sha256 匹配不上。