Java实现tcp内网穿透,将内网映射到外网访问
本文连接:https://www.cnblogs.com/muphy/p/15292965.html
gitee: https://gitee.com/muphy1112/ruphy-frp/
原理如下
为什么需要客户端和服务端?
服务端先启动,然后启动客户端,
ProxyServer服务端被动等待ProxyClient内网客户端和外网应用的连接
ProxyClient客户端主动连接ProxyServer服务端和内网应用的连接,ProxyClient可以代理内网任意主机的TCP应用
使用方法
使用Javac编译:
javac ProxyServer.java -encoding UTF-8 javac ProxyClient.java -encoding UTF-8
编译后分别启动ProxyServer和ProxyClient,此代码长连接只支持一对一
java ProxyServer 48981 48982 usage: java ProxyServer [内网:6010] [外网:6011] 内网端口:48981,外网端口:48982
java ProxyClient 47.*.*.* 48981 localhost 8080 usage: java ProxyClient [外网:localhost 6011] [内网:localhost 8080] 应用:192.168.2.15:8080,外网:47.*.*.*:48981
源码:ProxyServer.java
import java.io.*; import java.math.BigInteger; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.Executors; import java.util.regex.Pattern; public class ProxyServer extends Thread { private final ServerSocket intranetServer; private final ServerSocket extranetServer; private static InputStream intranetInputStream = null; //服务端输入流 private static OutputStream intranetOutputStream = null; //服务端输出流 //使用线程处理收到的请求 private volatile InputStream extranetInputStream = null; private volatile OutputStream extranetOutputStream = null; private volatile Socket extranetClient = null; private volatile Socket intranetClient = null; public ProxyServer(int intranetPort, int extranetPort) throws IOException { intranetServer = new ServerSocket(intranetPort); extranetServer = new ServerSocket(extranetPort); System.out.println("内网端口:" + intranetPort + ",外网端口:" + extranetPort); } public static void main(String[] args) throws IOException { System.out.println("usage: java ProxyServer [内网:6010] [外网:6011]"); int intranetPort = 6011; int extranetPort = 6010; if (args.length > 0) { intranetPort = Integer.parseInt(args[0]); } if (args.length > 1) { extranetPort = Integer.parseInt(args[1]); } new ProxyServer(intranetPort, extranetPort).start(); } @Override public void run() { // 线程运行函数 if (!getIntranetClient()) { System.out.println("等待内网服务连接失败"); return; } Executors.newFixedThreadPool(1).execute(() -> { while (true) { if (intranetClient == null || intranetClient.isClosed()) { if (!getIntranetClient()) { System.out.println("等待内网服务连接失败"); break; } } byte[] buf = new byte[1024]; //try { while (true) { int len = 0; try { len = intranetInputStream.read(buf, 0, buf.length); } catch (IOException e) { e.printStackTrace(); close(intranetInputStream, intranetOutputStream, intranetClient); intranetClient = null; break; } if (len < 0) { close(intranetInputStream, intranetOutputStream, intranetClient); intranetClient = null; break; } String suitableString = getSuitableString(buf, len); System.out.println("内网:" + suitableString); if (extranetClient == null || extranetClient.isClosed()) { continue; } if ("close".equals(suitableString)) { close(extranetInputStream, extranetOutputStream, extranetClient); extranetClient = null; continue; } boolean close = suitableString.endsWith("close"); if (close) { try { extranetOutputStream.write(buf, 0, len - 5); extranetOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } finally { close(extranetInputStream, extranetOutputStream, extranetClient); extranetClient = null; continue; } } try { extranetOutputStream.write(buf, 0, len); extranetOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); close(extranetInputStream, extranetOutputStream, extranetClient); byte[] bytes = "close".getBytes(); try { intranetOutputStream.write(bytes, 0, bytes.length); intranetOutputStream.flush(); } catch (IOException ex) { ex.printStackTrace(); close(intranetInputStream, intranetOutputStream, intranetClient); break; } } } } }); while (true) { byte[] buf = new byte[1024]; try { extranetClient = extranetServer.accept(); System.out.println("外网连接:" + extranetClient.getRemoteSocketAddress()); //使用线程处理收到的请求 extranetInputStream = extranetClient.getInputStream(); //客户端输入流 extranetOutputStream = extranetClient.getOutputStream(); //客户端输出流 int len; while ((len = extranetInputStream.read(buf, 0, buf.length)) > -1) { System.out.println("外网:" + getSuitableString(buf, len)); intranetOutputStream.write(buf, 0, len); intranetOutputStream.flush(); } } catch (Exception e) { e.printStackTrace(); } close(extranetClient, extranetInputStream, extranetOutputStream); byte[] bytes = "close".getBytes(); try { intranetOutputStream.write(bytes, 0, bytes.length); intranetOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } } } private synchronized boolean getIntranetClient() { if (intranetClient != null && !intranetClient.isClosed()) { return false; } try { intranetClient = intranetServer.accept(); System.out.println("内网连接:" + intranetClient.getRemoteSocketAddress()); intranetInputStream = intranetClient.getInputStream(); intranetOutputStream = intranetClient.getOutputStream(); return true; } catch (IOException e) { e.printStackTrace(); close(intranetInputStream, intranetOutputStream, intranetClient); } return false; } public static String getSuitableString(byte[] bytes, int len) { if (bytes == null || bytes.length == 0) { return ""; } byte[] buffer = new byte[len]; System.arraycopy(bytes, 0, buffer, 0, len); String suitableParseString = new String(buffer);return suitableParseString; } /** * 关闭所有流 */ private static void close(Closeable... closeables) { if (closeables != null) { for (int i = 0; i < closeables.length; i++) { if (closeables[i] != null) { try { closeables[i].close(); } catch (IOException e) { e.printStackTrace(); } } } } } }
源码:ProxyClient.java
import java.io.*; import java.math.BigInteger; import java.net.InetSocketAddress; import java.net.Socket; import java.util.concurrent.Executors; import java.util.regex.Pattern; public class ProxyClient extends Thread { private Socket server = null; private final String serverIp; private final int serverPort; private Socket app = null; private static InputStream serverInputStream = null; //服务端输入流 private static OutputStream serverOutputStream = null; //服务端输出流 private static InputStream appInputStream = null; //服务端输入流 private static OutputStream appOutputStream = null; //服务端输出流 private final String appIp; private final int appPort; public ProxyClient(String serverIp, int serverPort, String appIp, int appPort) throws IOException { this.appIp = appIp; this.appPort = appPort; this.serverIp = serverIp; this.serverPort = serverPort; System.out.println("应用:" + appIp + ":" + appPort + ",外网:" + serverIp + ":" + serverPort); } public static void main(String[] args) throws IOException { System.out.println("usage: java ProxyClient [外网:localhost 6010] [内网:localhost 8080]"); String serverIp = "47.*.*.*"; int serverPort = 6011; String appIp = "192.168.2.100"; int appPort = 8080; if (args.length > 0) { serverIp = args[0]; } if (args.length > 1) { serverPort = Integer.parseInt(args[1]); } if (args.length > 2) { appIp = args[2]; } if (args.length > 3) { appPort = Integer.parseInt(args[3]); } new ProxyClient(serverIp, serverPort, appIp, appPort).start(); } @Override public void run() { // 线程运行函数 if (!getServer()) { System.out.println("连接服务器失败!"); return; } Executors.newFixedThreadPool(1).execute(() -> { while (true) { if (server == null || server.isClosed()) { if (!getServer()) { System.out.println("连接服务器失败!"); return; } } byte[] buf = new byte[1024]; int len; while (true) { try { len = serverInputStream.read(buf, 0, buf.length); } catch (IOException e) { e.printStackTrace(); close(serverInputStream, serverOutputStream, server); server = null; break; } if (len < 0) { close(serverInputStream, serverOutputStream, server); server = null; break; } String suitableString = getSuitableString(buf, len); System.out.println("外网:" + suitableString); if ("close".equals(suitableString)) { close(appInputStream, appOutputStream, app); app = null; continue; } if (app == null || app.isClosed()) { if (!getApp()) { System.out.println("连接内网应用失败!"); } } boolean close = suitableString.endsWith("close"); if (close) { try { appOutputStream.write(buf, 0, len - 5); appOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } close(appInputStream, appOutputStream, app); app = null; continue; } try { appOutputStream.write(buf, 0, len); appOutputStream.flush(); } catch (Exception e) { e.printStackTrace(); close(appInputStream, appOutputStream, app); app = null; byte[] bytes = "close".getBytes(); try { serverOutputStream.write(bytes, 0, bytes.length); serverOutputStream.flush(); } catch (IOException ex) { ex.printStackTrace(); close(serverInputStream, serverOutputStream, server); break; } } } } }); } private boolean getServer() { try { server = new Socket(); server.connect(new InetSocketAddress(serverIp, serverPort), 2000); System.out.println("外网服务器连接成功:" + serverIp + ":" + serverPort); serverInputStream = server.getInputStream(); serverOutputStream = server.getOutputStream(); return true; } catch (IOException e) { e.printStackTrace(); } close(serverInputStream, serverOutputStream, server); System.exit(0); return false; } private boolean getApp() { app = new Socket(); try { app.connect(new InetSocketAddress(this.appIp, this.appPort), 2000); appInputStream = new DataInputStream(app.getInputStream()); appOutputStream = new DataOutputStream(app.getOutputStream()); System.out.println("外网服务器连接成功:" + this.appIp + ":" + this.appPort); } catch (IOException e) { app = null; e.printStackTrace(); close(appInputStream, appOutputStream, app); byte[] bytes = "close".getBytes(); try { serverOutputStream.write(bytes, 0, bytes.length); serverOutputStream.flush(); } catch (IOException ex) { ex.printStackTrace(); close(serverInputStream, serverOutputStream, server); server = null; } return false; } Executors.newFixedThreadPool(1).execute(() -> { int len; byte[] buf = new byte[1024]; try { while ((len = appInputStream.read(buf, 0, buf.length)) > -1) { System.out.println("应用:" + getSuitableString(buf, len)); serverOutputStream.write(buf, 0, len); serverOutputStream.flush(); } } catch (Exception e) { e.printStackTrace(); } finally { close(appInputStream, appOutputStream, app); byte[] bytes = "close".getBytes(); try { serverOutputStream.write(bytes, 0, bytes.length); serverOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); close(serverInputStream, serverOutputStream, server); server = null; } } }); return true; } public static String getSuitableString(byte[] bytes) { return getSuitableString(bytes, bytes.length); } public static String getSuitableString(byte[] bytes, int len) { if (bytes == null || bytes.length == 0) { return ""; } byte[] buffer = new byte[len]; System.arraycopy(bytes, 0, buffer, 0, len); String suitableParseString = new String(buffer);return suitableParseString; }/** * 关闭所有流 */ private static void close(Closeable... closeables) { if (closeables != null) { for (int i = 0; i < closeables.length; i++) { if (closeables[i] != null) { try { closeables[i].close(); } catch (IOException e) { e.printStackTrace(); } } } } } }