浅谈IP归属地检测
IP归属地检测故名思义, 是通过IP协议中的src地址来确定其所属的地理位置. 通过识别用户IP归属, 可以实现限制地区用户访问(OpenAI)、推荐地区用户喜好、展示评论用户所在城市等功能诉求. 本篇文章, 我们讲一下IP归属地检测的原理及方法, 以及翻墙绕过检测的方法.
IP协议基础
首先, 我们重温一下IP协议的基础知识. IP协议位于传统OSI7层模型 (Open Systems Interconnection model ) 中的网络层, 负责设备在复杂网络中通信时的寻址addressing、路由routing 等职责. IP协议本身是无状态、无连接、无顺序、不可靠的, 这些特性如需要均要由上层传输层如tcp协议的ack和重传机制保证. IP协议本身不care这些问题, 遇到网络拥堵、路由设备缓冲区满等情况, 均会直接将IP包丢弃.
目前, IP网络层上层的主流传输层协议仍是 tcp 和 udp协议, 一些新的号称新传输层协议如quic等也是在udp协议上层进行了拓展. 换句话说, 基本上所有的服务端应用本质上均是对 tcp、udp端口的监听, 解析并响应来自客户的请求报文.
不管是tcp还是udp, 由于底层都是IP协议. 在发送报文时, 客户端都会在IP层报文携带src(本机ip 192.168.1.100)和dest ip地址(内网or公网). dest ip 会经由路由器层层寻址交由下次网关路由, 而src ip 也会在途径WAN网关时, NAT至公网IP地址. 公网IP的IP包不会再被修改, 并会经过路由表逐跳层层寻址最终抵达目标设备, 可能是一个F5、一个用户PC等, 这个过程不再详细分析了. 最终, 其实服务端可以很轻松的拿到客户请求中的公网src ip, 这个src ip最多是个代理, 但是是不会造假的, 因为造假的话服务端的响应回传client就接收不到了.
翻墙代理
翻墙代理目前基本也是两大类, 一类是VPN, 一类是VPS. 前者是用虚拟网卡+隧道, 后者是代理服务+数据加密. 前者功能更丰富, 对server端的要求更高, 出于成本角度, 只为了翻墙基本都是采用VPS+部署代理服务.
VPS就是一台境外ip、且未被墙的虚机, 可供国内ip访问连接, 并且部署了代理服务. 代理服务也有很多种, 提供的代理能力也分369等, 有只代理http的, 只代理tcp的, 也有tcp + udp均可代理的. 如果是自己搭的vps, 就可以安装个支持tcp+udp的代理, 一般直接买的SaaS多节点代理服务, 通常只支持http or tcp请求代理.
浏览器UDP通信
早期浏览器网页内容均由基于tcp的http1.1/2协议或 websocket协议提供, 这种场景下, 只要用户开个具备http or tcp代理能力的翻墙软件, 再在浏览器装个http代理插件, 即可隐藏自己国内ip. 但随着浏览器对http3 QUIC和webrtc api的支持, 浏览器逐步开始向udp通信变迁. 浏览器udp通信时, 如果你只将tcp包交由代理转发, 对端sever拿到的client src ip 自然还是你的udp本地出局ip.
尽管如此, 对于使用了http3 QUIC和 WebRTC的网站来说, 如果想隐藏自己的大陆ip, 也只要把代理服务升级下, 让UDP包也经由代理转发路由即可. 因为不管是tcp还是udp, 只要让对应的网络层ip数据包经由代理的境外IP发出即可解决问题.
WebRTC STUN协议
WebRTC是基于UDP的浏览器即时通讯模块, 通过浏览器的WebRTC api, 可以实现P2P端到端的实时数据通信, 目前已经广泛用于视频会议、文件数据传输、IM等场景. WebRTC可以实现网络互通的任意两台设备的P2P通信, 比如, 属于同一内网的两台内网pc、或均支持公网udp通信的两台互联网PC. 做P2P通信前, 首先要知道对方的 IP地址 & UDP通信端口( SDP session description protocol). WebRTC中对如何获取对方的SDP信息不做要求, 本端可以先获取到自身的IP及端口信息, 再通过自研一套IM信令互相通知, 甚至可以直接微信聊天发送给对方. 只要知道互相知道了对端SDP, 便可进行通信.
传输SDP不是WebRTC考虑的问题, 但各端如何获取自己的SDP是其要解决的问题, WebRTC api中, 各端可以获取到本机的网卡ip地址, 并随机一个udp端口来进行后续通信, 如 192.168.1.100 : 65530, 但是, 如果将这个作为SDP发给对端, 对方如果不在同一个子网下, 数据肯定是发送不过来的. 所以WebRTC需要提供能力, 让各端获取自己的公网IP及NAT后的UDP端口. 这套协议便是 STUN协议.
Rfc5389 规定了STUN协议细节, 简单总结下来, STUN是一个具备多公网IP的UDP服务, 侦听来自客户的udp请求, 并试图使用不同的ip及端口, 将客户udp packet的 src ip src port内容原路进行返回. 从而检测客户的公网IP及NAT限制类型(full cone、 ip or port restrict).
在IP归属地探测场景, 也可以使用该API, 让客户浏览器发送一个UDP包到server, 从而额外检测客户的UDP包IP地址的归属地. 但正如之前所说, 如果客户的udp包也是经由代理发出的, 则也无法检测出真实IP.