凌峰创科服务平台

Android HTTP代理服务器如何搭建与配置?

  1. 应用层代理:在你的 App 内部创建一个 HTTP 代理服务器,用于拦截、修改或转发该 App 自己发出的所有网络请求,这是最常见的需求,通常用于抓包、调试或实现自定义的网络逻辑。
  2. 系统层代理:设置整个 Android 设备的系统代理,使得所有 App(包括系统应用)的网络流量都通过指定的代理服务器,这通常需要设备已 Root,或者通过 VPN、代理 Auto-Config (PAC) 等方式实现。

下面我将重点讲解第一种应用层代理,因为它不依赖 Root 权限,是开发者最常使用的技术,然后简要介绍第二种系统层代理的实现方式。

Android HTTP代理服务器如何搭建与配置?-图1
(图片来源网络,侵删)

应用层 HTTP 代理 (App 内部)

在 App 内部实现一个 HTTP 代理服务器,最核心的技术是 Proxy 类和 WebView 的代理设置,你可以使用一个轻量级的网络库来快速搭建代理服务器,NettyOkHttp

这里我们以一个基于 OkHttp 的简单代理服务器为例,因为它代码简洁,易于理解。

工作原理

  1. 启动一个本地服务器:在你的 App 中启动一个运行在本地(如 0.0.1:8888)的 TCP 服务器。
  2. 设置 App 代理:将 App 的网络请求(WebView 或使用 OkHttp/HttpURLConnection 的请求)指向这个本地代理服务器。
  3. 拦截与转发
    • 当 App 发起一个 HTTP 请求(http://www.google.com)时,请求并不会直接发往 google.com,而是先发到你的本地代理服务器 (0.0.1:8888)。
    • 你的本地代理服务器接收到这个请求后,会完整地解析出原始的目标地址(www.google.com)和请求内容(GET/POST, headers, body 等)。
    • 你的代理服务器代替 App,向真正的目标地址(www.google.com)发起请求。
    • 服务器将收到的响应再返回给你的 App。

在这个过程中,你就有机会在代理服务器中查看、修改甚至丢弃任何请求和响应。

实现步骤

添加依赖

在你的 app/build.gradle 文件中添加 OkHttp 依赖:

Android HTTP代理服务器如何搭建与配置?-图2
(图片来源网络,侵删)
dependencies {
    implementation("com.squareup.okhttp3:okhttp:4.12.0") // 使用最新版本
}

创建代理服务器

这是一个核心类,它负责接收来自 App 的请求,并转发到目标服务器。

import okhttp3.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SimpleProxyServer {
    private final int port;
    private ExecutorService executorService;
    private ServerSocket serverSocket;
    private volatile boolean isRunning;
    public SimpleProxyServer(int port) {
        this.port = port;
    }
    public void start() {
        isRunning = true;
        executorService = Executors.newCachedThreadPool();
        try {
            serverSocket = new ServerSocket(port);
            System.out.println("Proxy server started on port " + port);
            while (isRunning) {
                // 接受来自客户端(App)的连接
                Socket clientSocket = serverSocket.accept();
                // 为每个连接创建一个任务来处理
                executorService.execute(new ProxyTask(clientSocket));
            }
        } catch (IOException e) {
            if (isRunning) {
                e.printStackTrace();
            }
        } finally {
            stop();
        }
    }
    public void stop() {
        isRunning = false;
        if (serverSocket != null && !serverSocket.isClosed()) {
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (executorService != null) {
            executorService.shutdown();
        }
        System.out.println("Proxy server stopped.");
    }
    // 处理单个代理连接的任务
    private static class ProxyTask implements Runnable {
        private final Socket clientSocket;
        ProxyTask(Socket clientSocket) {
            this.clientSocket = clientSocket;
        }
        @Override
        public void run() {
            try (InputStream clientInput = clientSocket.getInputStream();
                 OutputStream clientOutput = clientSocket.getOutputStream()) {
                // 1. 读取客户端(App)发来的HTTP请求头,解析出目标主机和端口
                byte[] buffer = new byte[4096];
                int bytesRead = clientInput.read(buffer);
                if (bytesRead == -1) return;
                String request = new String(buffer, 0, bytesRead);
                System.out.println("--- Received Request ---\n" + request);
                // 解析目标地址 ( GET http://www.google.com/ HTTP/1.1)
                String[] requestLines = request.split("\r\n");
                String[] requestParts = requestLines[0].split(" ");
                if (requestParts.length < 2 || !requestParts[1].startsWith("http://")) {
                    // 不是有效的HTTP请求,直接关闭
                    clientSocket.close();
                    return;
                }
                String targetUrl = requestParts[1];
                String host = targetUrl.substring(7).split("/")[0]; // 去掉 "http://"
                String[] hostPort = host.split(":");
                String hostname = hostPort[0];
                int port = hostPort.length > 1 ? Integer.parseInt(hostPort[1]) : 80;
                // 2. 连接到真正的目标服务器
                try (Socket serverSocket = new Socket(hostname, port);
                     OutputStream serverOutput = serverSocket.getOutputStream();
                     InputStream serverInput = serverSocket.getInputStream()) {
                    // 3. 将客户端的请求转发给服务器
                    serverOutput.write(buffer, 0, bytesRead);
                    // 4. 读取服务器的响应,并转发回客户端
                    while ((bytesRead = serverInput.read(buffer)) != -1) {
                        clientOutput.write(buffer, 0, bytesRead);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    clientSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

注意:上面的 SimpleProxyServer 是一个非常基础的实现,它只处理了简单的 HTTP 请求,不处理 HTTPS(需要处理 CONNECT 方法)、分块传输、WebSocket 等,在实际项目中,推荐使用成熟的库如 Netty 来构建,或者直接使用 OkHttpProxy 机制。

在 App 中启动代理并设置

我们可以在 ActivityApplication 类中启动这个代理服务器,并将其配置给 WebView

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
    private SimpleProxyServer proxyServer;
    private WebView webView;
    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = findViewById(R.id.webview);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebViewClient(new WebViewClient());
        // 启动代理服务器
        proxyServer = new SimpleProxyServer(8888);
        new Thread(proxyServer::start).start();
        // 设置WebView使用本地代理
        // 注意:Android 9 (Pie) 以后,WebView 默认使用系统网络栈,需要设置此标志
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
            WebView.setWebContentsDebuggingEnabled(true); // 方便Chrome DevTools调试
            // 使用Proxy.NO_PROXY表示不使用系统代理,而是由WebView自己处理
            // 然后我们通过下面的方式注入代理逻辑,这通常需要更复杂的实现
            // 对于简单的演示,我们使用OkHttp来发起网络请求,而不是WebView
        }
        // --- 更推荐的做法:使用OkHttp发起请求 ---
        // 因为直接让WebView使用我们自己的OkHttp代理服务器比较复杂,
        // 更简单的方式是让App的所有网络请求都通过OkHttp,并设置OkHttp的代理。
        // 演示:使用OkHttp通过代理访问网络
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8888)))
                .build();
        Request request = new Request.Builder()
                .url("https://www.httpbin.org/get")
                .build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String responseData = response.body().string();
                runOnUiThread(() -> {
                    // 在UI线程显示结果
                    webView.loadData(responseData, "text/plain", "UTF-8");
                });
            }
        });
    }
    @
Android HTTP代理服务器如何搭建与配置?-图3
(图片来源网络,侵删)
分享:
扫描分享到社交APP
上一篇
下一篇