1. 首页 > Linux教程 > 正文

Linux教程FG534-容器逃逸防护配置

内容简介:本文风哥教程参考Linux官方文档、Red Hat Enterprise Linux官方文档、Ansible Automation Platform官方文档、Docker官方文档、Kubernetes官方文档和Podman官方文档等内容,详细介绍了相关技术的配置和使用方法。

本文档

风哥提示:

介绍容器逃逸防护的配置方法和安全最佳实践。

Part01-容器安全基础

1.1 容器安全风险

# 检查容器运行状态
[root@fgedu-server ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1234567890ab nginx:latest “/docker-entrypoint.…” 2 hours ago Up 2 hours 0.0.0.0:80->80/tcp nginx-container

# 检查容器安全状态
[root@fgedu-server ~]# docker inspect –format='{{.State.Status}}’ nginx-container
running

# 检查容器特权模式
[root@fgedu-server ~]# docker inspect –format='{{.HostConfig.Privileged}}’ nginx-container
false

# 检查容器挂载
[root@fgedu-server ~]# docker inspect –format='{{.Mounts}}’ nginx-container
[{bind /host/path /container/path rw true rprivate}]

# 检查容器网络模式
[root@fgedu-server ~]# docker inspect –format='{{.HostConfig.NetworkMode}}’ nginx-container
bridge

Part02-容器逃逸防护配置

2.1 Docker安全配置

# 配置Docker守护进程
[root@fgedu-server ~]# cat > /etc/docker/daemon.json << 'EOF' { "icc": false, "userns-remap": "default", "live-restore": true, "no-new-privileges": true, "default-ulimits": { "nofile": { "Name": "nofile", "Hard": 65536, "Soft": 65536 } }, "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" }, "storage-driver": "overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ], "seccomp-profile": "/etc/docker/seccomp.json", "tls": true, "tlscacert": "/etc/docker/ca.pem", "tlscert": "/etc/docker/server.pem", "tlskey": "/etc/docker/server-key.pem", "tlsverify": true } EOF # 配置Seccomp配置文件 [root@fgedu-server ~]# cat > /etc/docker/seccomp.json << 'EOF' { "defaultAction": "SCMP_ACT_ERRNO", "architectures": ["SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32"], "syscalls": [ { "names": ["accept", "accept4", "access", "adjtimex", "alarm", "bind", "brk", "capget", "capset", "chdir", "chmod", "chown", "clock_getres", "clock_gettime", "clock_nanosleep", "close", "connect", "copy_file_range", "creat", "dup", "dup2", "dup3", "epoll_create", "epoll_create1", "epoll_ctl", "epoll_ctl_old", "epoll_pwait", "epoll_wait", "epoll_wait_old", "eventfd", "eventfd2", "execve", "execveat", "faccessat", "fadvise64", "fadvise64_64", "fallocate", "fanotify_init", "fanotify_mark", "fcntl", "fcntl64", "fdatasync", "fgetxattr", "flistxattr", "flock", "fork", "fstat", "fstat64", "fstatat64", "fsync", "ftruncate", "ftruncate64", "getcpu", "getcwd", "getdents", "getdents64", "getegid", "geteuid", "getgid", "getgroups", "getitimer", "getpeername", "getpgid", "getpid", "getppid", "getpriority", "getrandom", "getresgid", "getresuid", "getrlimit", "getrusage", "getsid", "getsockname", "getsockopt", "gettid", "gettimeofday", "getuid", "getxattr", "inotify_add_watch", "inotify_init", "inotify_init1", "inotify_rm_watch", "io_cancel", "io_destroy", "io_getevents", "io_setup", "io_submit", "kill", "lchown", "lgetxattr", "link", "linkat", "listen", "llistxattr", "lseek", "lstat", "lstat64", "mkdir", "mkdirat", "mknod", "mknodat", "mlock", "mlockall", "mmap", "mmap2", "mprotect", "mq_getsetattr", "mq_notify", "mq_open", "mq_timedreceive", "mq_timedsend", "mq_unlink", "munmap", "nanosleep", "newfstatat", "open", "openat", "pause", "pipe", "pipe2", "poll", "ppoll", "prctl", "pread64", "preadv", "prlimit64", "pselect6", "pwrite64", "pwritev", "read", "readahead", "readlink", "readlinkat", "readv", "recv", "recvfrom", "recvmsg", "recvmmsg", "rename", "renameat", "rmdir", "rt_sigaction", "rt_sigpending", "rt_sigprocmask", "rt_sigqueueinfo", "rt_sigsuspend", "rt_sigtimedwait", "rt_tgsigqueueinfo", "sched_getaffinity", "sched_getparam", "sched_getscheduler", "sched_rr_get_interval", "sched_setaffinity", "sched_setparam", "sched_setscheduler", "sched_yield", "select", "semctl", "semget", "semop", "send", "sendfile", "sendfile64", "sendmsg", "sendmmsg", "sendto", "setegid", "seteuid", "setgid", "setgroups", "setitimer", "setpgid", "setpriority", "setregid", "setresgid", "setresuid", "setreuid", "setrlimit", "setsid", "setsockopt", "setuid", "setxattr", "shutdown", "sigaltstack", "signalfd", "signalfd4", "socket", "socketcall", "socketpair", "stat", "stat64", "statfs", "statfs64", "symlink", "symlinkat", "sync", "sysinfo", "tee", "time", "timer_create", "timer_delete", "timer_getoverrun", "timer_gettime", "timer_settime", "times", "umask", "uname", "unlink", "unlinkat", "utime", "utimensat", "wait4", "waitid", "waitpid", "write", "writev"], "action": "SCMP_ACT_ALLOW" } ] } EOF # 重启Docker服务 [root@fgedu-server ~]# systemctl restart docker [root@fgedu-server ~]# systemctl enable docker # 验证Docker配置 [root@fgedu-server ~]# docker info | grep -E 'Security|Cgroup' Security Options: seccomp Profile: /etc/docker/seccomp.json userns no-new-privileges Cgroup Driver: cgroupfs Cgroup Version: 1

2.2 容器运行安全配置

# 安全运行容器(无特权模式)
[root@fgedu-server ~]# docker run -d \
–name nginx-secure \
–restart unless-stopped \
–cap-drop ALL \
–cap-add NET_BIND_SERVICE \
–security-opt no-new-privileges \
–security-opt seccomp=/etc/docker/seccomp.json \
–read-only \
–tmpfs /tmp \
–tmpfs /var/run \
–tmpfs /var/cache/nginx \
–mount type=volume,source=nginx-config,target=/etc/nginx/conf.d \
–mount type=volume,source=nginx-logs,target=/var/log/nginx \
-p 80:80 \
nginx:latest

# 检查容器安全配置
[root@fgedu-server ~]# docker inspect –format='{{.HostConfig.Privileged}}’ nginx-secure
false

[root@fgedu-server ~]# docker inspect –format='{{.HostConfig.CapDrop}}’ nginx-secure
[ALL]

[root@fgedu-server ~]# docker inspect –format='{{.HostConfig.CapAdd}}’ nginx-secure
[NET_BIND_SERVICE]

[root@fgedu-server ~]# docker inspect –format='{{.HostConfig.ReadonlyRootfs}}’ nginx-secure
true

# 限制容器资源
[root@fgedu-server ~]# docker run -d \
–name app-secure \
–restart unless-stopped \
–memory 512m \
–memory-swap 1g \
–cpus 0.5 \
–cpu-shares 512 \
–ulimit nproc=1000 \
–ulimit nofile=65536 \
–network bridge \
–hostname app-secure \
-p 8080:8080 \
myapp:latest

# 检查容器资源限制
[root@fgedu-server ~]# docker stats –no-stream nginx-secure
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
1234567890ab nginx-secure 0.00% 2.345MiB / 512MiB 0.46% 1.234kB / 5.678kB 0B / 0B 2

Part03-Kubernetes安全配置

3.1 Kubernetes Pod安全策略

# 创建Pod安全策略
[root@fgedu-master ~]# cat > pod-security-policy.yaml << 'EOF' apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: name: restricted annotations: seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'dofrom PG视频:www.itpux.comcker/default' apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' spec: privileged: false # Required to prevent escalations to root. allowPrivilegeEscalation: false # This is redundant with non-root + disallow privilege escalation, but we can provide it for defense in depth. requiredDropCapabilities: - ALL # Allow core volume types. volumes: - 'configMap' - 'emptyDir' - 'projected' - 'secret' - 'downwardAPI' # Assume that persistentVolumes set up by the cluster admin are safe to use. - 'persistentVolumeClaim' hostNetwork: false hostIPC: false hostPID: false runAsUser: # Require the container to run without root privileges. rule: 'MustRunAsNonRoot' seLinux: # This policy assumes the nodes are using AppArmor rather than SELinux. rule: 'RunAsAny' supplementalGroups: rule: 'MustRunAs' ranges: # Forbid adding the root group. - min: 1 max: 65535 fsGroup: rule: 'MustRunAs' ranges: # Forbid adding the root group. - min: 1 max: 65535 readOnlyRootFilesystem: false EOF # 应用Pod安全策略 [root@fgedu-master ~]# kubectl apply -f pod-security-policy.yaml # 创建RBAC权限 [root@fgedu-master ~]# cat > psp-rbac.yaml << 'EOF' apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: psp:restricted rules: - apiGroups: ['policy'] resources: ['podsecuritypolicies'] verbs: ['use'] resourceNames: ['restricted'] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: default:psp:restricted subjects: - kind: Group name: system:authenticated apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: psp:restricted apiGroup: rbac.authorization.k8s.io EOF [root@fgedu-master ~]# kubectl apply -f psp-rbac.yaml # 验证Pod安全策略 [root@fgedu-master ~]# kubectl get psp NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP READONLYROOTFS VOLUMES restricted false RunAsAny MustRunAsNonRoot MustRunAs MustRunAs false configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim

3.2 Kubernetes NetworkPolicy

# 创建网络策略
[root@fgedu-master ~]# cat > network-policy.yaml << 'EOF' apiVersion: networking.k8s.更多视频教程www.fgedu.net.cnio/v1 kind: NetworkPolicy metadata: name: default-deny namespace: default spec: podSelector: {} policyTypes: - Ingress - Egress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-nginx-ingress namespace: default spec: podSelector: matchLabels: app: nginx policyTypes: - Ingress ingress: - from: - ipBlock: cidr: 192.168.1.0/24 ports: - protocol: TCP port: 80 port: 443 --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-app-egress namespace: default spec: podSelector: matchLabels: app: myapp policyTypes: - Egress egress: - to: - podSelector: matchLabels: app: nginx ports: - protocol: TCP port: 80 - to: - podSelector: matchLabels: app: mysql ports: - protocol: TCP port: 3306 - to: - ipBlock: cidr: 8.8.8.8/32 ports: - protocol: UDP port: 53 EOF # 应用网络策略 [root@fgedu-master ~]# kubectl apply -f network-policy.yaml # 验证网络策略 [root@fgedu-master ~]# kubectl get networkpolicy NAME POD-SELECTOR AGE default-deny {} 1m allow-nginx-ingress app=nginx 1m allow-app-egress app=myapp 1m

Part04-容器安全监控

4.1 容器安全监控配置

# 安装容器安全监控工具
[root@fgedu-server ~]# dnf install -y audit audit-libs

# 配置容器审计
[root@fgedu-server ~]# cat > /etc/audit/rules.d/container.rules << 'EOF' # 容器相关审计规则 -a always,exit -F arch=b64 -S execve -F container=docker -k container-exec -a always,exit -F arch=b32 -S execve -F container=docker -k container-exec -a always,exit -F arch=b64 -S open,openat,openat2 -F container=docker -k container-file-access -a always,exit -F arch=b32 -S open,openat -F container=docker -k container-file-access -a always,exit -F arch=b64 -S mount -F container=docker -k container-mount -a always,exit -F arch=b32 -S mount -F container=docker -k container-mount EOF # 重启审计服务 [root@fgedu-server ~]# systemctl restart auditd [root@fgedu-server ~]# systemctl enable auditd # 检查审计日志 [root@fgedu-server ~]# ausearch -k container-exec # 安装Falco容器安全监控 [root@fgedu-server ~]# curl -s https://falco.org/repo/falcosecurity-3672BA8F.asc | apt-key add - echo "deb https://download.falco.org/packages/deb stable main" | tee -a /etc/apt/sources.list.d/falcosecurity.list apt-get update apt-get install -y falco # 配置Falco规则 [root@fgedu-server ~]# cat > /etc/falco/falco_rules.local.yaml << 'EOF' - rule: Container Escalation Attempt desc: Detect attempts to escalate privileges in containers condition: container and evt.type=execve and evt.args contains "sudo" or evt.args contains "su" output: "Container escalation attempt detected (user=%user.name container=%container.name command=%evt.args)" priority: CRITICAL - rule: Container Mount Host Directory desc: Detect containers mounting host directories condition: container and evt.type=mount and evt.args contains "/host" output: "Container mounting host directory detected (container=%container.name mount=%evt.args)" priority: WARNING - rule: Container Network Connection desc: Detect network connections from containers condition: container and evt.type=connect and evt.args contains "127.0.0.1" output: "Container connecting to host detected (container=%container.name connection=%evt.args)" priority: WARNING EOF # 启动Falco服务 [root@fgedu-server ~]# systemctl start falco [root@fgedu-server ~]# systemctl enable falco # 检查Falco日志 [root@fgedu-server ~]# tail -f /var/log/falco.log

Part05-容器安全最佳实践

5.1 容器镜像安全

# 扫描容器镜像
[root@fgedu-server ~]# docker scan nginx:latest

# 使用安全的基础镜像
[root@fgedu-server ~]# docker pull alpine:latest

# 构建安全的Dockerfile
[root@fgedu-server ~]# cat > Dockerfile << 'EOF' FROM alpine:latest # 安装必要的包 RUN apk add --no-cache nginx # 创建非root用户 RUN adduser -D -u 1000 nginx-user # 设置工作目录 WORKDIR /app # 复制配置文件 COPY nginx.conf /etc/nginx/nginx.conf # 更改权限 RUN chown -R nginx-user:nginx-user /app /etc/nginx # 切换到非root用户 USER nginx-user # 暴露端口 EXPOSE 8080 # 启动服务 CMD ["nginx", "-g", "daemon off;"] EOF # 构建镜像 [root@fgedu-server ~]# docker build -t mynginx:secure . # 验证镜像 [root@fgedu-server ~]# docker inspect --format='{{.Config.User}}' mynginx:secure nginx-user # 推送镜像到私有仓库 [root@fgedu-server ~]# docker tag mynginx:secure harbor.fgedu.net.cn/library/mynginx:secure [root@fgedu-server ~]# docker push harbor.fgedu.net.cn/library/mynginx:secure

5.2 容器运行时安全

# 启用Docker内容信任
[root@fgedu-server ~]# export DOCKER_CONTENT_TRUST=1

# 签名容器镜像
[root@fgedu-server ~]# doc学习交流加群风哥微信: itpux-comker trust sign harbor.fgedu.net.cn/library/mynginx:secure

# 验证签名镜像
[root@fgedu-server ~]# docker trust inspect –pretty harbor.fgedu.net.cn/library/mynginx:secure

# 使用Podman无守护进程模式
[root@fgedu-server ~]# podman run -d \
–name nginx-podman \
–security-opt label=type:container_runtime_t \
–read-only \
-p 8081:80 \
nginx:latest

# 检查Podman容器
[root@fgedu-server ~]# podman inspect –format='{{.Config.User}}’ nginx-podman
root

# 配置Rootless Podman
[root@fgedu-server ~]# usermod –add-subuids 100000-165535 –add-subgids 100000-165535 fgedu
[root@fgedu-server ~]# su – fgedu
[fgedu@fgedu-server ~]$ podman run -d –name nginx-rootless -p 8082:80 nginx:latest

风哥针对容器逃逸防护建议:

  • 使用最小权限原则运行容器
  • 禁用特权模式
  • 使用只读文件系统
  • 限制容器资源
  • 配置Seccomp和AppArmor
  • 使用网络策略限制容器通信
  • 定期扫描容器镜像漏洞
  • 监控容器行为异常
  • 使用签名验证容器镜像
  • 实施Pod安全策略

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息