大家好,最近遇到一个奇葩的网络问题,分享给大家,看完一定会觉得很奇葩。

问题现象

客户反馈有一个服务器端S,两个客户端端C1,C2,S的iptables规则对C1,C2都是放通的,但是C2无法连接上S,客户很着急,催我们尽快解决。

这里解释一下,iptables规则是防火墙规则,是Linux系统实现防火墙一个应用层配置工具,依赖于Linux内核网络的netfiler框架。这里简单介绍一下问题的背景知识(后面网络硬核系列文章会详细介绍)。

背景知识

netfilter是Linux内核内部的一个框架,该框架允许内核模块在Linux网络中的不同位置注册的堆栈函数。然后对于遍历Linux网络内部相互链接的每个数据包,将调用已注册的一部分函数。

netfilter / iptables能做什么?

  • 建立基于无状态和有状态数据包过滤的互联网防火墙

  • 部署高可用性的无状态和有状态防火墙部署

  • 如果您没有足够的公共IP地址,请使用NAT和伪装来共享Internet访问

  • 使用NAT来实现透明代理

  • 协助tc和iproute2系统用于内置复杂的QoS和策略路由器

  • 进行进一步的数据包处理(处理),例如更改IP标头的TOS / DSCP / ECN位

在内核协议栈位置大概是这样:

netfilter XML的位置:

5个HOOK点:

PREROUTING :数据包进入路由表之前

INPUT :通过路由表后目的地为本机

FORWARD :通过路由表后,目的地不为本机

输出:由本机产生,超出发送

POSTROUTIONG :发送到网卡接口之前。

每个HOOK点都会执行一些函数,大致分为以下几个表:

NAT表:用于实现nat功能,端口映射,地址映射等

mangle表:用于修改报文,例如更改IP标头的TOS / DSCP / ECN位

filter表:用来过滤报文

raw表:用来预先标记报文不走一些流程(而不需要建会话)

如果不熟悉不要紧,只是知道在协议栈收发关键入口(进入,转发,发出)注册一些hook函数,然后报文会通过hook内部函数处理,而这些hook的动作(函数)是需要一个iptables的工具下发配置生成的。

iptables是您下发规则的用户状态工具。IP表中的每个规则都由多个分类器(iptables匹配项)和一个连接的动作(iptables目标)组成。命令格式可参考下图,详细可以参考手册:

这里记住两个动作就行了,ACCEPT表示通过,DROP表示丢掉;

内核里面看到的规则大概是这个样子:

主要特点

  • 无状态数据包过滤(IPv4和IPv6)

  • 有状态的数据包过滤(IPv4和IPv6)

  • 各种网络地址和端口转换,例如NAT / NAPT(IPv4和IPv6)

  • 灵活可扩展的基础架构

  • 第三方扩展的API

所以大多数公司会基于netfilter框架实现软件防火墙(安全组)和软件虚拟交换机(vswitch,类似ovs)。

好,背景简单介绍完了,如果不是很理解,后面会详细介绍的,来看一下这个客户实际问题。

分析过程

1.先了解网络拓扑

客户网络拓扑是相当的简单,就是同网段下client机器访问服务器,一台可以访问,一台不可以。

2.查看配置是否丢失

对于服务端10.0.0.3而言,两台客户端机器到本机的iptable规则都是一样的。但10.0.2.8到10.0.0.3的20202端口的syn包被丢了,而10.0.2.7到10.0.0.3的20202范围的访问是正常的。

配置都在,需要进一步分析。

3.抓包分析

client端发起telnet命令连接服务器,服务器按client ip抓包,发现只有TCP SYN请求过来,根本回包,确实是本机OS内丢包导致无法正常连接:

通过netstat可以查看服务器TCP统计信息:连接数不高,没有TCP丢包统计信息,结合10.0.0.2.7客户端可以访问,进一步确认,放通安全组后,10.0.2.8到10.0.0.3的icmp包也没有回,这个时候和TCP协议处理没有本质关系了。

4.追踪内核丢包调用栈

报文如果被内核破坏后,正常情况下调用kfree_skb函数,内核通过kfree_skb释放skb,kfree_skb函数中已经埋下了跟踪点,并通过__builtin_return_address(0)记录下了调用kfree_skb的函数地址并传给给位置参数,可以通过systemtap脚本,追踪kfree_skb这个跟踪点,找到匹配的丢包并输出对应的变量:

/ **
* kfree_skb-释放一个sk_buff
* @skb:释放缓冲区
*
*删除对缓冲区的引用,并在使用计数
达到零时释放它。
* /
void  kfree_skb ( struct sk_buff * skb )
{如果 (不太可能(! skb ))返回; 如果 (可能(atomic_read (& SKB - >用户) ==  1 ))smp_rmb (); 否则 ,如果 (可能(!atomic_dec_and_test (与SKB - >用户)))回报; trace_kfree_skb ( SKB , __builtin_return_address (0 )); __kfree_skb ( skb );
}
EXPORT_SYMBOL ( kfree_skb ); / *
* Tracepoint免费提供一个sk_buff:
* /
TRACE_EVENT ( kfree_skb ,TP_PROTO ( struct sk_buff * skb , void  * location ),TP_ARGS (skb , location ),TP_STRUCT__entry (__field (        void  * ,          skbaddr          )__field (        void  * ,          location         )__field (         unsigned short , protocol         )),TP_fast_assign (__entry- > skbaddr = skb ;__entry- > location = location ;__entry- >协议=  ntohs ( skb- > protocol ); ),TP_printk (“ skbaddr =%p协议=%u location =%p” ,__entry- > skbaddr , __entry- >协议, __entry- > location )
));

systemtap脚本:

#猫mydropwatch 。STP
#/! USR /斌/科技咨询-所有-模块
%{
#包括< Linux的/内核。h >#include < linux / net 。h >#include < linux / textsearch 。h >#include < net /校验和。h >#include < linux /DMA -映射。h >#include < linux / netdev_features 。h >#include < linux / skbuff 。h >#include < uapi / linux / ip 。h >#include < uapi / linux / udp 。h >#include < uapi / linux / tcp 。h >
%}
################################################ ###########
dropwatch2 。STP
#示例脚本来模仿行为的的dropwatch效用
#报告每隔5秒与时间戳
#使用: STAP -摹-所有-模块mydropwatch 。stp //-g表示大师模式
########################################## ##################
function get_packet_info :字符串( skb : long )
%{int ret =-1 ; unsigned int src_port =  0 ; unsigned int dest_port =  0 ; struct udphdr * udp_header ; struct tcphdr * tcp_header ; struct sk_buff * skb =  ( struct sk_buff * ) STAP_ARG_skb ; struct iphdr * ip_header ; 无符号整数src_ip = 0 , dest_ip = 0 ; 如果(! skb ){转到EXIT_F ; }ip_header =  ( struct iphdr * )skb_network_header ( skb ); 如果(! ip_header ){转到EXIT_F ; }src_ip =  ( unsigned int ) ip_header- > saddr ; dest_ip =  ( unsigned int ) ip_header- > daddr ;
#如果 0如果 ( IP_HEADER - >协议== 17 ) {udp_header =  ( struct udphdr * )skb_transport_header ( skb ); src_port =  ( unsigned int )ntohs ( udp_header- > source ); }  else  if  ( ip_header- > protocol ==  6 ) {tcp_header =  ( struct tcphdr * )skb_transport_header ( skb );src_port =  ( unsigned int )ntohs ( tcp_header- > source ); dest_port =  ( unsigned int )ntohs ( tcp_header- > dest ); } printk ( KERN_INFO “输出数据包信息:src ip:%u,src端口:%u; dest ip:%u,dest端口:%u; proto:%u \ n” , src_ip , src_port , dest_ip , dest_port , ip_header ->协议);
#万一// printk(KERN_DEBUG“ IP地址=%pI4 DEST =%pI4 \ n”,&src_ip,&dest_ip);
EXIT_F :snprintf ( STAP_RETVALUE , MAXSTRINGLEN , “%d。%d。%d。%d” ,( unsigned int )(( unsigned char * )& src_ip )[ 0 ],( unsigned int )(( unsigned char * )& src_ip )[ 1 ],( unsigned int )(( unsigned char * )& src_ip )[ 2 ],( unsigned int )((unsigned char * )& src_ip )[ 3 ]);
%}
#保留放置点列表的数组,我们可以找到
全局位置
#注意,当我们打开和关闭监视器时,
探针开始{  printf (“监视丢弃的数据包\ n” ) }
探针结束{  printf (“停止丢弃的数据包监视器\ n“ ) }
#为在
探针内核处放置的每个位置增加一个放置计数器。跟踪(“ kfree_skb” ) {SrcIp = get_packet_info ( $ skb )//if(SrcIp== "10.0.2.8") //数据包的src ip为“ 10.0.2.8” // printf(“ srcip:%s \ r \ n”,SrcIp)如果( SrcIp == @ 1 ){位置[ $ location ]  <<<  1  // systemtap统计聚合if(symname($ location)==“ nf_hook_slow”)//如果nf_hook_slow函数print_backtrace()调用了kfree_skb,则转储回溯。}
}
#每隔5秒报告我们的墨滴位置
探测定时器。秒(5)
{
// printf(“ \ n ===%s === \ n”,ctime(gettimeofday_s()))foreach  ( l在位置- ) { printf (“ \ n ===%s === \ n“ , ctime (gettimeofday_s ()))printf (”%d个数据包在%x(%s)处丢弃\ n“ ,@ count ( location [ l ]), l , symname ( l ))}删除位置
}## #mydropwatch 。stp结束###

执行方法:

stap -g -v --all-modules mydropwatch.stp 10.0.2.8

执行命令后,对应输出:

从调用栈可知是在ip_local_deliver函数时因为iptables规则导致的丢包,结合内核代码:

nf_hook_slow + 0xf3对于代码188行(先找到对应内核版本的源代码,用崩溃工具打开对应内核版本的vmlinux,反汇编函数查看指令布局,定位到源代码行号):

可知是在INPUT链丢的包,但是检查了mangle,nat,filter等表的INPUT链,可以其他拖放规则,更改策略可以接受,所以这里有点奇怪。

为了确定是否真的匹配上了ACCEPT规则,我在规则前面添加了打印日志规则,报文匹配后会打印日志出来:

显示确认一下:

通过触发请求,匹配上了第一个打印日志的规则,10.0.2.8白名单规则命中计数有添加,而第二日志规则没有匹配上,说明报文命中了白名单规则,报文可以通过防火墙:

但为什么服务端没有回syn + ack呢,是不是某种场景触发了netfiler框架的错误,假装接受,实际上把报文悄悄地给丢了?结合报文和系统环境,看了几遍netfiler代码后,没有抛光啥问题,清空iptables规则,停了firewalld,依然丢了,还是丢在nf_hook_ slow,也越来越证明不是普通iptables规则导致的。

如果要继续排查,是不是得遍历下内核数据结构,看看是不是列表坏掉了,由于时间比较紧迫,遍历内核数据结构有点麻烦,需要找到netfiler hook表起始地址,再结合数据结构算出偏偏移,一步一步遍历内存,由于可以通过器可以重启(业务已经不正常了),客户相信,重启可以比我们重新解决问题,还是重启大法好,但不幸的是,机器重启完后没有恢复,问题依然存在,这个就有意思了。

5.排查其他netfilter hook(钩子)函数

那么,有没有可能是有其他内核模块在INPUT链中注册了hook函数,drop了对应的包呢?

背景知识

crash是redhat的工程师开发的,主要用于离线分析Linux内核转存文件,它集成了gdb工具,功能非常强大。生成的转存文件格式,如kdump,LKCD,netdump和diskdump,而且还可以分析虚拟机Xen和Kvm上生成的内核转存文件。内核映象存放在/ proc / kcore。

5.1。从nf_hooks找到ipv4 INPUT链的挂钩

内核hook的组织:

那么对于NFPROTO_IPV4协议的NF_INET_LOCAL_IN链,我们可以找到其链表地址:

可以看到有一个非标模块resguard_linux日期了非标钩子函数net_hook_in_v4,反汇编net_hook_in_v4函数,可知其有一些白名单/黑名单之类的检查:

由此基本可以确定是这个模块的安全功能利用netfilter hook拦截了访问。

他大爷的,还真的注册了nf hook 

但要客户认账,还得证明这个包就是这个hook函数丢的,其实已经差不多了。

5.2。如何证明是net_hook_in_v4返回NF_DROP(0x0)导致的丢包?

可以结合systemtap得到skb地址,然后通过perf probe抓取net_hook_in_v4和nf_iterate的返回值:

脚本:

运行结果:

由此可以抛光bb2100最后的这个skb是因为nf_hook_in_v4导致的丢包。

网上搜索可知该第三方安全模块疑似云锁类别软件提供,他可以通过ip黑白列表控制对网站的访问。

问题算术终于结束了,想着之前催得那么急,真想在线战斗一下,而客户是大爷,不敢想,不敢想

可以学到什么

1.大致了解Linux防火墙实现框架:netfilter + iptables;

2.通过systemtap脚本追踪内核协议栈丢包特定信息;

3.如何通过尺寸函数和指令替换找到源代码信息;

4.一些丢包排查思路;

5.了解一些工具使用,有时会系统点击,崩溃,iptables,tcpdump等;

一个奇葩的网络问题,把技术砖家“搞蒙了”相关推荐

  1. 一个奇葩的网络问题,把技术砖家搞蒙了

    大家好,最近遇到一个奇葩的网络问题,分享给大家,看完一定会觉得很奇葩. 问题现象 客户反馈有一个server端S, 两个client端C1, C2, S的iptables规则对C1, C2都是放通的, ...

  2. IT真的不行了吗?下一个风口在哪里?IT技术人搞钱攻略!

    所有的理想最后还是要落到实处,无论是学技术或者搞其他什么事情,最后还是要想办法变现. 最近都在说大环境不好,这个问题显而易见,热搜上阿里裁员上万人,淘宝天猫合并,是它利润不好嘛? 互联网行业繁荣不再, ...

  3. 网络故障的技术一些东东

    IT 精品杂志 一个互联网的时代,一个知识以几何速度增长的时代,当人们在讨论知识的快速扩展会给人们带来什么的时候,知识的增长的速度不为人类意识的缓慢而依旧快速增加着.我们能做的有什么--,只能是接受, ...

  4. 5G NGC — 关键技术 — 网络切片 — 底层技术支撑

    目录 文章目录 目录 网络切片的特性 网络切片的底层技术支撑 - NFV/SDN 网络切片的特性 隔离性:不同的网络切片之间互相隔离,一个切片的异常不会影响到其他的切片. 虚拟化:网络切片是在物理网络 ...

  5. 【复杂网络】用户画像不应脱离社会关系,谈复杂网络的关键技术和应用实践

    原文链接:http://www.sohu.com/a/119515569_470008 本文是11月17日大数据杂谈群分享的内容. 关注"大数据杂谈"公众号,点击"加群学 ...

  6. WE CAN:全球智能路由网络 | 体验共享技术专题

    导读:为了支持网易云信在娱乐社交领域打造融合通信云行业第一的品牌战略目标,建设覆盖全球的低延迟大规模传输网络,WE-CAN 在优化体验共享,降低传输延迟方面做了很多工作,本文将介绍 WE-CAN 全球 ...

  7. 应对不良网络文化的技术之一——网络信息抽取技术

    1     引言 2008年1月17日,中国互联网络信息中心(CNNIC)发布了<第21次中国互联网络发展状况统计报告>[1],报告显示: (1) 截至2007年12月,网民数已增至2.1 ...

  8. 转:Linux网络IO并行化技术概览

    转:http://codinginet.com/articles/view/201605-linux_net_parallel?simple=1&from=timeline&isapp ...

  9. 【Python笔记】网络爬虫——常用技术

    网络爬虫常用技术 Python 的网络请求 1.urllib 模块 2.urllib3 模块 3.requests 模块 请求 headers 处理 网络超时 代理服务 HTML解析之 Beautif ...

最新文章

  1. 008_HttpServletRequest对象
  2. JZOJ 5478. 【NOIP2017提高组正式赛】列队
  3. tensorflow随笔-队列管理器QueueRunner-生产者与消费者
  4. 「Vueconf」探索 Vue3 中 的 JSX
  5. [转] java.nio.ByteBuffer中flip、rewind、clear方法的区别
  6. Android基础知识之智能指针:强指针和弱指针
  7. 一款原型设计软件——墨刀的介绍
  8. 鸿蒙系统自主研发,华为鸿蒙OS系统规划曝光,原来国产自主研发系统已经如此强大...
  9. (转)CocosCreator零基础制作游戏《极限跳跃》五、制作游戏主场景背景滚动
  10. AndroidStudio 集成海康威视 Android SDK,集成萤石Android SDK
  11. web前端设计与开发,css段落首行缩进2字符怎么设置
  12. 荣耀/华为电脑安装重新安装电脑管家实现跟华为手机多屏协同(666)
  13. 使用计算机时应先按,自考试题及答案《计算机应用基础》
  14. 朗文词典第五版安装详细步骤
  15. USACO 1359. 城堡(并查集)
  16. 玄铁C910内存管理与地址转换技术
  17. 公关作用下的品牌建设
  18. db2 replace函数的用法_48R软件数据的基本处理之删除重复数据(duplicated()、unique()、distinct()函数)...
  19. 推荐六款图片素材网站
  20. 华硕笔记本安装linux失败

热门文章

  1. doraemon的python 从计算机基础到面向对象的笔记(加面试题)
  2. cesium turf.js展示两多边形相交区域
  3. Android 桌面工具,安卓怎样添加桌面工具
  4. 微软股价史高,不干了这碗CEO亲自熬的鸡汤?
  5. How to ask questions?|提问的智慧
  6. Description 现举行新生歌手大赛,评分规则是这样的:一共有10个评委给每个歌手打分,分数采用 百分制,算分时去掉一个最高分,去掉一个最低分,取其余8个评委的平均分作为歌手的 得分。现有多个歌
  7. 【平面设计基础】12:ACR调色
  8. 【我的故事】一个还不成熟的女程序员的苦恼
  9. 电视机防近视预警系统c语言,预防近视、提升视力 TCL儿童电视亮相重庆
  10. 消费服务平台“小黑鱼科技”完成5000万美金融资,资方含光速美国、晨兴资本等多家知名机构...