我创建了一个本地代理服务器来拦截所有网络流量。该代码拦截http / https流量。代理可以在Eclipse中正常工作,但是当我将其与android项目集成时,它仅适用于http流量。
最初,它不适用于http流量,这还因为未在Android中保护套接字不受VpnService的攻击。一旦通道的套接字被保护为http,它就可以正常工作。
import java.io.*;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.regex.Pattern;
public class Server extends Thread {
public static void main(String[] args) {
(new Server()).run();
}
@Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(9999)) {
Socket socket;
try {
while ((socket = serverSocket.accept()) != null) {
(new Handler(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
public static class Handler extends Thread {
public static final Pattern CONNECT_PATTERN = Pattern.compile("CONNECT (.+):(.+) HTTP/(1\\.[01])", Pattern.CASE_INSENSITIVE);
public int port = 80;
private final Socket clientSocket;
public Handler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
@Override
public void run() {
try {
byte[] buffer = new byte[4096];
InputStream browserInputStream = clientSocket.getInputStream();
int n = browserInputStream.read(buffer);
String browserRequest = new String(buffer, 0, n);
String[] requestLines = browserRequest.split("\r\n");
if (requestLines[0].startsWith("CONNECT")) {
//HTTPS TRAFFIC
//Browser Request Received
String[] connectRequest = requestLines[0].split(" ");
String urlAndPort = connectRequest[1];
String url = urlAndPort.split(":")[0];
int port = Integer.parseInt(urlAndPort.split(":")[1]);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(clientSocket.getOutputStream());
final Socket forwardSocket;
try {
forwardSocket = new Socket(url, port);
} catch (IOException | NumberFormatException e) {
e.printStackTrace();
outputStreamWriter.write("HTTP/" + "1.1" + " 502 Bad Gateway\r\n");
outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
outputStreamWriter.write("\r\n");
outputStreamWriter.flush();
return;
}
try {
//OK Response sent to browser
outputStreamWriter.write("HTTP/" + "1.1" + " 200 Connection established\r\n");
outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
outputStreamWriter.write("\r\n");
outputStreamWriter.flush();
Thread remoteToClient = new Thread() {
@Override
public void run() {
forwardData(forwardSocket, clientSocket);
}
};
remoteToClient.start();
try {
forwardData(clientSocket, forwardSocket);
} finally {
try {
remoteToClient.join();
} catch (InterruptedException e) {
e.printStackTrace(); // TODO: implement catch
}
}
} finally {
forwardSocket.close();
}
} else {
//HTTP TRAFFIC
int start = browserRequest.indexOf("Host: ") + 6;
int end = browserRequest.indexOf('\n', start);
String host = browserRequest.substring(start, end - 1);
SocketChannel proxyToServerChannel = SocketChannel.open();
Socket proxyToServerSocket = proxyToServerChannel.socket();
//VpnServiceHelper.protect(proxyToServerSocket) //Protect the socket from VPNSERVICE
InetSocketAddress serverAddress = new InetSocketAddress(host, port);
proxyToServerChannel.configureBlocking(false);
proxyToServerChannel.connect(serverAddress);
while (!proxyToServerChannel.finishConnect());
ByteBuffer buf = ByteBuffer.wrap(buffer);
proxyToServerChannel.write(buf);
try {
InputStream inputStream = proxyToServerSocket.getInputStream();
try {
OutputStream outputStream = clientSocket.getOutputStream();
try {
int read = 0;
do {
if (read == 0)
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
read = proxyToServerChannel.read(ByteBuffer.wrap(buffer));
if (read > 0) {
clientSocket.getOutputStream().write(buffer);
if (inputStream.available() < 1) {
outputStream.flush();
}
}
} while (read >= 0);
} finally {
if (!clientSocket.isOutputShutdown()) {
clientSocket.shutdownOutput();
}
}
} finally {
if (!proxyToServerSocket.isInputShutdown()) {
proxyToServerSocket.shutdownInput();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void forwardData(Socket inputSocket, Socket outputSocket) {
try {
InputStream inputStream = inputSocket.getInputStream();
try {
OutputStream outputStream = outputSocket.getOutputStream();
try {
byte[] buffer = new byte[4096];
int read;
do {
read = inputStream.read(buffer);
if (read > 0) {
outputStream.write(buffer, 0, read);
if (inputStream.available() < 1) {
outputStream.flush();
}
}
} while (read >= 0);
} finally {
if (!outputSocket.isOutputShutdown()) {
outputSocket.shutdownOutput();
}
}
} finally {
if (!inputSocket.isInputShutdown()) {
inputSocket.shutdownInput();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}