Java,Socket,实现Socket4代理服务器,客户端用Socket4代理请求

前言Socket代理协议
Socket代理协议有Socket4和Socket5两个版本,Socket4协议只支持TCP/IP,Socket代理协议只是单纯传递数据包,不关心具体协议和用法,所以速度快很快 。
Socket4代理已经过时了,支持Socket4代理,需要自己编写协议,这里研究是为了抓一些数据包供分析 。
协议:
http://www.openssh.com/txt/socks4.protocol
协议说明
客户端请求,服务器端绑定 。
【Java,Socket,实现Socket4代理服务器,客户端用Socket4代理请求】请求:|VN-1|CD-1|DSTPORT-2|DSTIP-4|NULL...|
响应:|VN-1|CD-1|DSTPORT-2|DSTIP-4|
Socket4代理服务器一个类可以搞定~
代码实现
import JAVA.io.*;import java.NET.*;import java.util.Arrays;import java.util.Base64;import java.util.concurrent.*;import java.util.regex.Matcher;import java.util.regex.Pattern;public class Socks4Server {// constantsprivate static final int MAX_REQUEST_BYTES_NUMBER = 50;private static final int MINIMUM_REQUEST_LENGTH = 8;private static final int REQUEST_OK = 90;private static final int REQUEST_REJECTED_OR_FAILED = 91;private static final int MAX_PARALLEL_CONNECTIONS = 20;private static final int PROTOCOL_VERSION = 4;private static final int CONNECT_REQUEST = 1;private static final int TIMEOUT_TIME = 2000;private static final int BUF_SIZE = 4096;// error message definitionsprivate static final String SUCCESSFUL_CONNECTION = "Successful connection from ";private static final String PASSword_FOUND = "Password found! ";private static final String CLOSING_CONNECTION = "Closing connection from: ";private static final String CONNECTER_ERROR = "Unknown Connection Error";private static final String UNSUPPOERTED_SOCKS_PROT = "Unsupported SOCKS protocol version ";private static final String UNKNOWN_SOCKS_COMMAND_ERROR = "Unknown socks command! currently supports only CONNECT request";private static final String ILLEGAL_IP_LENGTH = "IP address is of illegal length";private static final String ILLEGAL_REQUEST_LENGTH_ERROR = "The request has an illegal length - under 8 characters";private static final String ILLEGAL_PORT_NUMBER_ERROR = "Illegal port number. given port number is 0";private static final String CONNECTION_TO_DESTINATION_IP_FAILED = "Connection error: while connecting to destination: connect timed out";private static final String TIMOUT_ERROR = "Timeout limit reached closing all connection";private static final String CLIENTHOSTIOERROR = "Error during client host communication";private static final String NOCONNECT = "No connect message received";/*** @param args*/public static void main(String[] args) {// 服务端口int port = 1080;try (ServerSocket serverSocket = new ServerSocket(port)) {// 线程池ThreadPoolExecutor connections = new ThreadPoolExecutor(0, MAX_PARALLEL_CONNECTIONS,1, TimeUnit.HOURS, new ArrayBlockingQueue(1), new RejectedConnection());while (true) {try {connections.submit(new Handler(serverSocket.accept()));} catch (Exception e) {System.err.println("与客户端的连接过程中出错");}}} catch (Exception e) {System.err.println("代理服务器崩溃");}}/*** SOCKS4服务器拒绝*/private static class RejectedConnection implements RejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {executor.remove(r);System.err.println("服务器容量已满,连接请求已被拒绝.");}}/*** 处理实际连接*/private static class Handler extends Thread {private Socket clientSocket;private int destinationPort;private InetAddress destinationIP;Handler(Socket clientSocket) {this.clientSocket = clientSocket;}@Overridepublic void run() {try (DataInputStream clientInput = new DataInputStream(clientSocket.getInputStream());DataOutputStream clientOutput = new DataOutputStream(clientSocket.getOutputStream())) {// 设置客户端超时时间clientSocket.setSoTimeout(TIMEOUT_TIME);// 读取来自客户端的请求byte[] byteArray = new byte[MAX_REQUEST_BYTES_NUMBER];int successFlag = clientInput.read(byteArray);if (successFlag == -1) {System.err.println("已到达流的末端");throw new NullPointerException();}// 处理连接请求并生成响应byte[] response = processRequest(byteArray);// 错误的请求导致连接被拒绝if (response[1] == REQUEST_REJECTED_OR_FAILED) {clientOutput.write(response);clientOutput.flush();closingClientConnectionMessage(clientSocket);} else if (response[1] == REQUEST_OK) {// 正常连接try (Socket hostSocket = new Socket(destinationIP, destinationPort);BufferedWriter HostOutput = new BufferedWriter(new OutputStreamWriter(hostSocket.getOutputStream()))) {hostSocket.setSoTimeout(TIMEOUT_TIME);clientOutput.write(response);clientOutput.flush();// 连接成功successfulConnectionMessage(clientSocket);try (BufferedReader clientBufReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {ExecutorService IOService = Executors.newFixedThreadPool(2);if (destinationPort == 80) {processClientDataHTTP(clientBufReader, HostOutput);}// 数据交换while (true) {ioService.submit(new ProcessData(clientSocket.getOutputStream(), hostSocket.getInputStream()));ioService.submit(new ProcessData(hostSocket.getOutputStream(), clientSocket.getInputStream()));if (!ioService.awaitTermination(TIMEOUT_TIME, TimeUnit.MILLISECONDS)) {throw new SocketTimeoutException();}}} catch (SocketTimeoutException e) {closingConnectionMessage(clientSocket);} catch (IOException e) {System.err.println(CLIENTHOSTIOERROR);}} catch (Exception e) {response[1] = REQUEST_REJECTED_OR_FAILED;clientOutput.write(response);clientOutput.flush();System.err.println(CONNECTION_TO_DESTINATION_IP_FAILED);closingClientConnectionMessage(clientSocket);}}} catch (NullPointerException e) {System.err.println(NOCONNECT);} catch (SocketTimeoutException e) {System.err.println(TIMOUT_ERROR);} catch (IOException e) {System.err.println(CONNECTER_ERROR);} finally {try {clientSocket.close();} catch (IOException e) {System.err.println("关闭过程中出错");}}}/*** 主机通信*/private class ProcessData implements Runnable {OutputStream out;InputStream in;private ProcessData(OutputStream out, InputStream in) {this.in = in;this.out = out;}@Overridepublic void run() {try {byte[] buf = new byte[BUF_SIZE];int numOfbytes = 0;int numOfLine = 0;while ((numOfbytes = in.read(buf)) > 0 && numOfbytes < BUF_SIZE) {System.out.print(String.format("%02x", numOfbytes) + " ");if (numOfLine % 16 == 0) {System.out.println();}numOfLine++;out.write(buf, 0, numOfbytes);}} catch (Exception e) {return;}}}/*** @param clientBufReader* @param HostOutput* @throws Exception*/private void processClientDataHTTP(BufferedReader clientBufReader, BufferedWriter HostOutput) throws Exception {String line = "";StringBuilder clientData = https://www.isolves.com/it/wlyx/fwq/2022-09-02/new StringBuilder();line = clientBufReader.readLine();// regex definitionPattern authorizationPattern = Pattern.compile("^[Aa]uthorization: [Bb]asic (.*)");String credentials = "";Pattern hostPattern = Pattern.compile("Host: (.*)");String hostName = "";Base64.Decoder decoder = Base64.getDecoder();// 读取客户端数据while (clientBufReader.ready()) {// password/username regexMatcher authorizationMatcher = authorizationPattern.matcher(line);if (authorizationMatcher.matches()) {credentials = authorizationMatcher.group(1);credentials = new String(decoder.decode(credentials.getBytes("UTF-8")));}// hostname regexMatcher hostMatcher = hostPattern.matcher(line);if (hostMatcher.matches()) {hostName = hostMatcher.group(1);}// parsing requestclientData.Append(line);clientData.append("rn");line = clientBufReader.readLine();}System.out.println(PASSWORD_FOUND + "http//:" + credentials + "@" + hostName);clientData.append("rnrn");HostOutput.write(clientData.toString());HostOutput.flush();}private void successfulConnectionMessage(Socket clientSocket) {System.out.println(SUCCESSFUL_CONNECTION + clientSocket.getInetAddress().getHostAddress() + ":" + clientSocket.getPort() + " to " + destinationIP.getHostAddress() + ":" + destinationPort);}private void closingConnectionMessage(Socket clientSocket) {System.out.println(CLOSING_CONNECTION + clientSocket.getInetAddress().getHostAddress() + ":" + clientSocket.getPort() + " to " + destinationIP.getHostAddress() + ":" + destinationPort);}private void closingClientConnectionMessage(Socket clientSocket) {System.out.println(CLOSING_CONNECTION + clientSocket.getInetAddress().getHostAddress() + ":" + clientSocket.getPort());}/*** @param request - the client request* @return response - the SOCKS4 server response*/private byte[] processRequest(byte[] request) {byte[] response = new byte[8];byte replyStatus = REQUEST_OK;// 检查请求是否有效if (!isRequestLengthLegal(request, response) ||!processProtocolVersionRequest(request[0]) ||!processSOCKScommandCode(request[1]) ||!processDestinationPortNumber(request[2], request[3]) ||!processDestinationIP(request)) {System.out.println("请求被拒绝!");replyStatus = REQUEST_REJECTED_OR_FAILED;}response[1] = replyStatus;return response;}// VN - SOCKS protocol version numberprivate boolean processProtocolVersionRequest(byte version) {if (version != PROTOCOL_VERSION) {System.err.println(UNSUPPOERTED_SOCKS_PROT + "(got " + version + ")");return false;}return true;}// DSPORTprivate boolean processDestinationPortNumber(byte firstByte, byte secondByte) {this.destinationPort = (firstByte & 0xff)


推荐阅读