agentmain对业务的影响
前面一篇已经说了java agent技术主要有premain和agentmain两种形式,如果大部分业务已经在线上运行的话,不方便用premain的方式来实现,所以agentmain的方式是更加通用、灵活的
由于RASP是与用户业务运行在同一个jvm中的 ,所以RASP会严重影响用户业务的执行情况,如果RASP崩溃的话那么业务程序也会收到严重毁灭性的影响。对业务上的影响主要包含cpu占用和耗时方面的影响
这种影响可以分为两个阶段:
RASP 启动时的问题:
字节码修改:当 RASP 启动时,它需要加载并初始化各种检测逻辑,这些逻辑将被应用到所有进入系统的请求上。
预热问题:当 RASP 刚刚启动时,由于检测逻辑尚未完全“预热”(即 JVM 的即时编译器(JIT)还未对新插入的代码进行优化),因此这些检测逻辑仍然以解释模式运行。解释模式下的性能远低于经过 JIT 编译后的本地机器指令执行效率,这就导致了启动初期的响应时间较长,TP 线变高。
RASP 运行过程中的问题:
检测引擎执行耗时长:如果检测引擎本身的设计不合理或者存在性能瓶颈(例如复杂的规则匹配、大量的数据处理等),也可能导致每次请求都需要花费较长时间来进行安全检查。
具体的运行过程:
以这个图为例,可以看到这个过程涉及到的组件大概有:
- 宿主机:这是运行整个系统的物理或虚拟环境。
- JVM:Java 虚拟机,负责执行 Java 应用程序。
- RASP Agent:RASP 代理,是一个 Java Agent,用于在运行时插入安全检测逻辑。
- RASP Daemon:RASP 守护进程,一个独立于 JVM 的进程,负责管理和控制 RASP Agent。
过程如下:
1. RASP Daemon 发起 Attach 请求
- 守护进程启动:RASP Daemon 是一个独立的进程,它会主动发起与目标 JVM 的连接请求。
- Attach 操作:通过调用
attach
方法,RASP Daemon 可以将自己附着到目标 JVM 上。这一步是通过 Java 提供的工具接口(attach API)实现的,允许外部进程与正在运行的 JVM 进行交互。
2. 加载 RASP Agent
- Agent Jar 包加载:一旦 RASP Daemon 成功 attach 到目标 JVM,它会将 RASP Agent 的 jar 包传递给 JVM。
- 类加载器加载:JVM 使用类加载器AppClassLoader来加载这个 RASP Agent 的 jar 包。这意味着 RASP Agent 将作为应用程序的一部分被加载和执行。(这是因为 Agent jar 包需要访问一些底层的功能和接口,而这些功能和接口是普通应用程序类无法访问的)
3. 初始化并运行 RASP Agent
- 初始化:当 RASP Agent 被加载后,它会开始初始化过程。这包括设置内部状态、注册监听器、配置安全规则等。
- 运行:初始化完成后,RASP Agent 开始监控和保护应用程序。它会在关键位置插入安全检测逻辑,如检查 SQL 注入、XSS 攻击等,并实时响应潜在的安全威胁。
4. 日志/命令通信
- Socket 通信:RASP Agent 和 RASP Daemon 之间通过 socket 进行通信。这种通信机制允许它们交换日志信息、命令和其他数据。
- 日志记录:RASP Agent 会将检测到的安全事件、异常情况等记录下来,并通过 socket 发送给 RASP Daemon。
- 命令处理:RASP Daemon 可以发送命令给 RASP Agent,例如更新安全规则、调整监控策略等。
升级变更难:
由于agent的入口类是jvm中的AppClassLoader加载的,所以即使attach了新的agent,由于类的加载机制也不能加载新的类,所以无法进行agent的变更和升级
学习资料:美团RASP大规模研发部署实践总结 - 美团技术团队