极狐GitLab Runner 自托管安全加固指南

在私有化部署场景中,极狐GitLab Runner 是 CI/CD 流水线真正执行构建、测试与部署任务的节点。它运行的是来自项目仓库的脚本,本质上提供的是远程代码执行能力。如果 Runner 主机暴露在共享网络中、使用高权限执行器,或者复用同一套环境处理多个项目,安全风险会被迅速放大。

本文从执行器选择、容器隔离、网络分段、镜像策略、主机加固、Git 清理六个维度,梳理一套可直接落地的 Runner 自托管安全加固方案。所有配置项均来自极狐GitLab 官方文档,适用于 JihuLab.com 与私有化部署两种场景。

01 为什么 Runner 安全容易被忽视

很多团队在部署极狐GitLab 时,会把主要精力放在服务端:HTTPS、备份、高可用、权限模型。但对 Runner 的关注往往停留在"能跑起来就行"。

这种疏忽的代价很高。任何拥有项目开发者角色的用户,都可以通过 .gitlab-ci.yml 在 Runner 上执行任意命令。如果 Runner 使用 Shell 执行器、以 root 身份运行,并且长期服务于多个项目,那么:

  • 一个嵌入恶意代码的任务可以读取同一 Runner 上其他项目的代码;
  • 任务可以窃取 CI/CD 变量,包括 CI_JOB_TOKEN
  • 任务可以安装持久化后门,影响后续所有在该 Runner 上执行的构建。

因此,Runner 的安全加固不是可选项,而是私有化部署 CI/CD 的必选项。

02 执行器选择:隔离级别决定安全基线

极狐GitLab Runner 支持多种执行器,安全隔离级别差异很大。官方文档给出了明确的安全排序:

执行器 隔离方式 安全风险 适用场景
Shell 无隔离 仅受信任的单一项目
SSH 远程主机执行 高(易受中间人攻击) 不推荐长期使用
Docker 容器隔离 中(非特权模式下可控) 大多数场景
Kubernetes Pod 隔离 云原生大规模构建
Parallels / VirtualBox 完整虚拟机隔离 对隔离要求最高的场景

Shell 执行器的风险最高,因为任务直接以 Runner 进程用户的权限在主机上运行。除非是在完全受信、单一用途的 Runner 上,否则不应使用 Shell 执行器。

如果必须使用容器化能力,优先选择 Docker 或 Kubernetes 执行器,并确保容器运行在非特权模式。特权容器会获得主机 root 的所有能力,包括挂载文件系统、运行嵌套容器,一旦发生容器逃逸,主机完全失守。

toml 复制代码
[[runners]]
  executor = "docker"
  [runners.docker]
    privileged = false
    services_privileged = false

03 Docker 执行器加固:最小权限原则

在非特权模式下,Docker 执行器已经提供了基础隔离。但要让它更安全,还需要做几件事。

以非 root 用户运行

默认情况下,容器内进程可能以 root 运行。即使容器被限制,root 进程仍比非 root 进程拥有更大的攻击面。建议在 config.toml 中为 Runner 指定一个非特权用户:

toml 复制代码
[runners.docker]
  user = "gitlab-runner"

同时在镜像构建阶段创建该用户,避免使用 root 作为默认运行身份。

收缩 Linux Capability

容器默认携带的 Linux Capability 可能超过 CI/CD 任务实际需要。通过 cap_drop 删除不必要的权限,是减少攻击面的有效手段。

toml 复制代码
[runners.docker]
  cap_drop = ["ALL"]
  cap_add = ["NET_BIND_SERVICE"]

上述配置先移除所有 capability,再按需添加。具体需要保留哪些 capability,取决于你的构建任务是否需要监听低端口、加载内核模块等特殊能力。

固定镜像并始终拉取

镜像拉取策略是 Runner 安全中最容易踩坑的地方之一。if-not-present 策略会在本地没有镜像时拉取,本地存在时复用。这个策略在共享 Runner 上会造成信息泄露:用户 A 用私有凭据拉取的镜像可能残留在 Runner 主机,用户 B 随后启动的构建可以复用该镜像,即使 B 本身没有拉取权限。

官方建议:对于被多项目、多用户共享的 Runner,使用 always 拉取策略;如果希望严格限制镜像来源,则使用 never 并结合预下载白名单。

toml 复制代码
[runners.docker]
  pull_policy = ["always"]
  allowed_images = ["registry.example.com/ci/*:*", "docker.io/library/alpine:*"]

启用用户命名空间

用户命名空间可以把容器内的 root 映射到主机上的非特权用户。即使容器发生逃逸,攻击者在主机上也只是普通用户权限。配置方式是在 config.toml 中启用:

toml 复制代码
[runners.docker]
  userns_mode = "host"

同时需要在 Docker 守护进程中开启 userns-remap 功能。这是一项系统级配置,不能仅在 Runner 层面完成。

04 网络分段:把构建节点放进独立的安全域

Runner 运行的是用户控制的脚本,网络行为不可预测。把 Runner 和其他内部服务放在同一网络段,意味着一旦任务被篡改,攻击者可能横向移动。

官方文档建议为 Runner 规划独立的网络段,至少包含以下控制点:

  • Runner 虚拟机部署在独立的子网或 VPC 中;
  • 禁止 Runner 之间的自由流量互访;
  • 限制 Runner 访问云厂商的元数据端点;
  • 关闭 Runner 面向互联网的 SSH 访问,统一使用堡垒机或串口管理。

所有 Runner 都需要出站到极狐GitLab 实例或 JihuLab.com。大多数构建任务还需要出站到互联网拉取依赖。其余访问应尽可能通过安全组、防火墙或零信任策略收紧。

05 主机加固:静态 Runner 的最后一道防线

如果你的 Runner 运行在静态主机上,而不是每次构建后销毁的短暂实例,那么主机本身的安全基线决定了 worst-case 影响范围。

启用构建目录清理

长期运行的 Runner 会在主机上留下构建目录。.git 目录、缓存、产物都可能被后续任务读取。官方提供功能标志 FF_ENABLE_JOB_CLEANUP,开启后 Runner 会在每次构建结束后清理构建目录。

toml 复制代码
[runners]
  environment = ["FF_ENABLE_JOB_CLEANUP=1"]

清理 Git 配置

从 Runner 17.10 开始,clean_git_config 默认启用。它会在每次构建开始和结束时清理 Git 锁文件、post-checkout hooks 以及 .git/config.git/hooks 目录,防止恶意 Git 配置在任务之间残留。

toml 复制代码
[runners]
  clean_git_config = true

保护主机上的敏感文件

静态主机上不要留存可以被 CI/CD 任务读取的 SSH 私钥、云凭证或 .docker/config.json。如果 Runner 需要访问私有镜像仓库,应通过 CI/CD 变量 DOCKER_AUTH_CONFIG 注入,而不是依赖主机本地配置。并且该变量建议使用 file 类型 变量,避免在日志中泄露。

限制并发与日志

toml 复制代码
concurrent = 8
output_limit = 4096

[[runners]]
  limit = 4
  [runners.docker]
    memory = "2g"
    cpus = "2"

通过 concurrentlimitmemorycpus 限制资源使用,既能防止资源耗尽型攻击,也能避免单个恶意任务拖垮整个 Runner。

关闭调试跟踪

CI_DEBUG_TRACE=true 会输出所有环境变量和命令执行细节,可能泄露敏感变量。在 Runner 配置中关闭调试跟踪,可以防止用户通过 CI 变量强行开启。

toml 复制代码
[runners]
  debug_trace_disabled = true

06 SSH 与 Git 安全:两个容易忽略的点

SSH 执行器

如果你还在使用 SSH 执行器,需要注意官方文档中的明确警告:SSH 执行器缺少 StrictHostKeyChecking 选项,容易受到中间人攻击。在短期无法替换执行器的情况下,至少应确保目标主机密钥被预先分发到 Runner 主机的 known_hosts,并尽量通过 VPN 或专线连接。

Git 策略

GIT_STRATEGY: fetch 可以复用本地仓库副本,提高构建速度。但在共享 Runner 上,这意味着一个项目的 .git 目录会被其他项目复用,可能引入子模块残留或 reflog 中的敏感信息。只有在信任所有访问共享环境的用户时,才应启用 fetch 策略。

07 特权容器:如果必须用它,请隔离到短命虚拟机

有些构建任务确实需要 --privileged 标志,例如在 Docker 中运行 Docker(DinD)。这种情况下,加固思路不是禁用特权,而是把特权任务关进最短的牢笼:

  • 仅让专用 Runner 运行特权任务;
  • 该 Runner 只处理受保护分支;
  • Runner 主机使用短暂虚拟机,每个实例只运行一个或少量构建后就被销毁。

如果使用 Docker Machine 执行器,可以配置 MaxBuilds = 1,确保每个自动扩展虚拟机只处理一个构建后就被回收。

toml 复制代码
[runners.machine]
  MaxBuilds = 1

08 升级与注册:一些基础但关键的操作

保持 Runner 版本与极狐GitLab 实例版本接近,可以及时获得安全修复。使用官方仓库安装时,建议固定到具体版本,而不是默认安装最新版,避免 CI/CD 环境被意外升级破坏。

bash 复制代码
# Debian/Ubuntu 示例
apt-cache madison gitlab-runner
sudo apt install gitlab-runner=17.7.1-1 gitlab-runner-helper-images=17.7.1-1

注册 Runner 时,不要把注册令牌硬编码在脚本或仓库中。注册完成后, Runner 使用与极狐GitLab 服务器通信的令牌来识别身份。不要克隆一个已注册的 Runner 到另一台主机,否则两个 Runner 共享同一令牌,会互相"抢任务",也成为潜在攻击向量。

写在最后

Runner 安全不是单一配置可以解决的问题,而是一组叠加的防护层:从执行器选择开始,到容器隔离、网络分段、主机加固、Git 清理,再到特权场景的最小化暴露。每一层都不能替代其他层。

对于企业私有化部署,建议把 Runner 视为与极狐GitLab 服务端同等重要的安全对象。一个配置不当的 Runner,可能成为从 CI/CD 环境横向进入内部网络的跳板。

极狐GitLab 官方文档提供了完整的安全指南和高级配置项。在部署或审查 Runner 时,建议对照本文清单逐条核对,把"能跑起来"变成"能安全地跑起来"。

相关推荐
其实防守也摸鱼1 小时前
如何使用自动化教育SRC漏洞挖掘系统--AutoHunter
运维·网络·人工智能·学习·安全·web安全·自动化
蒲锘1 小时前
DevOps 项目阶段笔记二:Docker Engine + cri-dockerd
笔记·docker·devops
天行健,君子而铎2 小时前
2026年中国API安全产品综合排名:选型指南与市场趋势解析
大数据·数据库·安全
luiyarch2 小时前
汽车电子ISO 26262功能安全系列(第14期):技术安全概念(TSC)——系统安全架构的设计蓝图
安全·汽车·安全架构
做一个AK梦2 小时前
DevOps
运维·devops
hzxpaipai2 小时前
杭州网站运维|企业官网上线前技术检查清单:SEO、GEO、安全、服务器与备份
运维·服务器·nginx·安全
其实防守也摸鱼4 小时前
推荐一个自动化教育SRC漏洞挖掘系统--AutoHunter
运维·开发语言·人工智能·学习·安全·web安全·自动化
ltl12 小时前
存储加密工程:块级、文件级与应用级怎么选
安全
破碎的南瓜14 小时前
wordpress核心框架漏洞(wp2shell)—先行版(小白篇)
安全·wordpress漏洞·wp2shell