首页 / 资讯动态 / debian服务器安全容器基础安全加固

debian服务器安全容器基础安全加固

Debian服务器跑容器,安全加固的核心不是装个防火墙就完事,而是要把“容器逃逸”和“内核参数滥用”这两条路先堵死。多数人把精力放在镜像漏洞扫描上,却忽略了宿主机的默认配置本身就不适合承载多租户容器。下面直接讲具体要改什么、怎么改、为什么这么改。

先锁定容器运行的内核参数

Debian 12默认内核参数对容器并不友好。容器里如果允许修改网络参数、挂载文件系统、访问宿主机IPC资源,等于把半个root权限交出去了。最有效的做法是在宿主机上通过sysctl强制覆盖,而不是指望容器启动命令里逐个禁用。

编辑/etc/sysctl.d/99-container-hardening.conf,写入以下内容:

# 禁止容器内修改内核网络参数
net.ipv4.ip_forward = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# 限制容器访问宿主机IPC资源
kernel.msgmax = 65536
kernel.msgmnb = 65536
kernel.sem = 250 32000 100 128

# 防止容器通过ptrace干扰宿主机进程
kernel.yama.ptrace_scope = 2

# 关闭未使用的网络协议,减少攻击面
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1

执行sysctl --system立即生效。这里把ip_forward设为0,是因为宿主机如果不是专门做路由或NAT网关,容器网络走桥接或macvlan根本不需要开启转发。很多教程让你开转发方便容器互通,但生产环境里容器间通信应该显式配置网络策略,而不是靠宿主机的全局转发兜底。

用户命名空间必须强制启用

Debian默认的Docker或containerd配置里,容器root用户映射到宿主机上依然是root,只是受限于capabilities。一旦某个capability被错误授予,或者内核出现漏洞,容器就能直接操作宿主机文件系统。启用用户命名空间后,容器内的root在宿主机上只是一个普通UID,即使逃逸出来也拿不到宿主机root权限。

对于Docker,编辑/etc/docker/daemon.json:

{
  "userns-remap": "default",
  "no-new-privileges": true,
  "live-restore": false
}

重启Docker服务后,所有容器会自动运行在独立的用户命名空间里。注意userns-remap会改变容器内文件在宿主机上的属主,如果你之前有持久化卷,需要先迁移权限。containerd用户则需要在/etc/containerd/config.toml中启用enable_keychain和user namespace相关配置,具体取决于你用的是runc还是kata。

no-new-privileges这个参数经常被忽略。它确保容器启动后,即使内部进程尝试执行带setuid位的程序,也无法获得额外权限。很多提权攻击依赖的就是setuid二进制文件,这个开关直接封死这条路。

Seccomp和AppArmor要叠加使用

Debian自带的Docker默认会启用一个seccomp配置文件,但这个默认配置允许的系统调用还是偏多。建议自己维护一份更严格的seccomp profile,重点拦截mount、umount、reboot、kexec_load、bpf等高风险调用。容器内跑常规Web服务、数据库、消息队列,根本不需要这些调用。

AppArmor方面,Debian默认对容器只加载了docker-default策略,这个策略比较宽松。你可以为不同业务容器编写独立的AppArmor profile,限制文件访问路径、网络socket类型、capabilities范围。比如一个纯计算型容器,直接禁止它监听端口和访问/etc/passwd以外的系统文件。

在容器启动命令中同时指定:

docker run --security-opt seccomp=/path/to/custom-seccomp.json \
           --security-opt apparmor=my-container-profile \
           --cap-drop=ALL \
           --cap-add=NET_BIND_SERVICE \
           your-image

cap-drop=ALL是基础,不要用默认的capabilities集合。默认集合里有CAP_SYS_ADMIN、CAP_SYS_PTRACE这类危险权限,绝大多数业务容器用不上。只加回必要的capability,比如绑定低端口需要NET_BIND_SERVICE,调整系统时间需要SYS_TIME,其余一律不给。

文件系统只读和挂载限制

容器根文件系统应该默认只读。业务需要写日志或临时文件时,单独挂载tmpfs或指定的持久化卷。这样即使容器被攻破,攻击者也无法修改容器内的二进制文件或植入后门。

docker run --read-only \
           --tmpfs /tmp:rw,noexec,nosuid,size=256m \
           --tmpfs /var/log:rw,noexec,nosuid,size=128m \
           --mount type=bind,source=/data/app,target=/app/data \
           your-image

注意tmpfs挂载时加上noexec和nosuid,防止攻击者在内存文件系统里放置并执行恶意程序。持久化卷的宿主机目录权限要单独收紧,不要让容器以root身份写宿主机目录,结合前面提到的用户命名空间,容器内的root在宿主机上只是普通用户,这样即使写入恶意文件也无法设置setuid位或修改系统关键路径。

容器网络隔离与防火墙策略

Debian宿主机上不要用默认的docker0网桥直接暴露容器端口。每个业务组使用独立的bridge网络,或者直接用macvlan让容器获得独立内网IP。容器之间的通信默认是互通的,除非你手动配置iptables规则或使用网络策略插件。

在宿主机上用iptables限制容器网段访问宿主机管理端口:

iptables -A INPUT -s 172.17.0.0/16 -d 10.0.0.10 -p tcp --dport 22 -j DROP
iptables -A INPUT -s 172.17.0.0/16 -d 10.0.0.10 -p tcp --dport 2375 -j DROP
iptables -A INPUT -s 172.17.0.0/16 -d 10.0.0.10 -p tcp --dport 2376 -j DROP

这里假设宿主机管理IP是10.0.0.10,容器网段是172.17.0.0/16。SSH端口和Docker API端口必须对容器网段关闭,否则容器内一旦拿到宿主机内网访问能力,就能直接尝试登录宿主机或操作Docker守护进程。

如果容器需要对外提供服务,不要在宿主机上直接做端口映射。更好的做法是前置一层反向代理或负载均衡,容器只监听内网地址,由代理统一处理TLS终止和访问控制。这样容器本身不直接暴露在公网,攻击面大幅缩小。

镜像供应链和运行时监控

基础镜像不要用latest标签,固定到具体版本号。每次构建时用debsecan或trivy扫描Debian基础镜像的已知漏洞,发现高危漏洞立即重建。容器运行后,用falco或sysdig监控异常系统调用、文件访问和网络行为。特别是容器内出现mount操作、访问/etc/shadow、尝试加载内核模块等行为,要立即告警并隔离容器。

Debian的unattended-upgrades在宿主机上要开启,但容器内的软件更新不能依赖宿主机机制。容器应该采用不可变基础设施思路,更新软件就是重新构建镜像,而不是在运行中的容器里apt upgrade。运行中的容器一旦被修改,就失去了可重复性和审计能力。

审计和日志落盘

容器日志不要只输出到stdout然后依赖Docker的json-file驱动。生产环境应该把日志通过syslog或journald转发到集中日志系统,同时宿主机上保留一份本地落盘。Docker的json-file驱动默认不限制日志文件大小,容器产生大量日志时可能撑爆宿主机磁盘。

在daemon.json中配置日志轮转:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

同时开启auditd对宿主机关键路径的监控,特别是/var/lib/docker、/etc/docker、/run/containerd这些目录。任何对容器配置、镜像存储、运行时状态的修改都要记录来源进程和用户。

Debian服务器承载容器时,安全加固不是一次性任务。内核参数、用户命名空间、seccomp/AppArmor、文件系统只读、网络隔离、镜像扫描、运行时监控,这七层缺一不可。每多一层限制,攻击者从容器逃逸到宿主机的难度就上升一个量级。实际部署时按照这个顺序逐项落地,比装一堆花哨的安全产品更有效。