Java实现tcp内网穿透,将内网映射到外网访问


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();
                    }
                }
            }
        }
    }
}

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM