MCP SSH操作
一种模型上下文协议(MCP)服务器,用于通过SSH在远程Linux系统上执行安全诊断命令。
特性
- 结构化命令格式:命令被指定为结构化JSON——通过构造不可能进行shell注入
- 基于允许列表的安全:只能执行预先批准的命令
- 危险指挥保护:有潜在风险的命令需要明确的许可
- 管道支持:将命令与管道连在一起
- 灵活配置:通过YAML轻松自定义允许的命令
项目结构
mcp-ssh-ops/
├── src/mcp_ssh_ops/
│ ├── __init__.py # Package initialization
│ ├── server.py # MCP server implementation
│ ├── ssh_client.py # SSH client wrapper
│ ├── commands.py # Command validation logic
│ ├── host_memory.py # Host descriptions from hosts.yaml
│ └── recap.py # Optional command recap logging
├── commands.yaml # Allowlist configuration
├── pyproject.toml # Project configuration
└── README.md设置
- 安装依赖项:
uv sync- 运行服务器:
uv run mcp-ssh-opsCLI参数
| 参数 | 描述 | 默认值 |
|---|---|---|
--hosts-config PATH | 通往 hosts.yaml 带主机描述 | 无(主机内存为空) |
--commands-config PATH | 通往 commands.yaml 与排外主义者 | commands.yaml 包裹旁边 |
--recap-dir PATH | 保存命令执行摘要的目录 | 无(已禁用) |
MCP客户端配置示例:
{
"mcpServers": {
"ssh-ops": {
"command": "mcp-ssh-ops",
"args": [
"--hosts-config", "/etc/mcp/hosts.yaml",
"--commands-config", "/etc/mcp/commands.yaml",
"--recap-dir", "/var/log/mcp-recaps"
]
}
}
}当 --recap-dir 设置后,每个命令执行都另存为 .log 文件下 recap-dir/YYYY-MM-DD/HHMMSS_ffffff.log.
用法
服务器公开了一个MCP工具: ssh_exec
参数
hostname:SSH服务器主机名或IP地址pipeline:结构化命令管道(见以下格式)username:SSH用户名(如果在~/.SSH/config中设置,则可选)password:SSH密码(可选)key_file:SSH私钥文件的路径(可选)port:SSH端口(默认值:22)allow_dangerous:启用危险命令(默认值:false)
管道格式
命令以结构化方式传递 pipeline 包含命令列表的对象。每个命令指定一个 program 及其 args 单独:
{
"pipeline": {
"commands": [
{"program": "ps", "args": ["aux"]}
]
}
}多个命令通过管道连接:
{
"pipeline": {
"commands": [
{"program": "ps", "args": ["aux"]},
{"program": "grep", "args": ["python"]},
{"program": "wc", "args": ["-l"]}
]
}
}这构造了: ps aux | grep python | wc -l 每一枚代币都通过 shlex.quote().
示例命令
安全命令 (始终允许):
// Process information
{"commands": [{"program": "ps", "args": ["aux"]}]}
{"commands": [{"program": "ps", "args": ["aux", "--sort=-%mem"]}, {"program": "head", "args": ["-20"]}]}
// Network diagnostics
{"commands": [{"program": "ss", "args": ["-tulpn"]}]}
{"commands": [{"program": "ip", "args": ["-br", "addr"]}]}
// Disk usage
{"commands": [{"program": "df", "args": ["-h"]}]}
{"commands": [{"program": "df", "args": ["-h"]}, {"program": "grep", "args": ["-v", "tmpfs"]}]}
// Memory information
{"commands": [{"program": "free", "args": ["-h"]}]}
// System information
{"commands": [{"program": "uptime"}]}
{"commands": [{"program": "uname", "args": ["-a"]}]}
// Logs
{"commands": [{"program": "journalctl", "args": ["-n", "50", "--no-pager"]}]}
{"commands": [{"program": "dmesg"}, {"program": "tail", "args": ["-50"]}]}
// Pipelines
{"commands": [{"program": "cat", "args": ["/proc/meminfo"]}, {"program": "grep", "args": ["MemTotal"]}]}
{"commands": [{"program": "ps", "args": ["aux"]}, {"program": "grep", "args": ["python"]}, {"program": "wc", "args": ["-l"]}]}危险指令 (要求 allow_dangerous=true):
{"commands": [{"program": "kill", "args": ["-9", "1234"]}]}
{"commands": [{"program": "systemctl", "args": ["restart", "nginx"]}]}配置
编辑 commands.yaml 自定义允许的命令。两者 safe_commands 和 dangerous_commands 是字典,其中每个键都是一个命令名。没有值的命令(或 null)没有争论限制。要限制参数,请添加 args 钥匙与 whitelist 和 blacklist:
safe_commands:
ps:
df:
free:
ip:
args:
blacklist: [add, del, set, flush]
dmesg:
args:
blacklist: [-C, --clear, -c]
dangerous_commands:
kill:
systemctl:
awk:
sed:
settings:
allow_pipes: true
max_command_length: 1000
default_timeout: 30命令类别
- 安全命令:只读诊断工具(ps、df、free等)
- 危险指令:可以修改系统状态(kill、systemctl)或执行任意命令(awk、sed),需要
allow_dangerous=true - 不在allowlist:自动拒绝(rm、关机等)
按命令参数限制
每个命令都可以定义 whitelist 和 blacklist 在...之下 args:
- 白名单:如果设置,则只允许这些确切的参数
- 黑名单:如果设置,这些参数将被阻止(支持精确匹配,
--flag=value,并组合短旗,如-Cl匹配-C)
两者可以结合使用——首先检查白名单,然后检查黑名单。
黑名单匹配示例:
- 精确匹配:
-C块dmesg -C - 带值的长标志:
--vacuum-size块journalctl --vacuum-size=100M - 组合短旗:
-C块dmesg -Cl - 子命令:
add,set块ip addr add,ip link set
安全
此服务器通过构造消除了shell注入:
- 结构化输入:AI将程序名称和参数作为单独的JSON字段提供,从不提供原始shell字符串
- 自动逃逸:每个令牌都通过
shlex.quote()在到达外壳之前。最终命令中唯一的shell运算符是|服务器本身插入的字符 - 程序名称验证:程序名称必须匹配
^[a-zA-Z0-9_][a-zA-Z0-9_.+-]*$--没有像这样的路径/bin/bash,没有shell运算符 - 允许名单执行:仅命令在
safe_commands或dangerous_commands被允许 - 每个命令参数白名单/黑名单:根据每个命令限制或阻止特定参数
- 无测序操作员:仅管道(
|)支持--否&&,||,或;AI可以进行多个工具调用以进行顺序操作
