Socket代理协议Socket代理协议有Socket4和Socket5两个版本,Socket4协议只支持TCP/IP,Socket代理协议只是单纯传递数据包,不关心具体协议和用法,所以速度快很快,下面我们就来说一说关于java实现socket的send方法?我们一起去了解并探讨一下这个问题吧!

java实现socket的send方法(JavaSocket实现Socket4代理服务器)

java实现socket的send方法

前言

Socket代理协议

Socket代理协议有Socket4和Socket5两个版本,Socket4协议只支持TCP/IP,Socket代理协议只是单纯传递数据包,不关心具体协议和用法,所以速度快很快。

Socket4代理已经过时了,支持Socket4代理,需要自己编写协议,这里研究是为了抓一些数据包供分析。

协议:http://www.openssh.com/txt/socks4.protocol

协议说明

客户端请求,服务器端绑定。

请求:|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 { // constants private 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 definitions private 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 { @Override public 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; } @Override public 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; } @Override public 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("x", 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 = new StringBuilder(); line = clientBufReader.readLine(); // regex definition Pattern 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 regex Matcher authorizationMatcher = authorizationPattern.matcher(line); if (authorizationMatcher.matches()) { credentials = authorizationMatcher.group(1); credentials = new String(decoder.decode(credentials.getBytes("UTF-8"))); } // hostname regex Matcher hostMatcher = hostPattern.matcher(line); if (hostMatcher.matches()) { hostName = hostMatcher.group(1); } // parsing request clientData.append(line); clientData.append("\r\n"); line = clientBufReader.readLine(); } System.out.println(PASSWORD_FOUND "http//:" credentials "@" hostName); clientData.append("\r\n\r\n"); 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 number private boolean processProtocolVersionRequest(byte version) { if (version != PROTOCOL_VERSION) { System.err.println(UNSUPPOERTED_SOCKS_PROT "(got " version ")"); return false; } return true; } // DSPORT private boolean processDestinationPortNumber(byte firstByte, byte secondByte) { this.destinationPort = (firstByte & 0xff) << 8 | (secondByte & 0xff); if (this.destinationPort <= 0) { System.err.println(ILLEGAL_PORT_NUMBER_ERROR); return false; } return true; } // CD - SOCKS command code and should be 1 for CONNECT request private boolean processSOCKScommandCode(byte code) { if (code != CONNECT_REQUEST) { System.err.println(UNKNOWN_SOCKS_COMMAND_ERROR); return false; } return true; } // DSTIP private boolean processDestinationIP(byte[] requestArray) { try { // SOCKS 4A if (requestArray[4] == 0 && requestArray[5] == 0 && requestArray[6] == 0 && requestArray[7] != 0) { int start = 0; int end = 0; int i = 8; while (requestArray[i] != 0) { i ; } start = i 1; i ; while (requestArray[i] != 0) { i ; } end = i; destinationIP = InetAddress.getByName(new String(Arrays.copyOfRange(requestArray, start, end))); } // regular SOCKS else { destinationIP = InetAddress.getByAddress(Arrays.copyOfRange(requestArray, 4, 8)); } } catch (UnknownHostException e) { System.err.println(ILLEGAL_IP_LENGTH); return false; } return true; } // request length must be minimum of length 8 private boolean isRequestLengthLegal(byte[] request, byte[] response) { if (request.length < MINIMUM_REQUEST_LENGTH) { System.err.println(ILLEGAL_REQUEST_LENGTH_ERROR); return false; } // dest port response[2] = request[2]; response[3] = request[3]; // ip response[4] = request[4]; response[5] = request[5]; response[6] = request[6]; response[7] = request[7]; return true; } } }

客户端使用Socket4代理

客户端协议实现类

import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; public class Sock4Socket extends Socket { // 版本 private static byte VERSION4 = 0X04; // 请求 private static byte CONNECT_REQUEST = 0X01; private static byte BIND_REQUEST = 0X02; // 结束 private static byte END = 0X00; private String targetHost; private int targetPort; public Sock4Socket(String proxyHost, int proxyPort, String targetHost, int targetPort) throws UnknownHostException, IOException { super(proxyHost, proxyPort); this.targetHost = targetHost; this.targetPort = targetPort; this.connect(); } /** * @param host * @param port * @return * @throws UnknownHostException */ private byte[] connByte(String host, int port) throws UnknownHostException { String[] subIP = host.split("\\."); String portStr = Integer.toHexString(port); byte subP1B = 0; byte subP2B = 0; if (portStr.length() <= 2) { subP2B = (byte) Byte.valueOf(portStr, 16); } else if (portStr.length() == 3) { String p1 = portStr.charAt(0) ""; subP1B = (byte) Byte.valueOf(p1, 16); String p2 = portStr.charAt(1) "" portStr.charAt(2); subP2B = (byte) Byte.valueOf(p2, 16); } else if (portStr.length() == 4) { String p1 = portStr.charAt(0) "" portStr.charAt(1); subP1B = (byte) Byte.valueOf(p1, 16); String p2 = portStr.charAt(2) "" portStr.charAt(3); subP2B = (byte) Byte.valueOf(p2, 16); } byte[] bt = new byte[9]; bt[0] = VERSION4; bt[1] = CONNECT_REQUEST; bt[2] = subP1B; bt[3] = subP2B; bt[4] = (byte) Integer.parseInt(subIP[0]); bt[5] = (byte) Integer.parseInt(subIP[1]); bt[6] = (byte) Integer.parseInt(subIP[2]); bt[7] = (byte) Integer.parseInt(subIP[3]); bt[8] = END; return bt; } /** * 连接 */ private void connect() throws IOException { byte[] data = connByte(this.targetHost, this.targetPort); OutputStream os = this.getOutputStream(); // 握手字节序列 os.write(data); os.flush(); // 服务端返回的字节 version,command,ip,port,message byte[] receive = new byte[8]; InputStream is = this.getInputStream(); is.read(receive); byte b = receive[1]; if (b == 0) { throw new IOException(""); } else if (b == 92) { throw new IOException("server time out"); } else if (b == 90) { // success } } }

测试案例

import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; public class Sock4SocketClientDemo { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { // Socket4代理服务地址 String proxyHost = "127.0.0.1"; int proxyPort = 1080; // 访问的地址 String targetHost = "124.239.226.238"; int targetPort = 80; // 创建Socket4代理Socket Sock4Socket sock4Socket = new Sock4Socket(proxyHost, proxyPort, targetHost, targetPort); OutputStream outputStream = sock4Socket.getOutputStream(); InputStream inputStream = sock4Socket.getInputStream(); InputStreamReader isr = new InputStreamReader(inputStream, "GBK"); BufferedReader br = new BufferedReader(isr); // 请求内容 StringBuilder request = new StringBuilder(); request.append("GET / HTTP/1.1\r\n"); request.append("Accept-Language: zh-cn\r\n"); request.append("Host: www.toutiao.com\r\n"); request.append("\r\n"); outputStream.write(request.toString().getBytes()); outputStream.flush(); // 响应内容 StringBuilder sb = new StringBuilder(); String str = null; while ((str = br.readLine()) != null) { sb.append(str "\n"); } System.out.println(sb.toString()); br.close(); isr.close(); outputStream.close(); } }

,