云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

香港带宽_数据库的三级模式_高性价比

小七 141 0

BPF-被遗忘的字节码

每隔一段时间,我就会遇到一种晦涩难懂的计算机技术,这是一块隐藏的宝石,多年来,它几乎已经被遗忘了。这正是我对tcpdump工具和它的核心对应物包过滤器接口的看法。例如,假设您运行:$tcpdump-ni eth0 ip和udp以及端口53对我们大多数人来说,这个命令是纯粹的魔法,几乎没有人知道幕后发生了什么。这是可以理解的,不需要知道它是如何工作的:这个工具很好地完成了它的工作,它是描述性的,而且非常快速。在本文中,我将尝试解释tcpdump是如何工作的,以及我们如何使用它的副产品来帮助抵御每天攻击我们的包洪水。但首先,我们需要一点历史。历史背景自从工作站相互连接后,网络管理员就需要"查看"网络上流动的内容。当出现问题时,即使是在大多数情况下,嗅探网络流量的能力也是必要的基本调试。为此,操作系统开发了用于包嗅探的api。但是,由于没有真正的标准,每个操作系统都必须发明一个不同的API:Sun的STREAMS NIT、DEC的Ultrix包过滤器、SGI的Snoop和Xerox Alto都有CMU/Stanford包过滤器。这导致了许多并发症。更简单的api只是将所有的包复制到用户空间嗅探器中,这在繁忙的系统上导致了大量无用的工作。以前更复杂的api能够过滤包将它们传递给用户空间,但这通常是麻烦和缓慢的。1993年,当stevenmccanne和vanjacobson发表了一篇论文,介绍了在内核中过滤包的更好方法,他们称之为"BSD包过滤器"(BPF)。从那时起,BPF风靡全球,与libpcap和tcpdump一起成为网络调试的事实标准。Tcpdump解剖Tcpdump由三个逻辑部分组成:表达式解析器:Tcpdump首先解析一个可读的过滤器表达式,比如ip和udp以及端口53。结果是在一个特殊的最小字节码(BPF字节码)中生成一个短程序。BPF字节码(过滤程序)连接到网络抽头接口。最后,tcpdump pretty打印从网络点击。漂亮的印刷绝非易事,tcpdump需要了解许多网络协议才能做到这一点。表达式分析器给定一个包过滤表达式,tcpdump在BPF字节码中生成一个短程序。查看解析器运行的最简单方法是传递-d标志,这将生成一个可读的类似程序集的程序:$sudo tcpdump-p-ni eth0-d"ip和udp"(000)乳酸脱氢酶[12](001)jeq#0x800 jt 2 jf 5(002)后勤数据库[23](003)jeq#0x11 jt 4 jf 5(004)ret#65535号(005)返回0这个程序是这样写的:在偏移量12处从数据包加载半个字(2个字节)。检查值是否为0x0800,否则失败。这检查以太网帧上的IP包。在偏移量23处从数据包加载字节。这是"协议"字段9IP帧中的字节。检查值是否为0x11,即UDP协议号,否则失败。返回成功。数据包与规则匹配。在这里您可以找到程序集语法的完整文档。可读性较差的编译字节码用-ddd选项打印:$sudo tcpdump-p-ni eth0-ddd"ip和udp"| tr"\n"","6,40 0 0 12,21 0 3 2048,48 0 0 23,21 0 1 17,6 0 0 65535,6 0 0 0,内核APITcpdump可以通过请求SOCK_RAW socket来打开网络抽头,在几次神奇的setsockopt调用之后,可以使用SO_ATTACH_filter选项设置过滤器:sock=套接字(PF_PACKET,sock_RAW,htons(ETH_P_全部))...setsockopt(插座、SOL插座、附加过滤器等)从现在起,BPF过滤器将针对所有接收到的数据包运行一个网络接口,并且只有与该筛选器匹配的数据包传递给网络tap文件描述符。所有细节都在文件/网络/过滤器.txt文件。为了获得最佳性能零拷贝数据包/数据包接收环接口,尽管大多数人应该坚持高级libpcap API。BPF字节码实际上,Tcpdump要求内核在内核上下文。这听起来可能有风险,但实际上并非如此执行BPF字节码内核可确保它是安全的:所有的跳跃都是向前的,这保证了没有BPF程序中的任何循环。因此,它必须终止。所有指令,尤其是内存读取都是有效的,并且在范围内。单个BPF程序的指令数少于4096条。所有这些都保证了在内核上下文中执行的BPF程序能够快速运行并且永远不会无限循环。这意味着BPF程序并不是图灵完备的,但实际上它们对于这项工作有足够的表达能力,并且能够很好地处理包过滤。BPF的原始概念是在1993年描述的,多年来不需要更新。另一方面,Linux的实现正在稳步发展:最近推出了一个新的、闪亮的即时BPF编译器,几个月前还尝试将BPF程序集升级到64位形式。不仅是tcpdumpBPF是一种非常出色和灵活的包过滤方法。多年来,它在更多地方得到重用,现在Linux使用BPF过滤器来:tcpdump风格的包过滤用于流量成形(QoS)的"cls_bpf"分类器"seccomp bpf"系统调用筛选到沙盒应用程序"xt_bpf"iptables模块我们如何使用它CloudFlare每天都会处理大量的数据包洪流。对于我们来说,能够在恶意流量攻击应用程序之前很快地将其丢弃是非常重要的。不幸的是,在应用程序之前进行匹配并不容易。基本的iptables过滤,例如只查看源IP,随着洪水变得越来越复杂,就不起作用了。最接近我们需求的iptables模块是"xt_32",但它很难理解,而且有一定的局限性。尽管它通常是非常有用的,为了使它更容易,人们编写了规则生成器。但最适合我们的是Willem de Bruijn的"xp_bpf"iptables模块。有了它,我们可以根据任何BPF表达式匹配iptable规则。不幸的是,我们的BPF字节码变得非常复杂,不能再像普通的tcpdump表达式那样编写它了。相反,我们依赖于一个定制的BPF字节码,例如,这是一个匹配DNS查询的"xt_BPF"字节码网站":20级ldx 4*([0]和0xf)添加x税磅0:;匹配:076578616d706c6503636f6d00'\x07示例\x03com\x00'ld[x+0]jneq#0x07657861,磅1ld[x+4]jneq#0x6d706c65,磅力1ld[x+8]jneq#0x03636f6d,磅1后勤数据库[x+12]jneq#0x00,磅1返回1磅/平方英寸:返回0要编译它,我们使用tools/net目录中的工具:$bpf_asm drop_示例_com.bpf公司14,0 0 0 20177 0 0,12 0 0 0,7 0 0,64 0 0 0 0,21 0 7 124090465,64 0 4,21 0 5 1836084325,64 0 8,21 0 3 56848237,80 0 0 12,21 0 1 0,6 0 1,6 0 0 0 0 0最后,您可以这样应用规则:iptables-输入\-p udp—端口53\-m bpf—字节码"14,0 0 0 20177 0 0 0,12 0 0 0,7 0 0 0 0,64 0 0 0,21 0 7 124090465,64 0 4,21 0 5 1836084325,64 0 8,21 0 3 56848237,80 0 0 12,21 0 1 0,6 0 0 0 0,"\-j下降这是一个相当简单的规则,只在包中查找特定的字节。也可以使用"u32"或quot;string模块。但是"xt_bpf"给了我们更多的灵活性。例如,我们可以使规则不区分大小写:...磅0:;匹配:076578616d706c6503636f6d00'\x07示例\x03com\x00'ld[x+0]或#0x002020jneq#0x07657861,磅1ld[x+4]或#0x2020202jneq#0x6d706c65,磅力1ld[x+8]或#0x002020jneq#0x03636f6d,磅1后勤数据库jneq#0x00,磅1返回1...或者匹配所有子域"example.com网站":...磅0:;匹配:*后勤数据库[x+0]添加x添加1税;匹配:076578616d706c6503636f6d00'\x07示例\x03com\x00'ld[x+0]jneq#0x07657861,磅1ld[x+4]jneq#0x6d706c65,磅力1ld[x+8]jneq#0x03636f6d,磅1后勤数据库[x+12]jneq#0x00,磅1返回1...这些规则非常有用,它们允许我们精确定位恶意流量并尽早丢弃。就在过去的几周里,我们丢弃了870213889941个数据包,其中很少有BPF规则。最近在一次洪灾中,我们看到有410亿个数据包由于一个很好的规则而在一夜之间被丢弃。摘要正如Steven McCanne和Van Jacobson所想的那样,BPF仍然非常有用并且非常快速。即使没有启用bpfjit,我们也看不到应用复杂BPF规则的任何性能损失。我相信我们将来会使用更多的BPF过滤器来屏蔽恶意流量,并有更多的CPU来处理合法的请求。生成BPF程序集听起来很有趣吗?我们正在招聘有才华的开发人员,包括我们在伦敦的精英办公室。