C语言 即使设置了cap_net_raw,也无法在Linux容器中打开原始套接字



我正在运行一个代码,它在一个docker容器中打开一个原始套接字,kubernetes作为编排器。

下面是我的示例代码:
#include <stdio.h>  
#include <sys/socket.h>
#include <stdlib.h>
#include <errno.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
int main (void)
{  
        //Create a raw socket
        int s = socket (AF_INET, SOCK_RAW, IPPROTO_SCTP);
        if(s == -1)
        {
                perror("Failed to create socket");
                exit(1);
        }
}

在我的容器/pod中以非root用户运行代码时,我得到了这个错误。

./rawSocTest
Failed to create socket: Operation not permitted

这是很明显的,因为它需要root级别的特权才能打开原始套接字。我通过设置能力cap_net_raw来纠正这个问题。

getcap rawSocTest
rawSocTest = cap_net_raw+eip

现在,当我再次运行它。我得到一个不同的错误。

./rawSocTest
bash: ./rawSocTest: Permission denied

根据我的理解,设置能力应该已经解决了我的问题。我遗漏了什么吗?或者这是已知的容器限制吗?

提前感谢。

我解决了。我需要在kubernetes部署的容器安全上下文部分设置功能。我添加了NET_RAW功能以允许原始套接字创建。我的印象是,只要在构建过程中添加cap_net_raw功能就足够了。但我的理解原来是错误的。

我做了一些研究并清理了部署解决方案。我在pod安全策略的允许功能部分添加了NET_RAW。然后创建角色和角色绑定。通过角色绑定将其链接到我的pod将要部署的名称空间中的服务帐户。然后在pod部署中使用这个serviceAccount。我不确定这是不是一个好的解决方案。

我使用用户kubernetes-admin运行它

将容器定义的示例部署文件添加到前面所述的

apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd-deployment
  labels:
    app: httpd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpd
  template:
    metadata:
      labels:
        app: httpd
    spec:
      containers:
      - name: my-apache2
        image: docker.io/arunsippy12/my-apache2:latest
        securityContext:
         allowPrivilegeEscalation: true
         capabilities:
          add: ["NET_RAW"]
        ports:
        - containerPort: 80

你也可以参考k8s文档:https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

最新更新