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

游戏服务器_云虚拟主机购买_三重好礼

小七 141 0

介绍p0f BPF编译器

两年前,我们在博客中谈到了我们对BPF(BSD包过滤器)字节码的热爱。jim simonson的CC BY 2.0图像然后我们发布了一组用于为我们的产品iptables生成BPF规则的实用程序:bpftools。今天,我们非常高兴地开放了BPF工具的另一个组件:我们的p0f BPF编译器!满足p0fp0f是超人michalzalewski编写的工具。p0f的主要目的是被动地分析和分类任意网络流量。您可以向p0f提供任何数据包,作为回报,它将获得有关发送该数据包的操作系统的知识。吸引我们注意的一个特性是用于描述tcpsyn包的简洁而解释性的签名格式。p0f SYN签名是由冒号分隔的值组成的简单字符串。这个字符串以人类可读的方式清晰地描述了SYN包。这种格式非常聪明,跳过了不同的TCP字段,只关注SYN包的本质,从中提取感兴趣的部分。我们每天都在使用它来对CloudFlare的数据包进行分类,当我们成为SYN flood的目标时,我们会看到这些数据包。为了抵御SYN攻击,我们需要区分属于攻击一部分的数据包和合法流量。其中一种方法是使用p0f。我们希望对攻击包进行分级限制,并实际上优先处理其他(希望是合法的)攻击包。p0f SYN签名为我们提供了一种描述和区分不同类型SYN包的语言。例如,下面是一个典型的Linux SYN包的p0f SYN签名:4: 64:0:*:mss*10,6:mss,sok,ts,nop,ws:df,id+:0虽然这是一个Windows 7版本:4: 128:0:*:8192,8:mss、nop、ws、nop、nop,sok:测向,id+:0虽然还没有详细说明,但您可以清楚地看到这些操作系统之间存在差异。随着时间的推移,我们注意到攻击包通常是不同的。以下是两个攻击SYN包的示例:4: 255:0:0:*,0::ack+,uptr+:04: 64:0:*:65535,*:mss,无,无,无,sok:测向,id+:0您可以在p0f的自述文件和签名数据库中查看更多签名。并不总是能够完全区分攻击和有效数据包,但通常是这样。这个实现使我们开发了一个基于p0f SYN签名的攻击缓解工具。这样,我们就可以要求iptables只对选定的攻击特征码进行分级限制。但在讨论缓解措施之前,让我们先解释一下签名格式。CC BY-sa3.0图片,由Hyacinth在英语维基百科签名如前所述,p0f SYN签名是一个冒号分隔的字符串,包含以下部分:IP版本:第一个字段携带IP版本。允许值为4和6。初始TTL:假设实际上一个包不会跳转超过35个跃点,我们可以指定一个初始TTL ittl(通常值为255、128、64和32),并检查包的TTL是否在范围内(ittl,ittl-35)。IP选项长度:IP选项的长度。尽管在IP报头中看到选项并不常见(因此0是您在签名中看到的典型值),但该标准在IP有效负载之前定义了一个可变长度字段,在该字段中可以指定选项。也允许使用*值,表示"未指定"。MSS:TCP选项中指定的最大段大小。可以是常量或*。窗口大小:在TCP头中指定的窗口大小。它可以表示为:常数c,比如8192MSS的倍数,采用c*MSS格式常数的倍数,格式为%c任何值,如*窗口比例:在三次握手过程中指定的窗口比例。可以是常量或*。TCP选项布局:TCP选项在TCP包中的显示顺序的列表。怪癖:以逗号分隔的列表,列出了一个数据包的异常(例如,在非ACK数据包中设置的ACK号码)或不正确(例如格式错误的TCP选项)特征。有效负载类:TCP负载大小。可以是0(无数据)、+(1个或更多字节的数据)或*。TCP选项格式以下是常见的TCP选项:没有:没有手术mss:最大段大小ws:窗口缩放sok:允许选择性确认sack:选择性确认ts:时间戳eol+x:选项结束,后跟x字节的填充怪癖p0f描述了许多怪癖:df:IP头中不设置碎片位id+:设置df位,IP标识字段非零id-:未设置df位,IP标识为零ecn:设置显式拥塞标志0+:IP标头中的保留("必须为零")字段实际上不是零流:IPv6标头中的流标签为非零序号:序号为零ack+:ack字段为非零,但未设置ack标志ack-:ack字段为零,但ack标志已设置uptr+:URG字段非零,但URG标志未设置urgf+:URG标志已设置pushf+:设置推送标志ts1-:时间戳1为零ts2+:在SYN包中,时间戳2是非零的opt+:选项段中的非零数据exws:窗口比例因子过大(窗口比例大于14)linux:匹配从linux网络堆栈发送的数据包(IP.id字段等于TCP.ts1协议异或TCP.序列号). 请注意,这个怪癖不是原始p0f签名格式的一部分;我们决定添加它,因为我们发现它很有用。错误:TCP选项格式不正确减轻攻击给定一个p0f SYN签名,我们希望将其传递给iptables进行缓解。目前还不清楚如何做到这一点,但幸运的是,我们在BPF字节码方面经验丰富,因为我们已经在使用它来阻止dnsdos攻击。我们决定扩展我们的BPF基础设施来支持p0f,方法是构建一个工具,将p0f SYN签名编译成BPF字节码blob,该字节码blob被纳入到bpftools项目中。这使得我们可以使用一种简单易懂的语法来缓解问题,即p0f签名,并将其编译为iptables可以使用的非常有效的BPF形式。通过在iptables中以BPF的形式运行p0f签名,我们能够以非常高的速度识别攻击包并做出相应的反应。如果我们愿意的话,我们可以放弃他们或者限制利率。如何将p0f编译成BPF首先,您需要克隆cloudflare/bpftools GitHub存储库:$git克隆https://github.com/cloudflare/bpftools.git然后编译它:$cd bpf工具$制造这样,您就可以运行bpfgen p0f来生成与p0f签名匹配的BPF过滤器。下面是一个例子,我们获取一个Linux-TCP SYN包的p0f签名(我们之前介绍过的),通过使用bpftools,我们生成将匹配这类数据包的BPF字节码:$./bpfgen p0f--4:64:0:*:mss*10,6:mss,sok,ts,nop,ws:df,id+:056,0 0 0 0,48 0 0 8,37 52 0 64,37 0 51 29,48 0 0 0,84 0 0 15,21 0 48 5,48 0 0 9,21 0 46 6,40 0 0 6,69 44 0 8191177 0 0,72 0 0 14,2 0 0 8,72 0 0 22,36 0 0 10,7 0 0 0,96 0 8,29 0 36 0177 0 0 0,80 0 0 39,21 0 33 6,80 0 0 12116 0 4,21 0 30 10,80 0 0 20,21 0 28 2,80 0 0 24,21 0 26 4,80 0 0 26,21 0 24 8,80 0 0 36,21 0 22 1,80 0 0 37,21 0 20 3,48 0 0 6,69 0 18 64,69 17 0 128,40 0 0 0 2,2 0 0 1,48 0 0 0,84 0 0 15,36 0 0 4,7 0 0 0 0,96 0 0 1,28 0 0 0 0 0 5177 0 0 0 80 0 0 12116 0 0 4,36 0 0 4,7 0 0 0,96 0 0 5,29 0 1 0,6 0 0 65536,6 0 0 0,如果这看起来很神奇,请使用-s标志查看发生了什么的解释:$./bpfgen-s p0f--4:64:0:*:mss*10,6:mss,sok,ts,nop,ws:df,id+:0;ip:ip版本;(ip[8]29;((ip[0]&0xf)==5):ip选项长度==0;(tcp[14:2]==(tcp[22:2]*10)):win size==mss*10;(tcp[39:1]==6):获胜比例==6;((tcp[12]>>4)==10:tcp数据偏移量;(tcp[20]==2):olayout mss;(tcp[24]==4):olayout-sok;(tcp[26]==8):olayout ts;(tcp[36]==1):olayout否;(tcp[37]==3):olayout ws;((ip[6]和0x40)!=0):测向集;((ip[6]&0x80)==0:mbz零;((ip[2:2]-((ip[0]&0xf)*4)-((tcp[12]>>4)*4))==0:有效负载长度==0;;ipver=4;ip和(ip[8]29)和((ip[0]&0xf)==5)和(tcp[14:2]==(tcp[22:2]*10))和(tcp[39:1]==6)和(tcp[12]>>4)=10)和(tcp[20]==2)和(tcp[24]==4)和(tcp[26]==8)和(tcp[36]==1)和(tcp[37]==3)和((ip[6]&0x40)!=0)和((ip[6]&0x80)==0)和((ip[2:2]-((ip[0]&0xf)*4)-((tcp[12]>>4)*4))==0)1000英镑:ld#0x0l001:后勤数据库[8]l002:jgt#0x40、l055、l003l003:jgt#0x1d、l004、l055l004:后勤数据库[0]l005:和#0xf2006年l006:jeq#0x5,l007,l055l007:后勤数据库[9]2008年:jeq#0x6、l009、l0552009年:乳酸脱氢酶[6]2010年:jset#0x1FF,l055,l011l011:ldxb 4*([0]和0xf)2012年:乳酸脱氢酶[x+14]2013年:st M[8]2014年:乳酸脱氢酶[x+22]2015年:10倍2016年:税l017:ld M[8]2018年:杰克x、l019、l055l019:ldxb 4*([0]和0xf)l020:后勤数据库[x+39]l021:jeq#0x6,l022,l055l022:后勤数据库[x+12]l023:rsh#4l024:jeq#0xa、l025、l055l025:后勤数据库[x+20]l026:jeq#0x2,l027,l055l027:后勤数据库[x+24]l028:jeq#0x4,l029,l055l029:后勤数据库[x+26]l030:jeq#0x8,l031,l055l031:后勤数据库[x+36]l032:jeq#0x1、l033、l055l033:后勤数据库[x+37]l034年:jeq#0x3,l035,l055l035:后勤数据库[6]l036:jset#0x40,l037,l055l037年:jset#0x80,l055,l038l038年:乳酸脱氢酶[2]l039:st M[1]l040:后勤数据库[0]l041:和#0xfl042:mul#4l043号:税l044号:ld M[1]段l045:子xl046号:st M[5]l047:ldxb 4*([0]和0xf)l048号:后勤数据库[x+12]l049号:rsh#42050年:mul#4l051:税l052:ld M[5]l053:杰克x,l054,l0552054年:雷特655362055年:返回0示例运行例如,我们想阻止由hping3工具生成的SYN包。首先,我们需要识别p0f SYN签名。在这里,我们知道一个不经意间:4: 64:0:0:*,0::确认+:0(注意:除非使用-l0选项,否则hping3将发送设置了ACK号码的SYN包,很有趣,不是吗?)现在,我们可以使用BPF工具来获取BPF字节码,它将匹配淘气包:$./bpfgen p0f--4:64:0:0:*,0::ack+:039,0 0 0 0,48 0 0 8,37 35 0 64,37 0 34 29,48 0 0 0,84 0 0 15,21 0 31 5,48 0 0 9,21 0