Commit 91a7693d authored by Administrator's avatar Administrator

远程命令支持

parent 99318efd
package com.virjar.echo.nat.client;
import com.virjar.echo.nat.cmd.CmdHandler;
import com.virjar.echo.nat.log.EchoLogger;
import com.virjar.echo.nat.protocol.EchoPacket;
import com.virjar.echo.nat.protocol.EchoPacketDecoder;
......@@ -7,6 +8,7 @@ import com.virjar.echo.nat.protocol.EchoPacketEncoder;
import com.virjar.echo.nat.protocol.PacketCommon;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
......@@ -33,14 +35,26 @@ public class EchoClient {
private String clientId;
private String adminAccount;
private Map<String, CmdHandler> cmdHandlerMap = new HashMap<>();
public EchoClient(String natServerHost, int natServerPort, String clientId) {
this.natServerHost = natServerHost;
this.natServerPort = natServerPort;
this.clientId = clientId;
}
public void setAdminAccount(String adminAccount) {
public EchoClient setAdminAccount(String adminAccount) {
this.adminAccount = adminAccount;
return this;
}
public EchoClient registerCmdHandler(CmdHandler cmdHandler) {
cmdHandlerMap.put(cmdHandler.action().toUpperCase(), cmdHandler);
return this;
}
public CmdHandler queryCmdHandler(String action) {
return cmdHandlerMap.get(action.toUpperCase());
}
private Bootstrap echoClientBootstrap;
......
package com.virjar.echo.nat.client;
import com.virjar.echo.nat.cmd.CmdHandler;
import com.virjar.echo.nat.cmd.CmdResponse;
import com.virjar.echo.nat.log.EchoLogger;
import com.virjar.echo.nat.protocol.EchoPacket;
import com.virjar.echo.nat.protocol.PacketCommon;
import io.netty.channel.*;
import java.util.concurrent.TimeUnit;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
public class EchoClientChannelHandler extends SimpleChannelInboundHandler<EchoPacket> {
private EchoClient echoClient;
......@@ -32,7 +38,9 @@ public class EchoClientChannelHandler extends SimpleChannelInboundHandler<EchoPa
case PacketCommon.TYPE_DISCONNECT:
handleDisconnectMessage(msg);
break;
case PacketCommon.C_TYPE_CONTROL:
handleControlMessage(ctx, msg);
break;
default:
EchoLogger.getLogger().warn("Unknown message type:" + msg.getType());
break;
......@@ -40,6 +48,29 @@ public class EchoClientChannelHandler extends SimpleChannelInboundHandler<EchoPa
}
private void handleControlMessage(ChannelHandlerContext ctx, EchoPacket msg) {
long seq = msg.getSerialNumber();
String action = msg.getExtra();
String cmdParam = "";
byte[] data = msg.getData();
if (data != null) {
cmdParam = new String(data);
}
CmdResponse cmdResponse = new CmdResponse(seq, ctx.channel());
CmdHandler cmdHandler = echoClient.queryCmdHandler(action);
if (cmdHandler == null) {
cmdResponse.failed("NO_ACTION_" + action);
return;
}
try {
cmdHandler.handle(cmdParam, cmdResponse);
} catch (Exception e) {
EchoLogger.getLogger().error("failed to call cmdHandler: " + action
+ " param->" + cmdParam, e);
cmdResponse.failed("error action:" + action + " param:" + cmdParam + " e:" + e.getMessage());
}
}
private void handleDisconnectMessage(EchoPacket msg) {
// 关闭真实服务器的链接,比如baidu.com:443
echoClient.closeRealServerConnection(msg.getSerialNumber());
......
package com.virjar.echo.nat.cmd;
public interface CmdHandler {
String action();
void handle(String param, CmdResponse cmdResponse);
}
package com.virjar.echo.nat.cmd;
import com.virjar.echo.nat.protocol.EchoPacket;
import com.virjar.echo.nat.protocol.PacketCommon;
import java.nio.charset.StandardCharsets;
import io.netty.channel.Channel;
public class CmdResponse {
private long req;
private Channel natChannel;
private boolean respond = false;
public CmdResponse(long req, Channel natChannel) {
this.req = req;
this.natChannel = natChannel;
}
public static final String STATUS_OK = "OK";
public static final String STATUS_FAILED = "FAILED";
public void success(String response) {
ack(STATUS_OK, response);
}
public void failed(String errorMessage) {
ack(STATUS_FAILED, errorMessage);
}
public synchronized void ack(String status, String response) {
if (respond) {
return;
}
respond = true;
EchoPacket ackMessage = new EchoPacket();
ackMessage.setSerialNumber(req);
ackMessage.setType(PacketCommon.C_TYPE_CONTROL);
String totalResponse = status;
if (response != null) {
totalResponse = totalResponse + ":" + response;
}
ackMessage.setData(totalResponse.getBytes(StandardCharsets.UTF_8));
natChannel.writeAndFlush(ackMessage);
}
}
package com.virjar.echo.nat.cmd;
import com.virjar.echo.nat.log.EchoLogger;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ShellCmdHandler implements CmdHandler {
@Override
public String action() {
return "shell";
}
@Override
public void handle(String param, CmdResponse cmdResponse) {
new Thread("") {
@Override
public void run() {
try {
EchoLogger.getLogger().info("execute shell:" + param);
Process process = Runtime.getRuntime().exec(param);
StringBuffer out = new StringBuffer();
StringBuffer error = new StringBuffer();
autoFillOutput(process.getInputStream(), out);
autoFillOutput(process.getErrorStream(), error);
process.waitFor();
cmdResponse.success(out + "\n\n" + error);
} catch (Exception e) {
e.printStackTrace();
EchoLogger.getLogger().error("error when execute cmd", e);
}
}
}.start();
}
private static void autoFillOutput(InputStream inputStream, StringBuffer stringBuffer) {
new Thread() {
@Override
public void run() {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line).append("\n");
}
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment