1.准备工作

安装selinux-policy-devel

selinux-policy-devel 提供更多自定义策略功能

yum install selinux-policy-devel -y

暂时关闭SELinux强制模式(代策略配置好后开启)

setenforce 0

开启 docker selinux

$ tee /etc/docker/daemon.json <<-'EOF'
{
  "selinux-enabled" : true
}
EOF

$ systemctl daemon-reload

$ systemctl restart docker

2.创建一个基本的容器策略,例如docker_elephdev

vi docker_elephdev.te

policy_module(docker_elephdev, 1.0);

virt_sandbox_domain_template(docker_elephdev);

# 许可域允许进程不被 SELinux 阻止(permissive)
# 当策略完全配置好后, 需注释掉,则是强制模式(enforcing)
# 配置阶段需容器使用到的规则都将被记录在AVC, 通过日志可以得知容器所需的策略配置
permissive docker_elephdev_t;

virt_sandbox_domain_template宏会创建新类型,docker_elephdev_t并为docker操作创建必要的规则,以将新类型用作容器域

3. 编译并加载策略模块

编译策略

# 如提示命令不存在则使用:/usr/share/selinux/devel/Makefile
make -f /usr/selinux/devel/Makefile docker_elephdev.pp

image.png

执行完后目录下会多出3个文件1个临时目录

[root@localhost elephdev]# ll
total 88
-rw-r--r--. 1 root root     0 Sep 26 03:36 docker_elephdev.fc
-rw-r--r--. 1 root root    23 Sep 26 03:36 docker_elephdev.if
-rw-r--r--. 1 root root 80946 Sep 26 03:36 docker_elephdev.pp
-rw-r--r--. 1 root root   116 Sep 26 03:35 docker_elephdev.te
drwxr-xr-x. 2 root root    78 Sep 26 03:36 tmp

加载策略模块

semodule -i docker_elephdev.pp
semodule -l | grep docker_elephdev #验证是否加载成功

image.png

4.如何根据容器配置对应策略

运行nginx容器并指定策略模块

[root@localhost elephdev]# docker run -it --rm -p 80:80 --name elenginx --security-opt label:type:docker_elephdev_t nginx

label:type:docker_elephdev_t nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2021/09/25 19:41:42 [notice] 1#1: using the "epoll" event method
2021/09/25 19:41:42 [notice] 1#1: nginx/1.21.3
2021/09/25 19:41:42 [notice] 1#1: built by gcc 8.3.0 (Debian 8.3.0-6)
2021/09/25 19:41:42 [notice] 1#1: OS: Linux 3.10.0-1160.el7.x86_64
2021/09/25 19:41:42 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2021/09/25 19:41:42 [notice] 1#1: start worker processes
2021/09/25 19:41:42 [notice] 1#1: start worker process 32
2021/09/25 19:41:42 [notice] 1#1: start worker process 33

image.png

查看拦截提醒

image.png

产生预期的错误。然后运行audit2allow以生成规则,以允许对进行这些操作docker_elephdev_t,您可以.te使用新规则更新相同的模块文件(请记住要增加版本号),编译并安装更新的模块

使用 audit2allow 命令,可以轻松地从拒绝操作的日志中生成 SELinux 策略允许规则

[root@localhost elephdev]# grep docker_elephdev_t /var/log/audit/audit.log | audit2allow -r

require {
        type node_t;
        type http_port_t;
        type docker_elephdev_t;
        class capability { chown net_bind_service setgid setuid };
        class tcp_socket { accept bind create listen name_bind node_bind setopt };
}

#============= docker_elephdev_t ==============
allow docker_elephdev_t http_port_t:tcp_socket name_bind;
allow docker_elephdev_t node_t:tcp_socket node_bind;
allow docker_elephdev_t self:capability { chown net_bind_service setgid setuid };
allow docker_elephdev_t self:tcp_socket { accept bind create listen setopt };

vi docker_elephdev.te

policy_module(docker_elephdev, 1.1);

virt_sandbox_domain_template(docker_elephdev);

require {
  type node_t;
  type http_port_t;
  type docker_elephdev_t;
  class capability { chown net_bind_service setgid setuid };
  class tcp_socket { accept bind create listen name_bind node_bind setopt };
};

#============= docker_elephdev_t ==============
allow docker_elephdev_t http_port_t:tcp_socket name_bind;
allow docker_elephdev_t node_t:tcp_socket node_bind;
allow docker_elephdev_t self:capability { chown net_bind_service setgid setuid };
allow docker_elephdev_t self:tcp_socket { accept bind create listen setopt };

permissive docker_elephdev_t;

编译并加载策略模块

[root@localhost elephdev]# make -f /usr/share/selinux/devel/Makefile docker_elephdev.pp
Compiling targeted docker_elephdev module
/usr/bin/checkmodule:  loading policy configuration from tmp/docker_elephdev.tmp
/usr/bin/checkmodule:  policy configuration loaded
/usr/bin/checkmodule:  writing binary representation (version 19) to tmp/docker_elephdev.mod
Creating targeted docker_elephdev.pp policy package
rm tmp/docker_elephdev.mod tmp/docker_elephdev.mod.fc

[root@localhost elephdev]# semodule -i docker_elephdev.pp
[root@localhost elephdev]# semodule -l | grep docker_elephdev
docker_elephdev 1.1

启用强制 selinux

setenforce 1

清除audit.log并测试访问

echo > /var/log/audit/audit.log

curl localhost:80

此时已报错提示且访问成功,说明策略配置成功

开启策略强制模式(去除docker_elephdev.te中的)

policy_module(docker_elephdev, 1.2);

virt_sandbox_domain_template(docker_elephdev);

require {
  type node_t;
  type http_port_t;
  type docker_elephdev_t;
  class capability { chown net_bind_service setgid setuid };
  class tcp_socket { accept bind create listen name_bind node_bind setopt };
};

#============= docker_elephdev_t ==============
allow docker_elephdev_t http_port_t:tcp_socket name_bind;
allow docker_elephdev_t node_t:tcp_socket node_bind;
allow docker_elephdev_t self:capability { chown net_bind_service setgid setuid };
allow docker_elephdev_t self:tcp_socket { accept bind create listen setopt };

#permissive docker_elephdev_t;

重新编译并加载策略模块

$ make -f /usr/share/selinux/devel/Makefile docker_elephdev.pp 
$ semodule -i docker_elephdev.pp

这时访问 nginx 不通,查询容器运行日志发现 recv()权限不足

image.png

调整tcp_socket策略

再次访问

image.png

点赞(0)

评论列表 共有 0 评论

暂无评论

微信服务号

微信客服

淘宝店铺

support@elephdev.com

发表
评论
Go
顶部