内容
# 跳过者
跳过者是一个轻量级的Oracle数据库诊断模型上下文协议(MCP)服务器。它可以查询Oracle固定视图,运行只读SQL,搜索Oracle SGA中的字节模式,推断X$结构的布局,并使用GDB跟踪Oracle C函数。
MCP服务器完全使用Python标准库编写。内存扫描由捆绑的`focs_vm`实用程序执行,该实用程序从Rust源代码构建。
> [!WARNING]
> 跳过者是一种特权诊断工具。它可以作为SYSDBA本地连接,检查进程内存,并将调试器附加到Oracle进程。仅在授权的诊断或实验室系统上安装它,限制网络访问,并且永远不要将HTTP端口直接暴露在Internet上。
## 平台和依赖项
下面的部署过程针对AArch64上的Oracle Linux 8.9,Oracle数据库由用户`oracle`和组`oinstall`运行。它使用:
| 依赖项 | 所需 | 备注 |
| --- | --- | --- |
| Python 3.12 | MCP服务器和测试 | 不需要第三方Python包、`pip`或虚拟环境。 |
| 本地Oracle数据库安装 | Oracle诊断工具 | 服务帐户必须能够使用本地OS身份验证。 |
| SQL\*Plus | 所有`oracle_*` SQL工具 | 通常位于 `$ORACLE_HOME/bin/sqlplus`。 |
| Rust工具链和Cargo | 构建`focs_vm` | 仅在构建或更新扫描器时需要。 |
| GCC/链接器 | 构建`focs_vm` | 从Oracle Linux开发包安装。 |
| Linux `/proc` 访问 | 进程和SGA发现 | 内存相关工具需要。 |
| `sudo` | 特权内存扫描和调试 | 仅当服务用户无法直接访问目标进程时需要。 |
| GDB | `oracle_debug_*` 工具 | 除非需要C函数跟踪,否则可选。 |
| GNU `strings` 和 `grep` | 长固定视图回退 | `strings` 由 `binutils` 提供;此回退仅在视图定义截断时运行。 |
| Git 和 curl | 安装 | 用于克隆存储库和安装Rust。 |
整个指南中明确使用Python 3.12。在Oracle Linux 8上,`python3` 可能仍解析为Python 3.6,因此不要假设它选择所需的解释器。
## 分步安装
本节中的命令假设最终安装目录为 `/home/oracle/skipper`。
### 1. 安装系统包
以用户`oracle`身份运行以下命令,并有权访问`sudo`:
```bash
sudo dnf install -y git curl gcc python3.12 binutils grep sudo
```
如果将使用`oracle_debug_*`工具,还请安装GDB:
```bash
sudo dnf install -y gdb
```
确认Python版本:
```bash
/usr/bin/python3.12 --version
```
### 2. 克隆存储库
```bash
cd /home/oracle
git clone https://github.com/ora600pl/skipper.git
cd /home/oracle/skipper
```
如果已经配置了GitHub SSH访问,可以使用SSH URL:
```bash
git clone git@github.com:ora600pl/skipper.git
```
### 3. 安装Rust
为`oracle`帐户安装Rust,因为该帐户构建和运行项目:
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup-init.sh
sh /tmp/rustup-init.sh -y --profile minimal
source "$HOME/.cargo/env"
rustc --version
cargo --version
```
### 4. 构建内存扫描器
使用`Cargo.lock`中记录的依赖项版本构建发布二进制:
```bash
cd /home/oracle/skipper
cargo build --locked --manifest-path tools/focs_vm/Cargo.toml --release
test -x tools/focs_vm/target/release/focs_vm
```
生成的可执行文件是:
```text
/home/oracle/skipper/tools/focs_vm/target/release/focs_vm
```
跳过者会自动找到此路径。只有当扫描器安装在其他位置时,才需要设置 `FOCS_VM_BIN`。
### 5. 运行测试套件
启动器将 `src/` 添加到Python模块路径,但测试运行器需要显式的 `PYTHONPATH`:
```bash
cd /home/oracle/skipper
PYTHONPATH=src /usr/bin/python3.12 -m unittest discover -s tests -v
/usr/bin/python3.12 -m unittest discover -s tools/rico2 -p 'test_*.py' -v
/usr/bin/python3.12 bin/skipper-mcp --version
/usr/bin/python3.12 bin/skipper-mcp --help
```
### 6. 手动提供密码字典
生产密码字典故意不在存储库中提供。请手动提供它作为此确切文件:
```text
/home/oracle/skipper/dict.txt
```
文件必须命名为 `dict.txt`,位于Skipper存储库根目录下,并包含每个UTF-8行一个密码候选。它被Git忽略,以便不会意外提交本地维护的字典。
当前包含一个小示例字典:
```text
/home/oracle/skipper/data/dict.example.txt
```
它只包含 `test`、`hr`、`dupa`、`abc123`、`oracle`、`Oracle+` 和 `Oracle+1`。如果未提供 `/home/oracle/skipper/dict.txt`,则 `oracle_password_check` 工具自动仅使用此示例文件。来自该回退的无匹配结果并不意味着密码很弱。
要基于示例创建最小的本地字典,请复制它然后扩展:
```bash
cd /home/oracle/skipper
cp data/dict.example.txt dict.txt
chmod 0600 dict.txt
```
### 7. 配置Oracle环境
服务不读取 `oracle` 用户的shell配置文件。复制提供的环境文件并为本地实例编辑它:
```bash
sudo install -m 0644 deploy/skipper-mcp.env.example /etc/sysconfig/skipper-mcp
sudo vi /etc/sysconfig/skipper-mcp
```
示例:
```ini
ORACLE_SID=rick
ORACLE_BASE=/u01/app/oracle
ORACLE_HOME=/u01/app/oracle/product/19.19/dbhome_1
PATH=/u01/app/oracle/product/19.19/dbhome_1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
```
以运行Skipper的用户身份验证本地OS身份验证:
```bash
echo 'select instance_name, status from v$instance; exit' | "$ORACLE_HOME/bin/sqlplus" -s / as sysdba
```
服务帐户必须属于Oracle OS组,以允许 `sqlplus / as sysdba`。
### 8. 授予狭义的进程内存访问权限
提供的systemd单元设置 `SKIPPER_FOCS_USE_SUDO=true`,导致内存扫描通过非交互式 `sudo -n` 运行。授予对扫描器的访问权限,而不是使用 `NOPASSWD: ALL`:
```bash
printf '%s\n' 'oracle ALL=(root) NOPASSWD: /home/oracle/skipper/tools/focs_vm/target/release/focs_vm' \
| sudo tee /etc/sudoers.d/skipper-mcp >/dev/null
sudo chmod 0440 /etc/sudoers.d/skipper-mcp
sudo visudo -cf /etc/sudoers.d/skipper-mcp
sudo -n /home/oracle/skipper/tools/focs_vm/target/release/focs_vm --help >/dev/null
```
要通过 `sudo` 使用GDB工具,请将 `/usr/bin/gdb` 添加到同一规则:
```sudoers
oracle ALL=(root) NOPASSWD: /home/oracle/skipper/tools/focs_vm/target/release/focs_vm, /usr/bin/gdb
```
然后将此行添加到 `/etc/sysconfig/skipper-mcp`:
```ini
SKIPPER_GDB_USE_SUDO=true
```
进程跟踪也可能受到Linux ptrace策略或服务强化的限制。请将这些权限限制在受控主机上。
### 9. 安装和启动systemd服务
包含的单元期望 `/home/oracle/skipper`、用户 `oracle`、组 `oinstall`、Python 3.12 和 TCP端口 6751:
```bash
cd /home/oracle/skipper
sudo install -m 0644 deploy/skipper-mcp.service /etc/systemd/system/skipper-mcp.service
sudo systemctl daemon-reload
sudo systemctl enable --now skipper-mcp.service
sudo systemctl status skipper-mcp.service --no-pager -l
```
检查健康端点和最近的日志:
```bash
curl --fail http://127.0.0.1:6751/health
sudo journalctl -u skipper-mcp.service -n 100 --no-pager
```
预期的健康响应:
```json
{"status":"ok","server":"skipper"}
```
MCP端点现在可在 `http://HOST:6751/mcp` 访问。
## 无systemd运行
对于前台HTTP服务器:
```bash
cd /home/oracle/skipper
export ORACLE_SID=rick
export ORACLE_HOME=/u01/app/oracle/product/19.19/dbhome_1
export PATH="$ORACLE_HOME/bin:$PATH"
/usr/bin/python3.12 bin/skipper-mcp --bind 127.0.0.1 --port 6751
```
适用于标准输入/输出的MCP:
```bash
/usr/bin/python3.12 /home/oracle/skipper/bin/skipper-mcp --stdio
```
## 连接MCP客户端
对于具有HTTP功能的MCP客户端,请使用:
```json
{
"mcpServers": {
"skipper": {
"url": "http://192.168.181.136:6751/mcp"
}
}
}
```
对于启动本地stdio服务器的客户端,请使用等效的:
```json
{
"mcpServers": {
"skipper": {
"command": "/usr/bin/python3.12",
"args": [
"/home/oracle/skipper/bin/skipper-mcp",
"--stdio"
],
"env": {
"ORACLE_SID": "rick",
"ORACLE_HOME": "/u01/app/oracle/product/19.19/dbhome_1"
}
}
}
}
```
客户端配置格式各不相同,因此请根据客户端调整外部JSON结构,同时保留命令、URL和环境值。
### 手动验证HTTP API
初始化MCP连接:
```bash
curl -sS http://127.0.0.1:6751/mcp \
-H 'Content-Type: application/json' \
--data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"manual-test","version":"1.0"}}}'
```
列出已注册的工具:
```bash
curl -sS http://127.0.0.1:6751/mcp \
-H 'Content-Type: application/json' \
--data '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
```
调用工具:
```bash
curl -sS http://127.0.0.1:6751/mcp \
-H 'Content-Type: application/json' \
--data '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"oracle_select","arguments":{"query":"select instance_name, status from v$instance"}}}'
```
## 使用工具
MCP `tools/list` 响应是每个参数的权威描述。下面总结了最常见的流程。
### 使用RICO2检查和编辑Oracle块
调用 `rico2` 时带有一个RICO2列表文件和一个命令或有序命令数组。数组中的每个命令都在同一个隔离会话中运行,因此位置、偏移量、编辑模式、当前块缓冲区及其撤销快照都得以保留:
```json
{
"listfile": "/home/oracle/rico2-listfile.txt",
"commands": [
"set dba 7,120",
"show",
"map",
"print kdbh",
"print *kdbr[0]",
"examine /rncc",
"verify"
]
}
```
适配器接受完整的交互式命令集:`INFO`、`SHOW`、`SET`、`DUMP`/`D`、`MAP`、`PRINT`/`P`、`EXAMINE`/`X`、`FIND`、`SELECT`、`MODIFY`/`ASSIGN`、`SUM`/`CHECKSUM`、`VERIFY`、`COPY`、`UNDO`、`REVERT`/`DUPA`、`SAVE`、`HELP`和`EXIT`/`QUIT`。有关语法和块结构详细信息,请参见 [`tools/rico2/README.md`](tools/rico2/README.md)。
`MODIFY` 和 `ASSIGN` 需要 `"confirm_modifications": true`;这会替换交互式 `Y/N` 提示。立即写入数据文件的命令(`SAVE`、`COPY`、`REVERT` 和 `DUPA`)还需要 `"allow_disk_writes": true`。RICO2仍然需要 `SET MODE EDIT`,而底层命令需要它。两个确认默认值为false。
```json
{
"listfile": "/home/oracle/rico2-listfile.txt",
"commands": [
"set dba 7,120",
"set offset 100",
"modify -h deadbeef",
"set mode edit",
"sum apply",
"verify",
"save"
],
"confirm_modifications": true,
"allow_disk_writes": true
}
```
RICO2写入原始的Oracle数据文件块,不会与正在运行的数据库协调。请仅在经过验证的备份或隔离的实验室副本上使用写入命令。新RICO2会话用于每个MCP调用;请将依赖的命令放在一个数组中。
### 运行只读Oracle查询
调用 `oracle_select` 时带有一个 `SELECT` 语句或以 `WITH` 开头的查询:
```json
{
"query": "select instance_name, status from v$instance"
}
```
该工具使用 `sqlplus / as sysdba` 连接,并返回以管道分隔的CSV。额外的SQL语句和SQL\*Plus命令被拒绝。默认超时为120秒,默认输出限制为1 MiB。
每当查询读取 `USER$` 时,结果会包含一个安全后续检查,鼓励模型为每个非空 `SPARE4` 值调用 `oracle_password_check`。
### 检查Oracle密码验证器对抗字典
调用 `oracle_password_check` 时提供完整的 `USER$.SPARE4` 值。它可能包含Oracle 11g `S:` 验证器、Oracle 12c `T:` 验证器或两者:
```json
{
"spare4": "S:9DEA3FA1EDC6087AD05C7E8AE3FD179D4E93CF9BBE12100B315AB84BC247"
}
```
该工具移植了 `oracle-Password` 中的算法:用于 `S:` 的盐化SHA-1,用于 `T:` 的PBKDF2-HMAC-SHA512加SHA-512。它报告了使用哪个字典文件、检查了哪些验证器版本、检查了多少个候选者以及是否找到密码。它更喜欢 `/home/oracle/skipper/dict.txt`;如果该文件不存在,它只使用 `/home/oracle/skipper/data/dict.example.txt`。这是对密码强度的离线审计,不会尝试登录数据库。
### 查找固定视图定义
调用 `oracle_view_definition`:
```json
{
"view_name": "GV$SQL"
}
```
如果SQL\*Plus截断长定义,Skipper可以搜索嵌入 `$ORACLE_HOME/bin/oracle` 的SQL,使用 `strings` 和 `grep`。传递 `"fallback": false` 禁用此行为。
### 搜索Oracle SGA
调用 `focs_vm` 时提供进程PID和UTF-8字符串:
```json
{
"pid": 2374,
"pattern": "select instance_name from v$instance"
}
```
对于字节模式,请使用十六进制令牌:
```json
{
"pid": 2374,
"pattern": "73 65 6c 65 63 74",
"pattern_type": "hex",
"memory_size": "6G"
}
```
如果省略 `memory_size`,Skipper选择进程映射的最大SysV共享内存段。人类可读的值(如 `6G`)与实际映射大小匹配;纯整数被视为确切的字节数。
### 从V$或GV$视图推断X$结构
调用 `oracle_structure_from_x`:
```json
{
"view_name": "GV$SQL",
"match_column": "SQL_FULLTEXT",
"match_value": "select instance_name from v$instance",
"pid": 2374,
"memory_size": "6G",
"output_path": "/tmp/gvsql-structure.json"
}
```
该工具解析底层X$表,映射视图列,找到匹配的X$行,构建二进制锚点,扫描SGA,集群候选偏移量,并写入JSON报告。如果省略 `pid`,它使用 `ORACLE_SID` 发现PMON。如果省略 `output_path`,则报告写入 `/tmp`。
### 跟踪 Oracle C 函数
持久调试工作流将进程控制与专注的 GDB 调查分开:
1. 调用 `oracle_debug_start_session` 启动 SQL*Plus 并获取 `debug_session_id`、Oracle SID 和服务器进程 SPID。
2. 调用 `oracle_debug_attach`,使用该 ID 和断点位置,例如 `kksLoadChild` 或 `kksLoadChild+0x2a`。服务器进程保持停止状态。
3. 调用 `oracle_debug_trigger`,使用应命中断点的 SQL。
4. 在 GDB 停止时,使用一个或多个调查工具:`oracle_debug_inspect`、`oracle_debug_backtrace`、`oracle_debug_evaluate`、`oracle_debug_set_variable`、`oracle_debug_memory` 或 `oracle_debug_disassemble`。
5. 始终调用 `oracle_debug_close` 以分离 GDB 并终止 SQL*Plus。
最小参数示例:
```json
{"connection":"/ as sysdba"}
{"debug_session_id":"ID_FROM_STEP_1","breakpoint":"kksLoadChild+0x2a"}
{"debug_session_id":"ID_FROM_STEP_1","sql":"select 1 from dual"}
{"debug_session_id":"ID_FROM_STEP_1"}
{"debug_session_id":"ID_FROM_STEP_1","full":false,"max_frames":32}
{"debug_session_id":"ID_FROM_STEP_1","expression":"$x0","format":"hex"}
{"debug_session_id":"ID_FROM_STEP_1","function":"kksLoadChild"}
{"debug_session_id":"ID_FROM_STEP_1"}
```
专注的工具将常见的 GDB 操作映射到结构化的 MCP 参数:
| MCP 工具 | GDB 等价 | 目的 |
| --- | --- | --- |
| `oracle_debug_backtrace` | `bt` 或 `bt full` | 返回调用栈,可选地带有局部变量和帧限制。 |
| `oracle_debug_evaluate` | `p`、`p/x` 及相关格式 | 评估寄存器、符号、强制转换、解引用和指针运算。 |
| `oracle_debug_set_variable` | `set $name = expression` | 在 GDB 方便变量中保存寄存器或计算指针。 |
| `oracle_debug_memory` | `x/nfu address` | 从选定地址读取字符串、整数、指针、原始字节或指令。 |
| `oracle_debug_inspect` | `bt full`、`info args`、`info registers` 及 ABI 探针 | 在一次调用中收集广泛的诊断快照。 |
| `oracle_debug_disassemble` | `disassemble /r function` | 返回汇编代码以及指令字节。 |
例如,以下调用基于 AArch64 参数寄存器重现 NLS 指针调查:
```json
{"debug_session_id":"ID_FROM_STEP_1","name":"new_nls","expression":"$x0"}
{"debug_session_id":"ID_FROM_STEP_1","name":"prev_nls","expression":"$x1"}
{"debug_session_id":"ID_FROM_STEP_1","address":"$new_nls+0xa0","count":1,"unit":"byte","format":"string"}
{"debug_session_id":"ID_FROM_STEP_1","address":"$prev_nls+0xa0","count":1,"unit":"byte","format":"string"}
```
这些变为 `set $new_nls = $x0`、`set $prev_nls = $x1`、`x/1bs $new_nls+0xa0` 和 `x/1bs $prev_nls+0xa0`。在评估、设置变量或内存调用中使用可选的 `frame` 参数,以在解析寄存器和符号之前选择堆栈帧。评估格式为 `natural`、`hex`、`signed`、`unsigned`、`octal`、`binary`、`address`、`char` 和 `float`。内存单位为 `byte`、`halfword`、`word` 和 `giant`;内存格式还包括 `string` 和 `instruction`。
交互工具不接受原始 GDB 命令。表达式仅限于单个非命令行,赋值和增量/减量表达式被拒绝,当 GDB 附加时禁用劣等函数调用。进程控制仅限于生命周期工具。
`oracle_debug_attach` 接受三种刻意限制的断点形式:
| 形式 | 示例 | GDB 行为 |
| --- | --- | --- |
| C 符号 | `kksLoadChild` | 在函数入口点中断。 |
| 符号加偏移量 | `kksLoadChild+0x2a` 或 `kksLoadChild+42` | 在从加载符号中解析的确切指令地址中断。 |
| 绝对十六进制地址 | `0x000000001234abcd` | 在附加进程中的确切虚拟地址中断。 |
偏移量为非负数,可以是十进制或十六进制。使用指向指令边界的偏移量;例如,可以使用调用指令后的地址来检查其返回值。GDB 在附加后解析符号位置,因此 `symbol+offset` 在 Oracle 映像被 ASLR 重新定位时继续有效。绝对地址是进程特定的。故意拒绝任意 GDB 表达式,以防止 MCP 输入成为 GDB 命令通道。
## 配置参考
命令行选项优先于环境默认值。
| 设置 | 默认值 | 目的 |
| --- | --- | --- |
| `-b`、`--bind`、`--host` / `SKIPPER_MCP_HOST` | `0.0.0.0` | HTTP 监听地址。 |
| `-p`、`--port` / `SKIPPER_MCP_PORT` | `6751` | HTTP 监听端口。 |
| `--path` / `SKIPPER_MCP_PATH` | `/mcp` | MCP HTTP 端点。 |
| `--stdio` | 关闭 | 使用标准输入/输出代替 HTTP。 |
| `SKIPPER_ALLOWED_ORIGINS` | 空 | 允许发送 HTTP 请求的以逗号分隔的浏览器来源列表。 |
| `FOCS_VM_BIN` | 捆绑的发布路径 | 重写 `focs_vm` 可执行文件。 |
| `SKIPPER_FOCS_USE_SUDO` | 关闭 | 通过 `sudo -n` 运行 `focs_vm`。 |
| `SQLPLUS_BIN` | 自动检测 | 重写 SQL*Plus 可执行文件。 |
| `ORACLE_BIN` | `$ORACLE_HOME/bin/oracle` | 重写 GDB 和字符串回退使用的 Oracle 可执行文件。 |
| `GDB_BIN` | `gdb` | 重写 GDB 可执行文件。 |
| `SKIPPER_GDB_USE_SUDO` | 关闭 | 通过 `sudo -n` 运行 GDB。 |
Skipper 支持 MCP 协议修订版 `2025-11-25`、`2025-06-18` 和 `2024-11-05`。
## 网络安全
内置的 HTTP 传输不提供身份验证或 TLS。当只需要本地访问时,请绑定到 `127.0.0.1`。对于远程访问,请使用防火墙将端口 6751 限制到受信任的主机,或将服务置于经过身份验证的 TLS 代理或 SSH 隧道后面。不要在公共接口上发布端点。
## 更新
```bash
cd /home/oracle/skipper
git pull --ff-only
source "$HOME/.cargo/env"
cargo build --locked --manifest-path tools/focs_vm/Cargo.toml --release
PYTHONPATH=src /usr/bin/python3.12 -m unittest discover -s tests -v
sudo systemctl restart skipper-mcp.service
curl --fail http://127.0.0.1:6751/health
```
## 开发
从存储库根目录运行所有测试:
```bash
PYTHONPATH=src /usr/bin/python3.12 -m unittest discover -s tests -v
```
工具适配器位于 `src/skipper_mcp/tools/`。新的适配器定义其处理程序和 `register(registry)` 函数,然后由 `src/skipper_mcp/tools/__init__.py` 导入。
## 许可证
请参阅 [LICENSE](LICENSE)。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器