seccomp(全称secure computing mode 安全计算模式)
linux kernel从2.6.23版本开始所支持的一种安全机制
在Linux系统里,大量的系统调用(systemcall)直接暴露给用户态程序。但是,并不是所有的系统调用都被需要,而且不安全的代码滥用系统调用会对系统造成安全威胁。通过seccomp,我们限制程序使用某些系统调用,这样可以减少系统的暴露面,使程序进入一种“安全”的状态。
官方说明 https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt
我们系统有300多个系统调用模块 syscall
查看命令运行过程调度了多少模块
root@vms82:/etc/apparmor.d# strace -fqc cat /etc/hosts
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
0.00 0.000000 0 3 read
0.00 0.000000 0 1 write
0.00 0.000000 0 6 close
0.00 0.000000 0 5 fstat
0.00 0.000000 0 7 mmap
0.00 0.000000 0 4 mprotect
0.00 0.000000 0 2 munmap
0.00 0.000000 0 3 brk
0.00 0.000000 0 3 3 access
0.00 0.000000 0 1 execve
0.00 0.000000 0 1 arch_prctl
0.00 0.000000 0 1 fadvise64
0.00 0.000000 0 4 openat
------ ----------- ----------- --------- --------- ----------------
100.00 0.000000 41 3 total
通过 Seccomp 方式禁用某些模块的调用
使用 Seccomp 限制容器的系统调用
1.Seccomp的规则
2.在docker条用Seccomp的规则
3.在K8s条用Seccomp的规则
docker运行时禁止调用的模块 300个中的44个被禁止调用
https://docs.docker.com/engine/security/seccomp/
The default seccomp profile provides a sane default for running containers with seccomp and disables around 44 system calls out of 300+. It is moderately protective while providing wide application compatibility. The default Docker profile can be found here.
Seccomp的规则
编写seccomp profile
cat aa1.json
{
"defaultAction": "SCMP_ACT_ALLOW" # 默认允许
}
cat bb.json
{
"defaultAction": "SCMP_ACT_ERRNO" # 默认禁止
}
SCMP_ACT_KILL: 当进程进行对应的系统调用时,内核发出SIGSYS信号终止该进程,该进程不会接受到这个信号
SCMP_ACT_TRAP: 当进程进行对应的系统调用时,该进程会接收到SIGSYS信号,并改变自身行为
SCMP_ACT_ERRNO: 当进程进行对应的系统调用时,系统调用失败,进程会接收到errno返回值
SCMP_ACT_TRACE: 当进程进行对应的系统调用时,进程会被跟踪
SCMP_ACT_ALLOW: 允许进程进行对应的系统调用行为
SCMP_ACT_LOG: 记录所有信息
在 docker 调用Seccomp的规则
官方json说明 https://raw.githubusercontent.com/moby/moby/master/profiles/seccomp/default.json
docker 默认使用的seccomp profile&
测试docker启动是调用其他规则文件
cat deny.json
{
"defaultAction": "SCMP_ACT_ERRNO"
}
root@vms82:~# docker run -dit --name=web --restart=always --security-opt seccomp=./deny.json nginx
d8e78cd1e6026692aee132fe9a7a72de448ee63c9990f300d8cd3506e7b1f76d
docker: Error response from daemon: cannot start a stopped process: unknown.
**这里由于deny.json 禁止了所有模块的调用,启动docker 报错 **
在 k8s 调用Seccomp的规则
因为我们的pod都是在worker上运行的,所以控制k8s 的seccomp 规则也是在对应worker上执行
pod在哪执行,seccomp就在哪设置
官方网站 https://kubernetes.io/zh/docs/tutorials/security/seccomp/
root@vms82:~/profiles# mkdir -p /var/lib/kubelet/seccomp/profiles
**默认读取的路径**
root@vms82:~/profiles# cd /var/lib/kubelet/seccomp/
root@vms82:~# curl -L -o profiles/audit.json https://k8s.io/examples/pods/security/seccomp/profiles/audit.json
{
"defaultAction": "SCMP_ACT_LOG" 记录所有信息
}
root@vms82:~# curl -L -o profiles/violation.json https://k8s.io/examples/pods/security/seccomp/profiles/violation.json
{
"defaultAction": "SCMP_ACT_ERRNO"
}
root@vms82:~# curl -L -o profiles/fine-grained.json https://k8s.io/examples/pods/security/seccomp/profiles/fine-grained.jso
root@vms82:/var/lib/kubelet/seccomp# ls profiles/
audit.json fine-grained.json violation.json
pod 的方式调用 master上编辑
apiVersion: v1
kind: Pod
metadata:
name: audit-pod
labels:
app: audit-pod
spec:
securityContext: # 新增调用
seccompProfile:
type: Localhost
localhostProfile: profiles/audit.json # 这边是相对路径,是在/var/lib/kubelet/seccomp/目录下的路径
containers:
- name: test-container
image: hashicorp/http-echo:0.2.3
args:
- "-text=just made some syscalls!"
securityContext:
allowPrivilegeEscalation: false # 是否允许提升权限
root@vms81:~/cks# kubectl apply -f pod1.yaml
root@vms81:~/cks# kubectl get pod
NAME READY STATUS RESTARTS AGE
audit-pod 1/1 Running 0 3s
root@vms81:~/cks# kubectl expose pod audit-pod --type NodePort --port 5678
service/audit-pod exposed
root@vms81:~/cks# kubectl get service audit-pod
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
audit-pod NodePort 10.105.28.175 <none> 5678:32303/TCP 4s
访问http://192.168.26.81:32303/ just made some syscalls!
sysdig(去监控pod的系统调用了哪些模块)
问题1: 我怎么知道pod 需要哪些系统调用
问题2 我该如何去监控pod的系统调用
1.安装sysdig
1.1 包安装
curl -s https://s3.amazonaws.com/download.draios.com/DRAIOS-GPG-KEY.public | sudo apt-key add -
sudo curl -s -o /etc/apt/sources.list.d/draios.list https://s3.amazonaws.com/download.draios.com/stable/deb/draios.list
sudo apt-get update
sudo apt-get -y install linux-headers-$(uname -r)
sudo apt-get -y install sysdig
2.2 容器运行
docker run -i -dt --name sysdig --restart=always --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro sysdig/sysdig
alias xxx='docker exec -it sysdig sysdig '
2.使用sysdig
sysdig 只能检测本机运行的进程或者容器
--list # 能检测的事件
sysdig -p "*%evt.time,%proc.name,%evt.type" container.id=5c9431eb8723
evt.num: 递增的事件号
evt.time: 事件发生的时间
evt.cpu: 事件被捕获时所在的 CPU,也就是系统调用是在哪个 CPU 执行的。比较上面的例子中,值 0 代表机器的第一个 CPU
proc.name: 生成事件的进程名字,也就是哪个进程在运行
thread.tid: 线程的 id,如果是单线程的程序,这也是进程的 pid
evt.dir: 事件的方向(direction),> 代表进入事件,< 代表退出事件
evt.type: 事件的名称,比如 open、stat等,一般是系统调用
evt.args: 事件的参数。如果是系统调用,这些对应着系统调用的参数
root@vms82:~# sysdig -p "*%evt.time,%proc.name,%evt.type" container.id=c360357a9658
17:08:55.892643107,http-echo,epoll_wait
17:08:55.892691150,http-echo,futex
17:08:55.892700598,http-echo,futex
17:08:55.892707352,http-echo,accept
17:08:55.892718243,http-echo,accept
17:08:55.892726440,http-echo,epoll_ctl
17:08:55.892729696,http-echo,epoll_ctl
17:08:55.892732185,http-echo,getsockname
17:08:55.892733057,http-echo,getsockname
17:08:55.892740151,http-echo,setsockopt
17:08:55.892741371,http-echo,setsockopt
17:08:55.892749619,http-echo,futex
17:08:55.892752491,http-echo,futex
17:08:55.892755250,http-echo,accept
17:08:55.892756889,http-echo,accept
17:08:55.892759024,http-echo,epoll_ctl
这样就查询到docker 运行特定pod 所需要调用的模块 写进 seccomp 来安全管控