导语

为什么我开了浏览器爬虫还是经常被风控?是因为浏览器指纹?还是因为浏览器的特征没被抹除?明明各种措施都已经添加了,可还是会被识别?这时候我们可能需要思考一下,是不是我们的源IP暴露了?

源IP暴露?不太可能吧,明明已经挂了代理IP,并且访问IP网站也显示的是代理IP的地址,怎么可能是源IP暴露呢?当然,普通的挂代理方式应对一些网站是没问题的,但是如果对方是根据webrtc来获取你的IP呢?

什么是webrtc

webrtc是一种web实时通信技术,使 Web 应用程序和站点能够捕获并可选择流式传输音频和/或视频媒体,以及在浏览器之间交换任意数据,而无需中介。构成 WebRTC 的一组标准使得共享数据和执行点对点电话会议成为可能,而无需用户安装插件或任何其他第三方软件。

webrtc的实现是建立浏览器之间的连接而无需服务器中转,即P2P。因此要求彼此知道对方网络的地址。但是计算机网络大多是位于NAT之后,少数主机拥有外网地址。这就需要NAT穿透技术,即STUN、TRUN。比如Google就有一个STUN服务,其地址为:stun:stun.l.google.com:19302,比如Mozilla也有STUN地址为:stun:stun.services.mozilla.com。其实拥有STUN的服务有很多,我这里写了一些:stun:stun.ekiga.net,stun:stun.ideasip.com,stun:stun.rixtelecom.se,stun:stun.schlund.de,stun:stun.stunprotocol.org:3478,stun:stun.voiparound.com,stun:stun.voipbuster.com,stun:stun.voipstunt.com,stun:stun.voxgratia.org。

webrtc原理

要说webrtc原理,其实要介绍STUN原理(进行nat穿透),这里简单的赘述下:

我们都知道,要进行nat穿透需要知道双方的IP,但是由于我们的网络基本都是由nat进行分配的,很少会有自己独立的公网IP,所以我们需要对nat进行穿透,而stun服务就是来记录我们每次通过UDP发送包时的IP和端口,从而双方包的对等互通。如上图所示,我们通过客户端通过路由连接到stun server服务器,服务器此时已经知道了我们的公网IP以及公网连接的端口,此时,只需要其他服务器对客户端的公网IP和端口进行udp包发送,便可以实现nat的穿透,将数据包发送到我们的客户端。

另一方面,如果要获取客户端IP则更为简单,因为stun已经知道了客户端的IP。

webrtc应用

简单的了解了webrtc的通信,那么webrtc的应用场景有哪些呢?

比如视频会议和语音通话、广播、远程访问、文件共享、还有反爬等,当然这里只是列举了一部分的应用,他的应用场景还有很多,想要了解的大家可以baidu一下。

webrtc反爬

了解了webrtc,那么我们该怎么突破他的反爬呢。

这里我们先简单来测试一下,拥有webrtc测试的网站有很多,我这里使用的是:https://surfshark.com/zh/webrtc-leak-test(大家可以自己测试下)

首先我这里打开的是(当前我挂了韩国的代理):

可以看到,显示我的ip地址是124.160.217.177,那么,我韩国的代理是什么呢?这里我们打开ip138进行测试看下:

从上图可以看到, 韩国的代理IP和webrtc暴露的IP是不同的,而webrtc的IP是我的真IP,继续用IP138测试一下:

此时可以看到, 暴露的IP是相同的啦。此时你可能明白, 为什么爬虫明明挂了代理,但还是被风控了吧。

webrtc反反爬

对于我们的chrome,firefox针对于webrtc暴露IP的行为,chrome我们可以下载插件,Firefox我们可以通过设置来处理,但是对于我们驱动的浏览器该怎么处理呢?

相对与平常,大家应该常用selenium进行无头爬虫,那么对于selenium应该怎么处理呢?看代码:

import time
from selenium import webdriver
from fastapi import FastAPI

import requests
from selenium import webdriver

import time

options = webdriver.ChromeOptions()
proxy = "http://127.0.0.1:7890"
options.add_argument("--proxy-server={}".format(proxy))

# options.add_argument("--proxy-server=http://127.0.0.1:7798")
options.add_argument("--disable-blink-features=AutomationControlled")
# options.add_argument("--headless")
options.add_argument(
    "user-agent=Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option("useAutomationExtension", False)
options.add_argument("--disable-extensions")
preferences = {
    "webrtc.ip_handling_policy": "disable_non_proxied_udp",
    "webrtc.multiple_routes_enabled": False,
    "webrtc.nonproxied_udp_enabled": False
}
options.add_experimental_option("prefs", preferences)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": data
})
driver.get('https://surfshark.com/zh/webrtc-leak-test')
time.sleep(100000000)

此时, 我们再打开网站查看:

会发现此处一直在刷新,因为此时我们已经屏蔽掉了webrtc,当然除了这种方式,我们还可以通过设置参数来屏蔽,如:--disable-features=WebRtcHideLocalIpsWithMdns, 并且此种方式除了适用selenium,还适用playwright,puppeteer等浏览器

结语

上面我们了解到了如何搞定webrtc的ip暴露问题,但是通过以上方式真的能完全阻止webrtc的ip暴露吗?是不是还有其他的套路来获取,又是否还有其他的套路来绕过呢?