本文目录导读:

在 PHP 中实现 Seccomp(安全计算模式)主要有以下几种方法:
使用 PHP 扩展
libseccomp 扩展
<?php
// 检查扩展是否可用
if (!extension_loaded('seccomp')) {
echo "seccomp 扩展未加载\n";
exit(1);
}
// 创建 seccomp 过滤器
$filter = seccomp_init(SCMP_ACT_ALLOW); // 默认允许所有
// 禁止特定系统调用
seccomp_rule_add($filter, SCMP_ACT_KILL, SCMP_SYS(execve), 0);
seccomp_rule_add($filter, SCMP_ACT_ERRNO, SCMP_SYS(open), 0, EACCES);
// 加载过滤器
seccomp_load($filter);
// 清理
seccomp_release($filter);
echo "Seccomp 过滤器已应用\n";
通过 FFI(Foreign Function Interface)
PHP 8.0+ 可以使用 FFI 直接调用 C 库:
<?php
// 使用 FFI 调用 libseccomp
$ffi = FFI::cdef("
typedef struct scmp_filter_ctx *scmp_filter_ctx;
scmp_filter_ctx seccomp_init(uint32_t def_action);
int seccomp_rule_add(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, ...);
int seccomp_load(scmp_filter_ctx ctx);
void seccomp_release(scmp_filter_ctx ctx);
#define SCMP_ACT_ALLOW 0x7fff0000U
#define SCMP_ACT_KILL 0x00000000U
", "libseccomp.so");
// 初始化过滤器
$ctx = $ffi->seccomp_init($ffi->SCMP_ACT_ALLOW);
// 禁止 execve 系统调用
$SYS_execve = 59; // x86_64 架构
$ffi->seccomp_rule_add($ctx, $ffi->SCMP_ACT_KILL, $SYS_execve, 0);
// 加载过滤器
$ffi->seccomp_load($ctx);
// 清理
$ffi->seccomp_release($ctx);
echo "Seccomp 已通过 FFI 应用\n";
调用外部工具
使用执行脚本方式
<?php
// 创建 seccomp 配置脚本
function apply_seccomp_policy(array $allowed_syscalls = []) {
$script = "#!/bin/bash\n";
$script .= "SECCCOMP_TOOL=$(which seccomp-tool 2>/dev/null)\n";
if (empty($allowed_syscalls)) {
// 默认策略:禁止所有,然后允许白名单
$script .= "$SECCCOMP_TOOL --kill-on-error --blacklist=";
$script .= implode(',', get_default_blocked_syscalls());
} else {
// 白名单模式
$script .= "$SECCCOMP_TOOL --whitelist=";
$script .= implode(',', $allowed_syscalls);
}
exec($script, $output, $return_code);
if ($return_code !== 0) {
throw new RuntimeException("Seccomp 应用失败: " . implode("\n", $output));
}
}
// 使用示例
apply_seccomp_policy(['read', 'write', 'exit', 'exit_group']);
echo "Seccomp 策略已应用\n";
使用 Docker 的方式(适用于容器环境)
<?php
// 检查是否在 Docker 中
function get_docker_seccomp_profile() {
$profile = [
"defaultAction" => "SCMP_ACT_ERRNO",
"defaultErrnoRet" => 1,
"archMap" => [
["architecture" => "SCMP_ARCH_X86_64", "subArchitectures" => []]
],
"syscalls" => [
[
"names" => [
"read", "write", "exit", "exit_group",
"fstat", "brk", "mmap", "munmap", "access"
],
"action" => "SCMP_ACT_ALLOW",
"args" => []
]
]
];
return json_encode($profile);
}
// 应用 Docker seccomp profile
function apply_docker_seccomp($container_id) {
$profile = get_docker_seccomp_profile();
$profile_file = '/tmp/seccomp-' . uniqid() . '.json';
file_put_contents($profile_file, $profile);
// 通过 Docker 命令应用
$cmd = sprintf(
'docker update --security-opt seccomp=%s %s',
escapeshellarg($profile_file),
escapeshellarg($container_id)
);
exec($cmd, $output, $return_code);
unlink($profile_file);
return $return_code === 0;
}
完整的 PHP 封装类
<?php
class SeccompManager {
private $ffi = null;
private $ctx = null;
public function __construct() {
$this->initFFI();
}
private function initFFI() {
try {
$this->ffi = FFI::cdef("
typedef struct scmp_filter_ctx *scmp_filter_ctx;
scmp_filter_ctx seccomp_init(uint32_t def_action);
int seccomp_rule_add(scmp_filter_ctx ctx, uint32_t action, int syscall, unsigned int arg_cnt, ...);
int seccomp_load(scmp_filter_ctx ctx);
void seccomp_release(scmp_filter_ctx ctx);
#define SCMP_ACT_ALLOW 0x7fff0000U
#define SCMP_ACT_KILL 0x00000000U
#define SCMP_ACT_ERRNO 0x00050000U
", "libseccomp.so");
} catch (FFI\Exception $e) {
throw new RuntimeException("无法初始化 FFI: " . $e->getMessage());
}
}
public function initialize($default_action = null) {
$action = $default_action ?: 0x7fff0000; // SCMP_ACT_ALLOW
$this->ctx = $this->ffi->seccomp_init($action);
if ($this->ctx === null) {
throw new RuntimeException("Seccomp 初始化失败");
}
return true;
}
public function blockSyscall($syscall_num, $action = 0) { // SCMP_ACT_KILL
if ($this->ctx === null) {
throw new RuntimeException("请先初始化");
}
$result = $this->ffi->seccomp_rule_add(
$this->ctx,
$action,
$syscall_num,
0
);
return $result === 0;
}
public function apply() {
if ($this->ctx === null) {
throw new RuntimeException("请先初始化");
}
$result = $this->ffi->seccomp_load($this->ctx);
return $result === 0;
}
public function cleanup() {
if ($this->ctx !== null) {
$this->ffi->seccomp_release($this->ctx);
$this->ctx = null;
}
}
public function __destruct() {
$this->cleanup();
}
}
// 使用示例
try {
$seccomp = new SeccompManager();
$seccomp->initialize();
// 禁止危险系统调用
$blocked_syscalls = [
59, // execve (x86_64)
57, // fork (x86_64)
107, // socket (x86_64)
41, // socketcall (x86_64)
];
foreach ($blocked_syscalls as $syscall) {
$seccomp->blockSyscall($syscall);
}
$seccomp->apply();
$seccomp->cleanup();
echo "Seccomp 配置完成\n";
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "\n";
}
注意事项
- 权限要求:Seccomp 需要 root 权限或适当的 capabilities
- 系统架构:系统调用号因架构而异(x86_64 vs ARM)
- 不可逆性:Seccomp 一旦应用就无法撤销
- 性能影响:过多的系统调用检查会影响性能
- 兼容性:确保 PHP 版本支持 FFI(8.0+)
选择哪种方式取决于你的具体需求、PHP 版本和运行环境。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播