授予非 root 用户使用一个端口的权限

授予非 root 用户使用一个端口的权限

我托管一个实验室服务器,我是根用户(也是普通用户)。

域名是 example.org,我为每个成员分配了一个子域名,例如 Bob 的子域名是 bob.example.org,而用户 Anna 的子域名是 anna.example.org。我想你明白了。:) 使用 nginx 将子域名反向代理到特定端口。

我的问题是,我有什么办法可以授权非 root 用户在其特定端口范围内启动 docker 容器。例如,Anna 被赋予范围 1300-1350,其中端口 1300 绑定到 anna.example.org,其他端口保留。

该系统运行Debian 11 Bullseye和最新的Docker版本。

答案1

首先,只有受信任的用户才可以控制你的 Docker 守护进程

在 Debian Bullseye 安装中,docker 守护进程默认以 root 身份运行。将用户添加到docker组将为该用户提供伪 root 访问权限,因为该用户拥有对 docker 守护进程的控制权,并具有该访问权限。docker 组中的每个用户都将完全控制主机和其他容器,并且可以运行使用--publish任何端口的容器。

有几种选项可以为用户的 Docker 访问提供安全性。

  1. 无根 Docker
  2. sudo
  3. API

1. 无根docker

A无根 docker 设置将允许每个用户运行 docker 守护进程。对于低于 1024 的端口,它需要遵守非特权端口信息bob 提供,因为每个用户将“拥有”自己的守护进程。Docker 还提供了相关指导。这不会阻止安娜占用鲍勃的港口。

2.sudo

允许用户运行 docker 命令的最简单方法是通过 sudo 提供一个 root 控制的脚本,该脚本可以是静态的,也可以控制用户输入的可选参数:

#!/bin/bash
docker run --detach --publish 1300:1300 anna/app-image
anna    ALL=(root) NOPASSWD: /usr/local/bin/start-anna-image

如果你希望用户能够添加自己的选项,你需要非常小心地控制他们的输入,因为

3. Docker 的授权插件或 API

由于 Docker 没有在守护进程上提供任何授权层,因此您需要添加一些内容来控制用户访问。

Docker 提供了内置授权插件实现这一点的框架。以下是一些示例:opa-docker-authzcasbin-authz-插件

您可以让用户访问某种形式的代理 API,该 API 提供对传递给 Docker REST API 的内容的身份验证和授权。大多数编程语言都有 docker 库。Kubernetes+RBAC 是一个位于 Docker 守护进程前面并控制访问的 API 示例(只是一个非常大/复杂的 API,可以做更多事情)。

答案2

据我所知,Linux 只有特权端口与非特权端口的概念。

Linux 内核调优参数 net.ipv4.ip_unprivileged_port_start 定义哪些端口是特权端口。0 到 之间的所有端口net.ipv4.ip_unprivileged_port_start都是特权端口。

特权端口只能由 root 用户启动的进程或具有 root 权限的进程使用,或者由分配了能力 CAP_NET_BIND_SERVICE例如sudo setcap cap_net_bind_service=ep /path/bin/application

所有其他端口都不是特权端口,任何用户都可以使用,只要这些端口尚未被使用。

我不知道有任何替代方法可以允许特定用户使用特定端口。

答案3

只要端口是非特权的,非 root 用户就可以绑定到任何端口(超过 1024)。他们可以使用以下命令启动容器:

docker run --expose 1300-1350  <image-name>

先到先得。如果两个程序尝试绑定到同一个端口,则只有第一个绑定的程序会成功。

对于特权端口(小于 1024),您需要 root 或 CAP_NET_BIND_SERVICE 功能。请参阅man capabilities了解详情。

答案4

只是想增加另一个视角...当然还需要做更多工作!但很有趣...

考虑运行一个容器编排器,例如 Kubernetes。 查看KIND(Kubernetes-in-Docker)了解仅使用 Docker 在单个节点上运行 Kubernetes 集群的有趣方法。

然后你可以做类似的事情

如果您正确地构建角色,那么可以允许用户在其命名空间中启动他们想要的任何容器,但不允许修改service定义公开端口的容器。

这是为了节省空间而简化的,但是像 k8s 这样的原语提供的功能对于像这样的多租户系统来说非常好。

相关内容