侧边栏壁纸
博主头像
DOKI SEKAI博主等级

行动起来,活在当下

  • 累计撰写 114 篇文章
  • 累计创建 38 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

基于 Java 获取用户真实 IP 并检测是否使用了代理

君
2024-10-23 / 0 评论 / 0 点赞 / 16 阅读 / 8927 字

项目目标:基于 Java 获取用户真实 IP 并检测是否使用了代理

该项目的目标是通过 Java 实现以下功能:

  1. 获取用户的真实 IP 地址
  2. 通过 API 接口查询 IP 是否为代理
  3. 通过端口探测和流量分析检测代理/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.ioIPStackIP2Proxy 等)查询 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,并检查响应中的 proxyhosting 字段。

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 依赖于 NpcapWinPcap 库来捕获网络数据包。

解决方案

  1. 下载并安装 Npcap
  2. 确保安装时启用了 WinPcap API-compatible mode
  3. 确保 Npcap 安装路径已添加到系统 PATH 环境变量中。
  4. 以管理员身份运行程序,确保有足够权限进行网络数据包捕获。

2.2 获取不到网卡信息或提示无网络连接

这种情况通常发生在系统无法识别网络接口时。

解决方案

  1. 使用 PowerShell 或命令提示符查看网卡名称:
    • PowerShell 命令:
      Get-NetAdapter
      
    • 命令提示符命令:
      ipconfig /all
      
  2. 确保在 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. 总结

该项目结合了三种代理检测方法:

  1. 基于 API 的代理检测:通过调用 IPinfo 等 API 查询 IP 地址是否为代理。
  2. 基于端口探测:通过探测常见代理/VPN 使用的端口来检测代理。
  3. 基于流量分析:使用 Pcap4J 捕获并分析网络数据包,检测代理特征。
0

评论区