🔨 记录 RDP 传输日志.

This commit is contained in:
lijiahangmax
2025-06-30 23:23:53 +08:00
parent 4468a429dd
commit fcec6579d7
11 changed files with 255 additions and 60 deletions

View File

@@ -43,7 +43,7 @@ import javax.annotation.PostConstruct;
public enum InputProtocolEnum {
/**
* 连接终端
* 请求连接
*/
CONNECT("co",
TerminalConnectHandler.class,
@@ -74,7 +74,17 @@ public enum InputProtocolEnum {
new String[]{"type", "width", "height"},
TerminalResizeRequest.class),
// ----------------------- SSH ----------------------
// ----------------------- guacd ----------------------
/**
* guacd 指令
*/
GUACD_INSTRUCTION("gi",
GuacdInstructionHandler.class,
new String[]{"type", "instruction"},
GuacdInstructionRequest.class),
// ----------------------- ssh ----------------------
/**
* SSH 输入
@@ -84,7 +94,7 @@ public enum InputProtocolEnum {
new String[]{"type", "command"},
SshInputRequest.class),
// ----------------------- SFTP ----------------------
// ----------------------- sftp ----------------------
/**
* SFTP 文件列表
@@ -182,15 +192,15 @@ public enum InputProtocolEnum {
new String[]{"type", "path"},
SftpBaseRequest.class),
// ----------------------- guacd ----------------------
// ----------------------- rdp ----------------------
/**
* guacd 指令
* RDP 文件系统事件
*/
GUACD_INSTRUCTION("gi",
GuacdInstructionHandler.class,
new String[]{"type", "instruction"},
GuacdInstructionRequest.class),
RDP_FILE_SYSTEM_EVENT("fse",
RdpFileSystemEventHandler.class,
new String[]{"type", "event"},
RdpFileSystemEventRequest.class),
;

View File

@@ -69,6 +69,13 @@ public enum OutputProtocolEnum {
*/
RESIZE("rs", "${type}|${width}|${height}"),
// ----------------------- guacd ----------------------
/**
* guacd 指令
*/
GUACD_INSTRUCTION("gi", "${type}|${instruction}"),
// ----------------------- ssh ----------------------
/**
@@ -143,13 +150,6 @@ public enum OutputProtocolEnum {
*/
SFTP_SET_CONTENT("sc", "${type}|${result}|${msg}|${token}"),
// ----------------------- guacd ----------------------
/**
* guacd 指令
*/
GUACD_INSTRUCTION("gi", "${type}|${instruction}"),
;
private final String type;

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2023 - present Dromara, All rights reserved.
*
* https://visor.dromara.org
* https://visor.dromara.org.cn
* https://visor.orionsec.cn
*
* Members:
* Jiahang Li - ljh1553488six@139.com - author
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.visor.module.terminal.handler.terminal.handler;
import cn.orionsec.kit.lang.utils.collect.Maps;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import org.dromara.visor.module.terminal.define.operator.TerminalOperatorType;
import org.dromara.visor.module.terminal.handler.terminal.model.TerminalChannelProps;
import org.dromara.visor.module.terminal.handler.terminal.model.request.RdpFileSystemEventRequest;
import org.dromara.visor.module.terminal.handler.terminal.model.transport.RdpFileSystemEvent;
import org.dromara.visor.module.terminal.handler.terminal.sender.IGuacdTerminalSender;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* rdp 文件系统事件 处理器
*
* @author Jiahang Li
* @version 1.0.0
* @since 2024/2/19 11:13
*/
@Slf4j
@Component
public class RdpFileSystemEventHandler extends AbstractTerminalHandler<IGuacdTerminalSender, RdpFileSystemEventRequest> {
@Override
public void handle(TerminalChannelProps props, IGuacdTerminalSender sender, RdpFileSystemEventRequest payload) {
long startTime = System.currentTimeMillis();
String sessionId = props.getId();
// 获取会话
RdpFileSystemEvent fsEvent = JSON.parseObject(payload.getEvent(), RdpFileSystemEvent.class);
String event = fsEvent.getEvent();
String path = fsEvent.getPath();
log.info("RdpFileSystemEventHandler-handle start sessionId: {}, event: {}, path: {}", sessionId, event, path);
String operatorType;
if (TerminalOperatorType.RDP_UPLOAD.equals(event)) {
// 上传文件
operatorType = TerminalOperatorType.RDP_UPLOAD;
} else if (TerminalOperatorType.RDP_DOWNLOAD.equals(event)) {
// 下载文件
operatorType = TerminalOperatorType.RDP_DOWNLOAD;
} else {
return;
}
// 保存操作日志
Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.PATH, path);
this.saveOperatorLog(props, extra, operatorType, startTime, null);
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2023 - present Dromara, All rights reserved.
*
* https://visor.dromara.org
* https://visor.dromara.org.cn
* https://visor.orionsec.cn
*
* Members:
* Jiahang Li - ljh1553488six@139.com - author
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.visor.module.terminal.handler.terminal.model.request;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.dromara.visor.module.terminal.handler.terminal.model.TerminalBasePayload;
/**
* rdp 文件系统事件请求
*
* @author Jiahang Li
* @version 1.0.0
* @since 2024/2/6 13:31
*/
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class RdpFileSystemEventRequest extends TerminalBasePayload {
/**
* 事件
*/
private String event;
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2023 - present Dromara, All rights reserved.
*
* https://visor.dromara.org
* https://visor.dromara.org.cn
* https://visor.orionsec.cn
*
* Members:
* Jiahang Li - ljh1553488six@139.com - author
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.visor.module.terminal.handler.terminal.model.transport;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* RDP 文件系统事件
*
* @author Jiahang Li
* @version 1.0.0
* @since 2025/6/30 22:33
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RdpFileSystemEvent {
/**
* 事件
*/
private String event;
/**
* 文件路径
*/
private String path;
}

View File

@@ -23,6 +23,7 @@
package org.dromara.visor.module.terminal.handler.transfer.session;
import cn.orionsec.kit.lang.exception.argument.InvalidArgumentException;
import cn.orionsec.kit.lang.utils.collect.Maps;
import cn.orionsec.kit.lang.utils.io.Streams;
import cn.orionsec.kit.net.host.SessionStore;
import cn.orionsec.kit.net.host.sftp.SftpExecutor;
@@ -33,14 +34,18 @@ import org.dromara.visor.common.constant.Const;
import org.dromara.visor.common.constant.FieldConst;
import org.dromara.visor.common.session.config.SshConnectConfig;
import org.dromara.visor.framework.biz.operator.log.core.model.OperatorLogModel;
import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import org.dromara.visor.framework.websocket.core.utils.WebSockets;
import org.dromara.visor.module.terminal.handler.terminal.model.TerminalChannelProps;
import org.dromara.visor.module.terminal.handler.terminal.record.TerminalAsyncSaver;
import org.dromara.visor.module.terminal.handler.terminal.utils.TerminalUtils;
import org.dromara.visor.module.terminal.handler.transfer.enums.TransferReceiver;
import org.dromara.visor.module.terminal.handler.transfer.model.TransferOperatorRequest;
import org.dromara.visor.module.terminal.handler.transfer.utils.TransferUtils;
import org.springframework.web.socket.WebSocketSession;
import java.util.List;
import java.util.Map;
/**
* 主机传输会话实现
@@ -149,10 +154,19 @@ public abstract class TransferSession implements ITransferSession {
* @param paths paths
*/
protected void saveOperatorLog(Long logId, String type, List<String> paths) {
TerminalChannelProps props = WebSockets.getAttr(channel, FieldConst.PROPS);
String path = String.join(Const.LF, paths);
int count = paths.size();
// 获取操作日志
OperatorLogModel model = TransferUtils.getOperatorLogModel(type, path, count, connectConfig, WebSockets.getAttr(channel, FieldConst.PROPS));
Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.PATH, path);
extra.put(OperatorLogs.COUNT, count);
extra.put(OperatorLogs.HOST_ID, connectConfig.getHostId());
extra.put(OperatorLogs.HOST_NAME, connectConfig.getHostName());
extra.put(OperatorLogs.ADDRESS, connectConfig.getHostAddress());
OperatorLogModel model = TerminalUtils.getOperatorLogModel(props, extra, type, System.currentTimeMillis(), null);
// 保存操作日志
TerminalAsyncSaver.saveOperatorLog(model);
// 保存操作日志
TerminalAsyncSaver.saveOperatorLog(model);
}

View File

@@ -23,21 +23,14 @@
package org.dromara.visor.module.terminal.handler.transfer.utils;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.collect.Maps;
import com.alibaba.fastjson.JSON;
import org.apache.catalina.connector.ClientAbortException;
import org.dromara.visor.common.constant.ErrorMessage;
import org.dromara.visor.common.session.config.BaseConnectConfig;
import org.dromara.visor.framework.biz.operator.log.core.model.OperatorLogModel;
import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import org.dromara.visor.framework.websocket.core.utils.WebSockets;
import org.dromara.visor.module.terminal.handler.terminal.model.TerminalChannelProps;
import org.dromara.visor.module.terminal.handler.terminal.utils.TerminalUtils;
import org.dromara.visor.module.terminal.handler.transfer.enums.TransferReceiver;
import org.dromara.visor.module.terminal.handler.transfer.model.TransferOperatorResponse;
import org.springframework.web.socket.WebSocketSession;
import java.util.Map;
import java.util.function.Consumer;
/**
@@ -52,30 +45,6 @@ public class TransferUtils {
private TransferUtils() {
}
/**
* 获取传输操作日志
*
* @param type type
* @param path path
* @param count count
* @param config config
* @param props props
*/
public static OperatorLogModel getOperatorLogModel(String type,
String path, Integer count,
BaseConnectConfig config,
TerminalChannelProps props) {
// 设置参数
Map<String, Object> extra = Maps.newMap();
extra.put(OperatorLogs.PATH, path);
extra.put(OperatorLogs.COUNT, count);
extra.put(OperatorLogs.HOST_ID, config.getHostId());
extra.put(OperatorLogs.HOST_NAME, config.getHostName());
extra.put(OperatorLogs.ADDRESS, config.getHostAddress());
// 获取操作日志
return TerminalUtils.getOperatorLogModel(props, extra, type, System.currentTimeMillis(), null);
}
/**
* 发送消息
*