项目目标:基于 Java 获取用户真实 IP 并检测是否使用了代理
该项目的目标是通过 Java 实现以下功能:
- 获取用户的真实 IP 地址。
- 通过 API 接口查询 IP 是否为代理。
- 通过端口探测和流量分析检测代理/VPN。
通过这三种方法结合,确保实现更精确的代理检测。
1. 项目的核心功能:
1.1 获取用户的真实 IP 地址
通过 HttpServletRequest
对象可以获取访问者的直接 IP 地址,并结合检查 HTTP 头信息(如 X-Forwarded-For
),获取可能经过代理的真实 IP。
import javax.servlet.http.HttpServletRequest;
public class IPAddressUtil {
// 获取访问者的直接 IP 地址
public static String getDirectClientIp(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For"); // 检查代理头
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr(); // 返回直接的 IP 地址
}
return ip;
}
}
- 真实 IP 的判断:
X-Forwarded-For
等 HTTP 头可能提供原始客户端的 IP 信息。如果这些头部不可用,返回通过getRemoteAddr()
获取的 IP。
1.2 通过 API 查询 IP 是否为代理
为了检测 IP 是否是通过代理或 VPN 访问,你可以使用第三方 API 服务(如 IPinfo.io
、IPStack
、IP2Proxy
等)查询 IP 地址的详细信息。
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;
public class IPChecker {
// 使用 IPinfo API 检查 IP 是否为代理
public static boolean isVpnOrProxy(String ipAddress) {
try {
URL url = new URL("https://ipinfo.io/" + ipAddress + "/json");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
InputStream responseStream = connection.getInputStream();
Scanner scanner = new Scanner(responseStream).useDelimiter("\\A");
String responseBody = scanner.hasNext() ? scanner.next() : "";
scanner.close();
// 检查响应内容是否包含代理或托管服务信息
return responseBody.contains("\"proxy\": true") || responseBody.contains("\"hosting\": true");
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
- API 查询功能:调用 IPinfo API 接口,查询 IP 地址是否属于代理或 VPN,并检查响应中的
proxy
或hosting
字段。
1.3 通过端口探测和流量分析
许多代理和 VPN 服务使用常见的端口号(如 8080、1080、1194 等)。通过探测这些端口是否开放,可以推断 IP 是否使用了代理服务。此外,通过 Pcap4J
库捕获和分析网络流量,检查是否存在代理流量特征。
端口探测
可以使用 Java 的 Socket
类来检测目标 IP 的常见代理端口。
import java.io.IOException;
import java.net.Socket;
public class PortScanner {
// 检测目标 IP 是否开放指定的端口
public static boolean isPortOpen(String ip, int port) {
try (Socket socket = new Socket(ip, port)) {
return true; // 端口开放
} catch (IOException e) {
// 端口关闭或连接失败
return false;
}
}
public static void main(String[] args) {
String ip = "8.8.8.8"; // 示例IP
int[] ports = {80, 443, 8080, 1080, 1194}; // 常见代理/VPN端口
for (int port : ports) {
boolean isOpen = isPortOpen(ip, port);
System.out.println("端口 " + port + " 是否开放: " + isOpen);
}
}
}
- 端口探测:常见的代理和 VPN 服务使用的端口包括 80(HTTP)、443(HTTPS)、8080(HTTP 代理)、1080(SOCKS5 代理)、1194(OpenVPN)。通过检测这些端口是否开放,可以初步判断是否为代理服务。
流量分析
使用 Pcap4J
库捕获流量,分析其协议特征以识别是否为代理或 VPN。
import org.pcap4j.core.*;
import org.pcap4j.packet.IpV4Packet;
import org.pcap4j.packet.Packet;
public class PacketCapture {
private static final String NIF_NAME = "eth0"; // 网络接口名称
public static void captureTraffic() {
try {
PcapNetworkInterface nif = Pcaps.getDevByName(NIF_NAME); // 获取网络接口
PcapHandle handle = nif.openLive(65536, PcapNetworkInterface.PromiscuousMode.PROMISCUOUS, 10);
// 设置过滤器,只捕获 IPv4 数据包
handle.setFilter("ip", BpfProgram.BpfCompileMode.OPTIMIZE);
// 开始捕获并分析数据包
handle.loop(10, new PacketListener() {
@Override
public void gotPacket(Packet packet) {
if (packet.contains(IpV4Packet.class)) {
IpV4Packet ipV4Packet = packet.get(IpV4Packet.class);
System.out.println("捕获到 IPv4 数据包,源IP: " + ipV4Packet.getHeader().getSrcAddr());
}
}
});
handle.close();
} catch (PcapNativeException | NotOpenException | InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
captureTraffic();
}
}
- 流量捕获:通过
Pcap4J
捕获 TCP/UDP 流量,并分析数据包中的 IP 地址和协议类型。
2. 解决遇到的问题
2.1 错误:java.lang.UnsatisfiedLinkError: Unable to load library 'wpcap': 找不到指定的模块
该错误是由于 Windows 系统无法找到 wpcap.dll
动态链接库。Pcap4J
依赖于 Npcap
或 WinPcap
库来捕获网络数据包。
解决方案:
- 下载并安装 Npcap。
- 确保安装时启用了 WinPcap API-compatible mode。
- 确保
Npcap
安装路径已添加到系统PATH
环境变量中。 - 以管理员身份运行程序,确保有足够权限进行网络数据包捕获。
2.2 获取不到网卡信息或提示无网络连接
这种情况通常发生在系统无法识别网络接口时。
解决方案:
- 使用 PowerShell 或命令提示符查看网卡名称:
- PowerShell 命令:
Get-NetAdapter
- 命令提示符命令:
ipconfig /all
- PowerShell 命令:
- 确保在
Pcap4J
中使用正确的网卡名称。
3. 完整的 pom.xml
文件
为了使用 Pcap4J
进行流量捕获,并且结合日志输出,你需要在 pom.xml
文件中引入以下依赖项:
<properties>
<java.version>21</java.version> <!-- 设置为 JDK 21 -->
</properties>
<dependencies>
<!-- Pcap4J 核心库,用于捕获和分析网络数据包 -->
<dependency>
<groupId>org.pcap4j</groupId>
<artifactId>pcap4j-core</artifactId>
<version>1.8.1</version>
</dependency>
<!-- Pcap4J 包含各种协议包的静态工厂类 -->
<dependency>
<groupId>org.pcap4j</groupId>
<artifactId>pcap4j-packetfactory-static</artifactId>
<version>1.8.1</version>
</dependency>
<!-- 日志框架(可选),用于输出日志信息 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId
>
<version>1.7.30</version>
</dependency>
</dependencies>
4. 总结
该项目结合了三种代理检测方法:
- 基于 API 的代理检测:通过调用 IPinfo 等 API 查询 IP 地址是否为代理。
- 基于端口探测:通过探测常见代理/VPN 使用的端口来检测代理。
- 基于流量分析:使用
Pcap4J
捕获并分析网络数据包,检测代理特征。
评论区