diff --git a/.gitignore b/.gitignore index 5ee4fa9c418d7e09912b108f8a16c7d2f6198df5..276b620a3209f773fce2ded2dcf51b01a2895e52 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .idea/* target/* */target/ -jforwarding.sqlite \ No newline at end of file +jforwarding.sqlite +*.iml \ No newline at end of file diff --git a/README.md b/README.md index 5afbae696d1f167bb44c9c6ea206b82aa8e70324..e12e76a4603c72592875335dff46e5efdff56307 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,9 @@ * 可转发本机或局域网内其它任何机器的TCP数据包 ### 设置 - +## 原理 +假设我们需要把一台局域网的80端口暴露出来,我们利用公网服务器的2222端口来转发,那么流程是这样的。 +![原理](https://gitee.com/uploads/images/2018/0513/223357_6e57ac16_1925495.png "屏幕截图.png") ## 快速开始 1. 按需修改两个模块下的配置文件,比如几个端口及主机端的服务器地址等。 2. 使用Maven打包,`mvn package`,将会在`target`目录下分别生成服务器端`original-commander-1.0-SNAPSHOT.jar`和主机端`messenger-1.0-SNAPSHOT.jar`。 diff --git a/commander/commander.iml b/commander/commander.iml deleted file mode 100644 index 343fa55018d89ef37587651e89eb14c723ccdbf6..0000000000000000000000000000000000000000 --- a/commander/commander.iml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/commander/src/main/java/cn/org/hentai/server/protocol/commander/CommandSession.java b/commander/src/main/java/cn/org/hentai/server/protocol/commander/CommandSession.java index d022afb23d96e4e10a176340c30603cfb0edffec..6c88e9600edd1ada22a143d72f6d385aa9ea41cd 100644 --- a/commander/src/main/java/cn/org/hentai/server/protocol/commander/CommandSession.java +++ b/commander/src/main/java/cn/org/hentai/server/protocol/commander/CommandSession.java @@ -13,6 +13,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.LinkedList; +import java.util.concurrent.LinkedBlockingQueue; /** * Created by Expect on 2018/1/25. @@ -24,7 +25,7 @@ public class CommandSession extends SocketSession Socket connection = null; long lastActiveTime = System.currentTimeMillis(); int testTimeout = 0; - LinkedList commands = new LinkedList(); // 待下发的指令 + LinkedBlockingQueue commands = new LinkedBlockingQueue(); // 待下发的指令 public CommandSession(Socket connection) { @@ -43,23 +44,39 @@ public class CommandSession extends SocketSession protected void converse() throws Exception { this.connection.setSoTimeout(testTimeout * 2); - InputStream inputStream = this.connection.getInputStream(); - OutputStream outputStream = this.connection.getOutputStream(); + final InputStream inputStream = this.connection.getInputStream(); + final OutputStream outputStream = this.connection.getOutputStream(); // 先读取一个包,确定一下主机端的身份 host = authenticate(inputStream, outputStream); HostConnectionManager.getInstance().register(host.getId(), this); Log.debug("主机: " + host.getName() + "己连接..."); - + // 保证连接的可用性 + new Thread(new Runnable(){ + + @Override + public void run() { + while (!timedout()) + { + try { + heartBeat(inputStream, outputStream); + + } catch (Exception e) { + e.printStackTrace(); + } + try { + Thread.sleep(testTimeout/3); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + } + }).start(); while (!timedout()) { - // 测试连接的可用性 - testConnection(inputStream, outputStream); - // 是否有需要下发的指令? sendCommand(inputStream, outputStream); - - Thread.sleep(10); } } @@ -77,9 +94,7 @@ public class CommandSession extends SocketSession */ private void sendCommand(InputStream inputStream, OutputStream outputStream) throws Exception { - if (commands.size() == 0) return; - Command cmd = commands.removeFirst(); - if (null == cmd) return; + Command cmd = commands.take(); byte[] packet = Packet.create(host.getId(), Packet.ENCRYPT_TYPE_DES, cmd.getCode(), cmd.getBytes(), host.getAccesstoken()); outputStream.write(packet); outputStream.flush(); @@ -92,9 +107,8 @@ public class CommandSession extends SocketSession * @param inputStream * @param outputStream */ - private void testConnection(InputStream inputStream, OutputStream outputStream) throws Exception + private void heartBeat(InputStream inputStream, OutputStream outputStream) throws Exception { - if (System.currentTimeMillis() - lastActiveTime < testTimeout) return; byte[] data = NonceStr.generate(32).getBytes(); byte[] packet = Packet.create(host.getId(), Packet.ENCRYPT_TYPE_DES, Command.CODE_TEST, data, host.getAccesstoken()); outputStream.write(packet); @@ -133,6 +147,10 @@ public class CommandSession extends SocketSession public synchronized void requestForward(int seqId, String nonce, Port port) { - commands.add(new StartForwardCommand(seqId, port.getHostIp(), port.getHostPort(), nonce)); + try { + commands.put(new StartForwardCommand(seqId, port.getHostIp(), port.getHostPort(), nonce)); + } catch (InterruptedException e) { + e.printStackTrace(); + } } } diff --git a/commander/src/main/java/cn/org/hentai/server/protocol/proxy/ProxySession.java b/commander/src/main/java/cn/org/hentai/server/protocol/proxy/ProxySession.java index 57ab125dca8059c53825f84364bffe17450b017d..efb54e3957a9b94489ae86b15863d8ebe84c97f0 100644 --- a/commander/src/main/java/cn/org/hentai/server/protocol/proxy/ProxySession.java +++ b/commander/src/main/java/cn/org/hentai/server/protocol/proxy/ProxySession.java @@ -19,6 +19,7 @@ import java.net.SocketTimeoutException; */ public class ProxySession extends SocketSession { + private Object obj = new Object(); private Port port; // 主机端ID private Socket clientConnection; // 客户端连接 private Socket hostConnection; // 被代理的主机端连接 @@ -40,6 +41,9 @@ public class ProxySession extends SocketSession public void attach(Socket hostConnection) { this.hostConnection = hostConnection; + synchronized (obj) { + obj.notify(); + } } @Override @@ -61,11 +65,9 @@ public class ProxySession extends SocketSession long stime = System.currentTimeMillis(); while (this.hostConnection == null) { - if (System.currentTimeMillis() - stime > connectTimeout) - { - throw new SocketTimeoutException("等待主机端连接超时"); + synchronized (obj) { + obj.wait(connectTimeout); } - sleep(10); } Log.debug("主机端己连接"); @@ -95,6 +97,10 @@ public class ProxySession extends SocketSession { // 主机端到客户端,需要解密后转发 decryptAndTransfer(hostIS, clientOS, hostBufLength); +// 如果不关闭 浏览器访问有更好的性能 +// ab -n 1 -c 1 http://127.0.0.1:2222/ 会触发超时 +// clientConnection.close(); +// return; } if (hostBufLength + clientBufLength == 0) Thread.sleep(1); } @@ -120,7 +126,8 @@ public class ProxySession extends SocketSession // to.write(buf, 0, len); } buf = null; - buf = DES.decrypt(baos.toByteArray(), this.nonce); +// buf = DES.decrypt(baos.toByteArray(), this.nonce); + buf = baos.toByteArray(); // to.write(ByteUtils.toBytes(buf.length)); to.write(buf); to.flush(); @@ -141,7 +148,8 @@ public class ProxySession extends SocketSession // to.write(buf, 0, len); } buf = null; - buf = DES.encrypt(baos.toByteArray(), this.nonce); +// buf = DES.encrypt(baos.toByteArray(), this.nonce); + buf = baos.toByteArray(); to.write((byte)0xfa); to.write((byte)0xfa); to.write((byte)0xfa); diff --git a/commander/src/main/resources/application.properties b/commander/src/main/resources/application.properties index 6a7c4ce63a5363e618e06f8305bc033008a5ddac..fa5d47b7b51441db57d9d3c7c2a43ff1b2b4d941 100644 --- a/commander/src/main/resources/application.properties +++ b/commander/src/main/resources/application.properties @@ -1,24 +1,24 @@ - + server.address=0.0.0.0 server.port=8888 -# ָ˿ +# 指令服务器监听端口 server.command.port = 12121 -# ת˿ +# 转发服务器监听端口 server.forward.port = 11221 -# ˵Ӳ԰ط룩 +# 服务器端的连接测试包重发间隔(毫秒) server.test-packet.timeout = 30000 -# û½ỰЧʱӣ +# 用户登陆会话有效时长(分钟) user.token.expire.minutes=1440 -# ûaccesstokenKEY +# 用户accesstoken加密KEY user.token.key=VJN42837P0QJHVEY29 -# 趨ftlļ· +# 设定ftl文件路径 spring.freemarker.template-loader-path=classpath:/templates -# 趨̬ļ·js,css +# 设定静态文件路径,js,css等 spring.mvc.static-path-pattern=/static/** # sqlite url diff --git a/messenger/messenger.iml b/messenger/messenger.iml deleted file mode 100644 index 73f608bd65fdb4cf601b3ac4115367ee0f071ffd..0000000000000000000000000000000000000000 --- a/messenger/messenger.iml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/messenger/src/main/java/cn/org/hentai/messenger/protocol/CommandListener.java b/messenger/src/main/java/cn/org/hentai/messenger/protocol/CommandListener.java index 88ee468fc552b72b1bda42a16dc4abf36f58e9ed..aaccb00208e4a1fbec5ebe8c0b46458ba14631cd 100644 --- a/messenger/src/main/java/cn/org/hentai/messenger/protocol/CommandListener.java +++ b/messenger/src/main/java/cn/org/hentai/messenger/protocol/CommandListener.java @@ -53,18 +53,17 @@ public class CommandListener implements Runnable byte[] resp, packet = Packet.create(hostId, Packet.ENCRYPT_TYPE_DES, cmd, accessToken); outputStream.write(packet); outputStream.flush(); - resp = Packet.read(inputStream, true); + Packet.read(inputStream, true); Log.debug("己连接到服务器端..."); lastExchangeTime = System.currentTimeMillis(); // 2. 等待服务器的心跳测试包或是指令包 while (true) { - resp = Packet.read(inputStream); + resp = Packet.read(inputStream,true); if (null == resp) { if (System.currentTimeMillis() - lastExchangeTime > iowaitTimeout) break; - Thread.sleep(100); continue; } diff --git a/messenger/src/main/java/cn/org/hentai/messenger/protocol/ForwardWorker.java b/messenger/src/main/java/cn/org/hentai/messenger/protocol/ForwardWorker.java index 28b851f3be76fc6105d8848a0ddc41389507ae55..d6b6f717d09e3a08a72e40fadac9157609dd5410 100644 --- a/messenger/src/main/java/cn/org/hentai/messenger/protocol/ForwardWorker.java +++ b/messenger/src/main/java/cn/org/hentai/messenger/protocol/ForwardWorker.java @@ -125,7 +125,8 @@ public class ForwardWorker extends Thread // to.write(buf, 0, len); } buf = null; - buf = DES.decrypt(baos.toByteArray(), this.nonce); +// buf = DES.decrypt(baos.toByteArray(), this.nonce); + buf = baos.toByteArray(); // to.write(ByteUtils.toBytes(buf.length)); to.write(buf); to.flush(); @@ -146,7 +147,8 @@ public class ForwardWorker extends Thread // to.write(buf, 0, len); } buf = null; - buf = DES.encrypt(baos.toByteArray(), this.nonce); +// buf = DES.encrypt(baos.toByteArray(), this.nonce); + buf = baos.toByteArray(); to.write((byte)0xfa); to.write((byte)0xfa); to.write((byte)0xfa);