防火墙导致Linux发送网络报文出现errno等于1的错误码

    服务启动过程中,偶然间看到udp socket发送报文,出现 errno == 1 错误码。

    错误码对应的描述:

  1.    zh_CN: 不允许的操作
  2.    en_US: Operation not permitted

  出现错误的代码,在失败后,下次定时尝试重作,无权限问题不出现了,具有偶发性!

分析


   在服务器启动过程中发送网络报文,出现errno == 1错误,最开始执拗于udp socket是无连接的协议,只要目的地址正确,而且有响应的路由,都应该可以发送的,觉得不应该出现此类错误?

   而且,在网上搜索,此类错误码等于‘1’的场景描述也较少。

   为了具体而微地解剖这个问题,特意从网上复制了一个udp socket的例子,进行发送接口不同的异常参数设置,发现udp socket的发送接口函数对于异常参数输入,虽然得到的errno的值是各不一样的,但就是不是为errno == 1的错误码!

   积累了两天的观察和对比分析,以及基于过去对于k8s  service IP是通过iptables进行NAT转换到达后端POD IP; 如果通过tcpdump抓取报文,就会发现访问service IP的报文,实际上被转换为POD IP投送过去,所以,k8s的很多网络问题,必须首先保证POD网络,或k8s节点网络的互通!

   猜测在启动节点,k8s对于iptables nat规则设置可能处于中间态,在NAT规则未设置完全的情况下,对于某些service IP网络服务Endpoint进行访问,发送网络报文,就会在防火墙层面拒绝了,进而,socket接口返回错误码,出现无权限提示!

  有了怀疑的方向和测试程序在手,就可以进一步验证是否如此!

  通过防火墙命令设置测试程序的目的port被不允许,则在测试程序中,就打印了‘permission not allowed’的错误提示:)

 知道的原因,就可以根据这个原因,采取一些规避的措施了!

  一切都得到了解释,是如此的欢快!!!

再次补充证明材料


# 如果在启动过程持续观察k8s节点,对于POD IP Endpoint的限制变化
# 就可以看出k8s在这个错误码场景的嫌疑

while true; do iptables -t filter -S | grep endpoint_keyword; echo 'sleep a while'; sleep 1; done

后来,觉得应该可以通过持续观察防火墙设置,发现k8s对于防火墙规则的修改过程,通过循环脚本执行了下,果然如此!

Linux UDP Socket 编程例子


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char * argv[]) {

    int client_sockfd;
    int len;
    char buf[BUFSIZ]            = {}; //数据传送的缓冲区
   
    struct sockaddr_in remote_addr; //服务器端网络地址结构体
    remote_addr.sin_family      = AF_INET; //设置为IP通信
    remote_addr.sin_addr.s_addr = inet_addr("172.16.6.1"); //服务器IP地址
    remote_addr.sin_port        = htons(8000); //服务器端口号

    /*创建客户端套接字--IPv4协议,面向无连接通信,UDP协议*/
    if ((client_sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
        printf("\n create socket error");
        return 1;
    }

    strcpy(buf, "This is a test message"); // 发送的内容
    printf("sending: '%s'\n", buf);

    /*向服务器发送数据包;如果出现安全因素阻拦,例如,防火墙,则出现errno == 1 的错误码*/

    if ((len = sendto(client_sockfd, buf, strlen(buf), 0, (struct sockaddr * ) &remote_addr, sizeof(struct sockaddr))) < 0) {
        char szErrno[128];
        strerror_r(errno, szErrno, sizeof(szErrno));
        printf("\n sendto error, errno:%d, %s", errno, szErrno);
        return 1;
    }

    printf("\n close udp socket fd\n");
    /*关闭套接字*/
    close(client_sockfd);

    return 0;
}

你可能感兴趣的:(c&c++技术,笔记,linux,errno,不允许的操作,not,permitted)