Home >Java >javaTutorial >How to use Java simulation to achieve intranet penetration into the black box?

How to use Java simulation to achieve intranet penetration into the black box?

PHPz
PHPzforward
2023-05-08 23:28:241476browse

1. Introduction to Intranet Penetration

Understanding from the perspective of a black box: Usually, whether a personal computer is connected to WIFI to access the Internet or uses a network cable to access the Internet, it belongs to the inside of the LAN. The Internet cannot directly access your computer. Intranet penetration can allow computers in your LAN to access the external network. Give an example: If you run a Web service locally and the occupied port is 8080, then your local test is: //localhost:8080. But what if you want to share your services with a good friend? Yes, it is through intranet penetration. In fact, intranet penetration is a very complicated operation. The explanation on Baidu Encyclopedia is:

Intranet penetration, that is, NAT penetration. NAT penetration is performed to enable certain A data packet with a specific source IP address and source port number is not blocked by the NAT device and is correctly routed to the intranet host.

I obviously can’t do it here. All I need is the service to access the intranet from the external network. As for the specific process, I don't care, I just need to achieve this goal.

2. Specific ideas and implementation details

2.1 Specific ideas

No matter which method is used to achieve intranet penetration, a public IP address is required. Here I am An Alibaba Cloud server is used. The following is a schematic diagram of the entire simulation:

How to use Java simulation to achieve intranet penetration into the black box?

Note:

1. The intranet penetration server is deployed on a machine with a public IP.

2. Intranet services and intranet penetration clients are deployed on intranet machines.

Explanation:

My idea is very simple, that is, the user accesses the intranet penetration server, and then the intranet penetration server sends the user's request message Forward to intranet penetration client , and then the intranet penetration client forwards the request message to intranet service , and then receives the of the intranet service The response message is forwarded to the intranet penetration server, and finally the intranet penetration server forwards it to the user. The general process is like this. For external users, it will only think that they have accessed an external network service, because the user is facing a black box system.

2.2 Implementation details

In order to achieve the above goal, the most critical thing is to maintain a long connection between the intranet penetration client and the intranet penetration server, I need to use this long connection to exchange message information from both parties. Therefore, this long connection needs to be established after the system is started. When a user request comes in, the intranet penetration server first receives the request, and then uses the long connection to transfer it to the intranet penetration client. The network penetration client uses this message as a request to access the intranet service, then receives the response from the intranet service, forwards it to the intranet penetration server, and finally forwards it to the user.

3. Code implementation

3.1 Directory structure

How to use Java simulation to achieve intranet penetration into the black box?

Description: This is the server and client code for intranet penetration. I put them together instead of writing them separately, because both sides need to use some common classes. However, it is recommended to separate it into two projects because they need to be deployed separately.

Or when exporting into a jar package, just select different main classes.

Client code files: Client.java, Connection.java, Msg.java, ProxyConnection.java.

Server code files: Server.java, Connection.java, Msg.java, ProxyConnection.java.

3.2 Client class

package org.dragon;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
/**
 * 用于双向通信的客户端
 * */
public class Client {
	private static final String REMOTE_HOST = "公网IP";
	private static final String LOCAL_HOST = "127.0.0.1";
	public static void main(String[] args) {
		try {
			Socket proxy = new Socket(REMOTE_HOST, 10000);       
			System.out.println("Connect Server Successfully!");
			ProxyConnection proxyConnection = new ProxyConnection(proxy);  // 维持和内网穿透服务端的长连接
			// 可以实现同一个人多次访问
			while (true) {
				Msg msg = proxyConnection.receiveMsg();
				Connection connection = new Connection(new Socket(LOCAL_HOST, 8080));
				connection.sendMsg(msg);    // 将请求报文发送给内网服务器,即模拟发送请求报文
				msg = connection.receiveMsg();  // 接收内网服务器的响应报文
				proxyConnection.sendMsg(msg);  // 将内网服务器的响应报文转发给公网服务器(内网穿透服务端)
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

3.3 Connection class

package org.dragon;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
 * 维持用户和服务器的连接
 * */
public class Connection {
	private InputStream input;
	private OutputStream output;
	public Connection(Socket client) throws IOException {
		this.input = new BufferedInputStream(client.getInputStream());
		this.output = new BufferedOutputStream(client.getOutputStream());
	}
	public Msg receiveMsg() throws IOException {
		byte[] msg = new byte[2*1024];
		int len = input.read(msg);
		return new Msg(len, msg);
	}
	public void sendMsg(Msg msg) throws IOException {
		output.write(msg.getMsg(), 0, msg.getLen());
		output.flush();  // 每一次写入都要刷新,防止阻塞。
	}
}

3.4 Msg class

package org.dragon;
public class Msg {
	private int len;
	private byte[] msg;
	public Msg(int len, byte[] msg) {
		this.len = len;
		this.msg = msg;
	}
	public int getLen() {
		return len;
	}
	public byte[] getMsg() {
		return msg;
	}
	@Override
	public String toString() {
		return "msg: " + len + " --> " + new String(msg, 0, len);
	}
}

3.5 ProxyConnection class

package org.dragon;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
/**
 * @author Alfred
 * 
 * 代理服务器和代理客户端是用于维持两者之间通信的一个长连接Socket,
 * 主要的目的是因为双方之间的通信方式是全双工的,它们的作用是为了传递报文。
 * */
public class ProxyConnection {
	private Socket proxySocket;
	private DataInputStream input;
	private DataOutputStream output;
	public ProxyConnection(final Socket socket) throws UnknownHostException, IOException {
		proxySocket = socket;
		input = new DataInputStream(new BufferedInputStream(proxySocket.getInputStream()));
		output = new DataOutputStream(new BufferedOutputStream(proxySocket.getOutputStream()));
	}
	/**
	 * 接收报文
	 * @throws IOException 
	 * */
	public Msg receiveMsg() throws IOException {
		int len = input.readInt();
		if (len <= 0) {
			throw new IOException("异常接收数据,长度为:" + len);
		}
		byte[] msg = new byte[len];
		int size = input.read(msg);  // 这里到底会不会读取到这么多,我也有点迷惑!
		return new Msg(size, msg);   // 为了防止出错,还是使用一个记录实际读取值size
	}
	/**
	 * 转发报文
	 * @throws IOException 
	 * */
	public void sendMsg(Msg msg) throws IOException {
		output.writeInt(msg.getLen());
		output.write(msg.getMsg(), 0, msg.getLen());
		output.flush();  // 每一次写入都需要手动刷新,防止阻塞。
	}
}

3.6 Server class

package org.dragon;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * 用于双向通信的服务器
 * */
public class Server {
	public static void main(String[] args) {
		try (ServerSocket server = new ServerSocket(10000)) {
			// 用于交换控制信息的Socket
			Socket proxy = server.accept();
			ProxyConnection proxySocket = new ProxyConnection(proxy);
			// 用于正常通讯的socket
			while (true) {
				Socket client = server.accept();
				Connection connection = new Connection(client);
				Msg msg = connection.receiveMsg();  // 接收用户的请求报文
				proxySocket.sendMsg(msg);           // 转发用户的请求报文给内网服务器
				msg = proxySocket.receiveMsg();     // 接收内网服务器的响应报文
				connection.sendMsg(msg);            // 转发内网服务器的响应报文给用户
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

4. Intranet service

The intranet service is a web service. Here I am using a simple SpringBoot project, which has only three request methods.

package org.dragon.controller;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Controller {
	@GetMapping("/loveEN")
	public String testEN() {
		return "I love you yesterday and today!";
	}
	@GetMapping("/loveZH") 
	public String loveZH() {
		return "有一美人兮,见之不忘。一日不见兮,思之如狂。凤飞翱翔兮,四海求凰。无奈佳人兮,不在东墙。";
	}
	@GetMapping("/loveJson")
	public Map<String, String> loveJson() {
		HashMap<String, String> map = new LinkedHashMap<>();
		map.put("english", "I love you yesterday and today!");
		map.put("chinese", "有一美人兮,见之不忘。一日不见兮,思之如狂。"
				+ "凤飞翱翔兮,四海求凰。无奈佳人兮,不在东墙。");
		return map;
	}
}

5. Test

5.1 Intranet test

Start the intranet service and enter the following three URLs in the browser to test. The function is normal.

How to use Java simulation to achieve intranet penetration into the black box?How to use Java simulation to achieve intranet penetration into the black box?

How to use Java simulation to achieve intranet penetration into the black box?

5.2 External network test

Start the intranet penetration server and the intranet penetration client successively, and then access the three URLs in the browser. Note: 1. If you test it yourself, you can switch to the IP address of the intranet penetration server you are running or use a domain name. 2. The external network machine and the internal network machine here use different ports (use them casually, as long as it does not conflict with the service port on your own machine). In fact, you can use port 80 on the external network, which is more friendly to ordinary users. . 3. The third test actually failed. You can see that the loading animation above keeps loading. It stands to reason that this should stop soon, but it seems impossible to stop. This is a system bug, but due to the limited knowledge I have, I won’t solve it.

How to use Java simulation to achieve intranet penetration into the black box?

How to use Java simulation to achieve intranet penetration into the black box?

How to use Java simulation to achieve intranet penetration into the black box?

6. Notes

The code here is A simulation, it can only simulate this function, but basically has no actual effect, haha. Because I only have one long connection here, I can only support serial communication. It is best to simply call it by one person. It seems that the calling speed cannot be too fast. I thought of a way to maintain a connection pool between the client and the server, so that multi-threaded access can be achieved. There is no handling of TCP packet sticking and sub-packaging here (I understand this concept, but I am not very good at handling it), so I default to request and response messages being within 2KB in size. Exceeding this length will cause problems. Although this parameter can be increased, if most packets are very small, it will also lead to low efficiency. This intranet penetration can support various protocols above TCP, not necessarily HTTP, at least in theory it is possible.

The above is the detailed content of How to use Java simulation to achieve intranet penetration into the black box?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete