应用办公生活信息教育商业
投稿投诉
商业财经
汽车智能
教育国际
房产环球
信息数码
热点科技
生活手机
晨报新闻
办公软件
科学动态
应用生物
体育时事

dpvssynproxy

  TCP协议开辟了一个比较大的内存空间请求连接队列来存储连接请求块,当SYN请求不断增加,请求连接数目到达上限时,会致使系统丢弃SYN连接请求。SYNcookies技术就可以使服务器在半连接队列已满的情况下仍能处理新的SYN请求
  当半连接队列满时,SYNcookies并不丢弃SYN请求,而是通过加密技术来标识半连接状态。在TCP实现中,当收到客户端的SYN请求时,服务器需回复SYNACK包给客户端,然后客户端再发送确认包给服务器。通常服务器的初始序列号是由服务器按照一定的规律计算得到或采用随机数,而在SYNcookies中,服务器的初始序列号是由客户端IP地址,客户端端口,服务器IP地址和服务器端口,接收到的客户端初始序列号以及其他一些安全数值进行hash运算,并加密后得到的,称之为cookie。当服务器遭受SYN攻击使得请求连接队列满时,服务器并不拒绝新的SYN请求,而是回复一个初始化序列号为cookie的SYN包给客户端,如果收到客户端的ACK段,服务器将客户端的ACK序列号减1得到的值,与用上述那些元素hash运算得到的值比较,如果相等,直接完成三次握手,注意:此时并不必查看此连接是否属于请求连接队列
  linux内核启用SYNcookies是通过在启动环境中设置以下命令来完成
  echo1procsysnetipv4tcpsyncookies三次握手示例图
  synproxy说明
  client发送syn,LB代理了第一次握手,不转发给rs。LB返回synack数据包时,seq由syncookies算法生成,并且将rcvwnd设置为0,不允许在握手阶段携带数据,由此得知不支持tcpfastopen当client返回ack时,反解seq,如果与syncookies算法匹配,那么就是正常流量。此时LB与后端RS开启三次握手,并透传winsize,由于经过LB代理,还需要记录seq差值delta数据交互通信,lb除了正常的fullnat工作,还要补偿seqdelta连接关闭,正常清理client第一次握手dpvsprerouting
  staticintdpvsprerouting(voidpriv,structrtembufmbuf,conststructinethookstatestate,intaf){。。。Synproxy:defencesynflood如果是传输层协议是TCP,synproxy处理,此处处理client端第一次握手(syn)包的处理if(IPPROTOTCPiph。proto){intvINETACCEPT;if(0dpvssynproxysynrcv(af,mbuf,iph,v))returnv;}returnINETACCEPT;
  }dpvssynproxysynrcv
  处理client侧第一次握手数据包(syn包)Synproxystep1logic:receiveclientsSyn。Checkifsynproxyisenabledforthisskb,andsendsynackbackSynproxyisenabledwhen:mbufisasynpacket,andtheserviceissynproxyenable,andipvstodropreturnfasle(notsupportednow)return0meansthecallershouldreturnatonceanduseverdictasreturnvalue,return1fornothing。intdpvssynproxysynrcv(intaf,structrtembufmbuf,conststructdpvsiphdriph,intverdict){intret;structdpvsservicesvcNULL;structtcphdrth,tcph;structdpvssynproxyopttcpopt;structnetifportdev;structetherhdreth;structetheraddrethaddr;th指向tcp首部thmbufheaderpointer(mbuf,iphlen,sizeof(tcph),tcph);if(unlikely(NULLth))gotosynrcvout;第一次握手只有syn包,并有访问svc,开启了synproxy防护if(thsyn!thack!thrst!thfin(svcdpvsservicelookup(af,iphproto,iphdaddr,thdest,0,NULL,NULL,NULL,rtelcoreid()))(svcflagsDPVSSVCFSYNPROXY)){ifservicesweightiszero(nonactiverealserver),donotinganddropthepacket如果后端服务svc权重为0,没有可用后端,返回INETDROPif(svcweight0){dpvsestatsinc(SYNPROXYNODEST);gotosynrcvout;}droppacketfromblacklist
  如果在黑名单中,那么退出,返回INETDROP
  if(dpvsblklstlookup(iphaf,iphproto,iphdaddr,
  thdest,iphsaddr)){
  gotosynrcvout;
  }}else{return1;}mbufwillbereusedandetherheaderwillbeset。FIXME:tosupportnonetherpackets。if(mbufl2len!sizeof(structetherhdr))gotosynrcvout;updatestatistics更新统计信息dpvsestatsinc(SYNPROXYSYNCNT);settxoffloadflags校验assert(mbufportNETIFMAXPORTS);获取netdevice层设备,并做校验devnetifportget(mbufport);if(unlikely(!dev)){RTELOG(ERR,IPVS,s:deviceethdnotfound,func,mbufport);gotosynrcvout;}根据物理设备的硬件负载功能,设置mbuf相应标志位if(likely(dev(devflagNETIFPORTFLAGTXTCPCSUMOFFLOAD))){if(afAFINET)mbufolflags(PKTTXTCPCKSUMPKTTXIPCKSUMPKTTXIPV4);elsembufolflags(PKTTXTCPCKSUMPKTTXIPV6);}reusembuf复用mbuf并回复synack,为什么说是复用呢?因为对mbuf修改后,直接当做synack回复包返回给了clientsynproxyreusembuf(af,mbuf,th,tcpopt);setL2headerandsendthepacketoutItisnotedthatipv4xmitshouldnotusedhere,becausembufisreused。设置L2层的header,源和目的对换eth(structetherhdr)rtepktmbufprepend(mbuf,mbufl2len);if(unlikely(!eth)){RTELOG(ERR,IPVS,s:nomemory,func);gotosynrcvout;}memcpy(ethaddr,ethsaddr,sizeof(structetheraddr));memcpy(ethsaddr,ethdaddr,sizeof(structetheraddr));memcpy(ethdaddr,ethaddr,sizeof(structetheraddr));调用netifxmit发送数据包if(unlikely(EDPVSOK!(retnetifxmit(mbuf,dev)))){RTELOG(ERR,IPVS,s:netifxmitfaileds,func,dpvsstrerror(ret));shouldnotsetverdicttoINETDROPsincenetifxmitalwaysconsumethembufwhileINETDROPmeansmbufllbefreeinINETHOOK。}verdictINETSTOLEN;return0;
  synrcvout:dropanddestroythepacketverdictINETDROP;return0;}
  synproxyreusembuf
  设置tcp选项计算synack包的seq,syncookies计算设置synack包的seq和ackseq交换ip和tcp首部的源,目的信息计算ip首部和tcp首部校验和Reusembufforsynproxy,calledbysynproxysynrcv()。dofollowingthings:settcpoptions,computeseqwithcookiefunc,settcpseqandackseq,exchangeipaddrandtcpport,computeiphdrandtcpcheck(HWxmitchecksumoffloadnotsupportforsyn)。staticvoidsynproxyreusembuf(intaf,structrtembufmbuf,structtcphdrth,structdpvssynproxyoptopt){uint32tisn;uint16ttmpport;intiphlen;获取ip首部长度if(AFINET6af){iphlensizeof(structip6hdr);}else{iphlenip4hdrlen(mbuf);}长度校验,确保首部长度正确if(mbufmaypull(mbuf,iphlen(thdoff2))!0){return;}dealwithtcpoptions解析并且设置tcpoptions,包括mss,windowsize,timestampsynproxyparsesetopts(mbuf,th,opt);getcookie根据syncookies算法生成synack数据包的seqif(AFINET6af){isnsynproxycookiev6initsequence(mbuf,th,opt);}else{isnsynproxycookiev4initsequence(mbuf,th,opt);}setsynackflag设置synack标志((uint8t)th)〔13〕0x12;exchageports交换dest,source端口tmpportthdest;thdestthsource;thsourcetmpport;setwindowsizetozero设置接收窗口为0,不允许握手阶段携带数据信息thwindow0;setseq(cookie)andackseq设置seq和ackseq,其中ackseq是客户端序号加1,而返回的synseq就是刚刚计算出来的cookiethackseqhtonl(ntohl(thseq)1);thseqhtonl(isn);exchageaddresses交换源和目的ip地址信息并重新计算校验和if(AFINET6af){structin6addrtmpaddr;structip6hdrip6hip6hdr(mbuf);tmpaddrip6hip6src;
  ip6hip6srcip6hip6dst;
  ip6hip6dsttmpaddr;
  ip6hip6hlimdpvssynproxyctrlsynackttl;
  if(likely(mbufolflagsPKTTXTCPCKSUM))
  {
  mbufl3len(void)th(void)ip6h;
  mbufl4lenntohs(ip6hip6plen)sizeof(structip6hdr)mbufl3len;
  thcheckip6phdrcksum(ip6h,mbufolflags,mbufl3len,IPPROTOTCP);
  }
  else
  {
  if(mbufmaypull(mbuf,mbufpktlen)!0)
  {
  return;
  }
  tcp6sendcsum((structipv6hdr)ip6h,th);
  }}else{uint32ttmpaddr;structiphdriph(structiphdr)ip4hdr(mbuf);tmpaddriphsaddr;
  iphsaddriphdaddr;
  iphdaddrtmpaddr;
  iphttldpvssynproxyctrlsynackttl;
  iphtos0;
  computechecksum
  if(likely(mbufolflagsPKTTXTCPCKSUM))
  {
  mbufl3leniphlen;
  mbufl4lenntohs(iphtotlen)iphlen;
  thcheckip4phdrcksum((structipv4hdr)iph,mbufolflags);
  }
  else
  {
  if(mbufmaypull(mbuf,mbufpktlen)!0)
  {
  return;
  }
  tcp4sendcsum((structipv4hdr)iph,th);
  }
  如果硬件不支持计算csum,调用ip4sendcsum生成checksum
  if(likely(mbufolflagsPKTTXIPCKSUM))
  {
  iphcheck0;
  }
  else
  {
  ip4sendcsum((structipv4hdr)iph);
  }}}
  synproxyparsesetopts
  Replacetcpoptionsintcpheader,calledbysynproxyreusembuf()staticvoidsynproxyparsesetopts(structrtembufmbuf,structtcphdrth,structdpvssynproxyoptopt){mssinreceivedpacketuint16tinmss;uint32ttmp;unsignedcharptr;计算tcp选项长度intlength(thdoff4)sizeof(structtcphdr);uint16tusermssdpvssynproxyctrlinitmss;structtimespectspnow;memset(opt,,sizeof(structdpvssynproxyopt));optmssclamp536;ptr(unsignedchar)(th1);while(length0){unsignedchartmpopcodeptr;intopcodeptr;intopsize;switch(opcode){选项结束,直接返回caseTCPOPTEOL:return;NOP选项,只作填充用,因此选项长度减1,进入下一个循环处理下一个选项caseTCPOPTNOP:length;continue;default:opsizeptr;如果不是选项表结束标志也不是空操作,则选取选项长度,并检测其合法性if(opsize2)sillyoptions{return;}选项长度校验if(opsizelength){return;dontparsepartialoptions}switch(opcode){caseTCPOPTMAXSEG:用来通告最大段长度,最大段长度选项格式如下kind2len4最大段长度该选项只能出现在SYN段片段中if(opsizeTCPOLENMAXSEG){inmssntohs((uint16t)ptr);if(inmss){如果系统设置的mss小于对端通告的mss,使用较小值回复if(usermssinmss){inmssusermss;}optmssclampinmss;}字节序转换(uint16t)ptrhtons(optmssclamp);}break;窗口选项caseTCPOPTWINDOW:kind3len3位移数去窗口扩大因子选项中的位移数,将标识SYN段中包含窗口扩大因子选项的wscaleok置为1,如果选项中位移数大于14则警告if(opsizeTCPOLENWINDOW){if(dpvssynproxyctrlwscale){optwscaleok1;optsndwscale(uint8t)ptr;if(optsndwscaleDPVSSYNPROXYWSCALEMAX){RTELOG(INFO,IPVS,tcpparseoptions:Illegalwindowscalingvalueddreceived。,optsndwscale,DPVSSYNPROXYWSCALEMAX);optsndwscaleDPVSSYNPROXYWSCALEMAX;}(uint8t)ptr(uint8t)dpvssynproxyctrlwscale;}else{不支持以NOP选项填充memset(tmpopcode,TCPOPTNOP,TCPOLENWINDOW);}}break;时间戳选项caseTCPOPTTIMESTAMP:if(opsizeTCPOLENTIMESTAMP){if(dpvssynproxyctrltimestamp){memset(tspnow,0,sizeof(tspnow));clockgettime(CLOCKREALTIME,tspnow);opttstampok1;tmp(uint32t)ptr;(tmp1)tmp;tmphtonl((uint32t)(TCPOPTTIMESTAMP(tspnow)));}else{memset(tmpopcode,TCPOPTNOP,TCPOLENTIMESTAMP);}}break;caseTCPOPTSACKPERMITTED:允许SACK选项,只能出现在SYN段中,将sackok置为1,标识syn中允许sack选项。if(opsizeTCPOLENSACKPERMITTED){if(dpvssynproxyctrlsack){optsackok1;}else{memset(tmpopcode,TCPOPTNOP,TCPOLENSACKPERMITTED);}}break;}ptropsize2;lengthopsize;}}
  }
  client第三次握手包应答dpvsin
  client侧第三次握手包(ACK),在dpvsprerouting中肯定会返回ACCEPT,继续在dpvsin中处理查找连接时不会命中,调用tcp传输层tcpconnsched函数进行新连接的调度staticintdpvsin(voidpriv,structrtembufmbuf,conststructinethookstatestate,intaf){。。。。对于新建的连接,肯定是没有会话的,connsched根据请求选择一个后端realserver建立连接if(unlikely(!conn)){tryscheduleRSandcreatenewconnection调用proto中connsched接口选择一个后端rs建立连接,如果创建连接失败,返回verdictif(protconnsched(prot,iph,mbuf,conn,verdict)!EDPVSOK){RTELOG(DEBUG,IPVS,s:failtoschedule。,func);return(verdict);}onlySNATtriggersconnectionbyinsideoutsidetraffic。snat模式,则是内部服务器访问外部服务,内网服务器dpvs外网服务器(baidu),所以设置dirDPVSCONNDIROUTBOUNDif(conndestfwdmodeDPVSFWDMODESNAT){dirDPVSCONNDIROUTBOUND;}else{其余模式设置dirDPVSCONNDIRINBOUNDdirDPVSCONNDIRINBOUND;}}。。。
  }
  tcpconnsched
  staticinttcpconnsched(structdpvsprotoproto,conststructdpvsiphdriph,structrtembufmbuf,structdpvsconnconn,intverdict){。。。Synproxystep2logic:receiveclients3handshackeackpacketWhensynproxydisabled,onlySYNpacketscanarrivehere。SodontjudgeSYNPROXYflaghere!IfSYNPROXYflagjudged,andsynproxygotdisbledandkeepalivedreloaded,SYNpacketsforRSmayneverbesent。如果是syncookies连接建立第三次握手数据包,则返回EDPVSPKTSTOLENif(dpvssynproxyackrcv(iphaf,mbuf,th,proto,conn,iph,verdict)0){Attention:FirstACKpacketisalsostoredinconnackmbufreturn(EDPVSPKTSTOLEN);}。。。
  }
  dpvssynproxyackrcv
  syncookies校验dpvsschedule新建立连接后端调度,选择一个realserversynproxysendrssyn进行LB与RS的第一次握手Synproxystep2logic:receiveclientsAckReceiveclients3handshakesackpacket,docookiecheckandthensendsyntorsaftercreatingasessionintdpvssynproxyackrcv(intaf,structrtembufmbuf,structtcphdrth,structdpvsprotopp,structdpvsconncpp,conststructdpvsiphdriph,intverdict){intres;structdpvssynproxyoptopt;structdpvsservicesvc;intrescookiecheck;Donotchecksvcsynproxyflag,asitmaybechangedaftersynproxystep1。if(!thsynthack!thrst!thfin(svcdpvsservicelookup(af,iphproto,iphdaddr,thdest,0,NULL,NULL,NULL,rtelcoreid()))){if(dpvssynproxyctrldefer!synproxyackhasdata(mbuf,iph,th)){Updatestatisticsdpvsestatsinc(SYNPROXYNULLACK);Wegetapureackwhenexpectingackpacketwithpayload,so
  havetodropit
  verdictINETDROP;
  return(0);
  }
  syncookies验证,如果不匹配,那么就是攻击或是无效流量,将包丢弃。如果成功,执行synproxy第二阶段,lb调用
  dpvsschedule与后端realserver建立连接
  if(AFINET6af)
  {
  rescookiechecksynproxyv6cookiecheck(mbuf,
  ntohl(thackseq)1,opt);
  }
  else
  {
  rescookiechecksynproxyv4cookiecheck(mbuf,
  ntohl(thackseq)1,opt);
  }
  if(!rescookiecheck)
  {
  Updatestatistics
  dpvsestatsinc(SYNPROXYBADACK);
  Cookiecheckfailed,dropthepacket
  RTELOG(DEBUG,IPVS,s:syncookiecheckfailedsequn,func,
  ntohl(thackseq)1);
  verdictINETDROP;
  return(0);
  }
  Updatestatistics
  dpvsestatsinc(SYNPROXYOKACK);
  Letthevirtualserverselectarealserverfortheincomingconnetion,
  andcreateaconnectionentry
  dpvsschedule新建立连接后端调度,选择一个realserver
  cppdpvsschedule(svc,iph,mbuf,1,0);
  if(unlikely(!cpp))
  {
  RTELOG(WARNING,IPVS,s:ipvsschedulefailedn,func);
  FIXME:Whattodowhenvirtualserviceisavailablebutnodestination
  availableforanewconnetion:sendanicmpUNREACHABLE?
  verdictINETDROP;
  return(0);
  }
  Donothingbutprintaerrormsgwhenfail,becausesessionwillbe
  correctlyfreedindpvsconnexpire
  synproxysendrssyn完成lb与realserver建连
  if(EDPVSOK!(ressynproxysendrssyn(af,th,cpp,mbuf,pp,opt)))
  {
  RTELOG(ERR,IPVS,s:synproxysendrssynfailedsn,
  func,dpvsstrerror(res));
  }
  Countintheackpacket(STOLENbysynproxy)
  dpvsstatsin(cpp,mbuf);
  Activesessiontimer,anddecrefcnt。
  Alsostealthembuf,andletcallerreturnimmediately
  dpvsconnput(cpp);
  verdictINETSTOLEN;
  return(0);}return(1);}
  synproxysendrssyn
  Createsynpacketandsendittors。Wealsostoresynmbufincpifsynretransmitionisturnedon。staticintsynproxysendrssyn(intaf,conststructtcphdrth,structdpvsconncp,structrtembufmbuf,structdpvsprotopp,structdpvssynproxyoptopt){inttcphdrsize;structrtembufsynmbuf,synmbufcloned;structrtemempoolpool;structtcphdrsynth;if(!cppacketxmit){RTELOG(WARNING,IPVS,s:packetxmitisnull,func);return(EDPVSINVAL);}Allocatembuffromdevicemempoolpoolgetmbufpool(cp,DPVSCONNDIRINBOUND);if(unlikely(!pool)){RTELOG(WARNING,IPVS,s:s,func,dpvsstrerror(EDPVSNOROUTE));return(EDPVSNOROUTE);}从内存池中分配synmbuf,用于发送到后端realserversynmbufrtepktmbufalloc(pool);if(unlikely(!synmbuf)){RTELOG(WARNING,IPVS,s:s,func,dpvsstrerror(EDPVSNOMEM));return(EDPVSNOMEM);}设置路由缓存为nullsynmbufuserdataNULL;makesurenorouteinfoReservespacefortcpheader为tcp层保留空间,包括选项,通过prepend向mbuf的headroom添加数据tcphdrsize(sizeof(structtcphdr)TCPOLENMAXSEG(opttstampok?TCPOLENTSTAMPAPPA:0)(optwscaleok?TCPOLENWSCALEALIGNED:0)SACKPERMisinthepalceofNOPNOPofTS((optsackok!opttstampok)?TCPOLENSACKPERMITTEDALIGNED:0));synth(structtcphdr)rtepktmbufprepend(synmbuf,tcphdrsize);if(!synth){rtepktmbuffree(synmbuf);RTELOG(WARNING,IPVS,s:s,func,dpvsstrerror(EDPVSNOROOM));return(EDPVSNOROOM);}Setuptcpheadermemset(synth,0,tcphdrsize);synthsourcethsource;synthdestthdest;synthseqhtonl(ntohl(thseq)1);synthackseq0;(((uint16t)synth)6)htons(((tcphdrsize2)12)THSYN0x02);FIXME:whatwindowshouldweusesynthwindowhtons(5000);synthcheck0;synthurgptr0;synthurg0;构造syn包的tcp选项synproxysynbuildoptions((uint32t)(synth1),opt);IP首部的构造if(AFINET6af){structip6hdrackip6h;structip6hdrsynip6h;Reservespaceforipv6header
  synip6h(structip6hdr)rtepktmbufprepend(synmbuf,
  sizeof(structip6hdr));
  if(!synip6h)
  {
  rtepktmbuffree(synmbuf);
  RTELOG(WARNING,IPVS,s:sn,func,dpvsstrerror(EDPVSNOROOM));
  return(EDPVSNOROOM);
  }
  ackip6h(structip6hdr)ip6hdr(mbuf);
  synip6hip6vfc0x60;IPv6
  synip6hip6srcackip6hip6src;
  synip6hip6dstackip6hip6dst;
  synip6hip6plenhtons(tcphdrsize);
  synip6hip6nxtNEXTHDRTCP;
  synip6hip6hlimIPV6DEFAULTHOPLIMIT;
  synmbufl3lensizeof(synip6h);}else{structiphdrackiph;structiphdrsyniph;Reservespaceforipv4header
  syniph(structiphdr)rtepktmbufprepend(synmbuf,sizeof(structipv4hdr));
  if(!syniph)
  {
  rtepktmbuffree(synmbuf);
  RTELOG(WARNING,IPVS,s:sn,func,dpvsstrerror(EDPVSNOROOM));
  return(EDPVSNOROOM);
  }
  ackiph(structiphdr)ip4hdr(mbuf);
  ((uint16t)syniph)htons((412)(58)(ackiphtos0x1E));
  syniphtotlenhtons(synmbufpktlen);
  syniphfragoffhtons(IPV4HDRDFFLAG);
  syniphttl64;
  syniphprotocolIPPROTOTCP;
  syniphsaddrackiphsaddr;
  syniphdaddrackiphdaddr;
  synmbufl3lensizeof(syniph);
  checksumisdonebyfnatinhandler
  syniphcheck0;}Savesynmbufifsynretransmissionisonsynretry,主动连接时的超时重传次数,如果大于零,将构造的数据报缓存起来if(dpvssynproxyctrlsynretry0){synmbufclonedmbufcopy(synmbuf,pool);if(unlikely(!synmbufcloned)){rtepktmbuffree(synmbuf);RTELOG(WARNING,IPVS,s:s,func,dpvsstrerror(EDPVSNOMEM));return(EDPVSNOMEM);}synmbufcloneduserdataNULL;
  cpsynmbufsynmbufcloned;
  spdbgstats32inc(spsynsaved);
  rteatomic32set(cpsynretrymax,dpvssynproxyctrlsynretry);}TODO:SaveinfoforfastresponsexmitCountinthesynpacketdpvsstatsin(cp,mbuf);Ifxmitfailed,synmbufwillbefreedcorrectly调用packetxmit发送,此处为dpvsxmitfnatcppacketxmit(pp,cp,synmbuf);return(EDPVSOK);}
  rs端synack应答dpvsin
  方向为DPVSCONNDIROUTBOUND此时能够查找到连接,最终会进入dpvssynproxysynackrcv逻辑staticintdpvsin(voidpriv,structrtembufmbuf,conststructinethookstatestate,intaf){if(connflagsDPVSCONNFSYNPROXY){if(dirDPVSCONNDIRINBOUND){FilteroutinackpacketwhencpisatSYNSENTstate。Dropitifnotavalidpacket,storeitotherwiseif(0dpvssynproxyfilterack(mbuf,conn,prot,iph,verdict)){dpvsstatsin(conn,mbuf);dpvsconnput(conn);return(verdict);}Reusesynproxysessions。Reusemeansupdatesynproxyseqstructandcleanackmbufetc。if(0!dpvssynproxyctrlconnreuse){if(0dpvssynproxyreuseconn(af,mbuf,conn,prot,iph,verdict)){dpvsstatsin(conn,mbuf);dpvsconnput(conn);return(verdict);}}}else{Synproxy3logic:receivesynackfromrsif(dpvssynproxysynackrcv(mbuf,conn,prot,iph。len,verdict)0){dpvsstatsout(conn,mbuf);dpvsconnput(conn);return(verdict);}}}
  }dpvssynproxysynackrcv
  Synproxystep3logic:receiverssSynAck。Updatesynproxyseq。deltaandsendstoredackmbufstors。intdpvssynproxysynackrcv(structrtembufmbuf,structdpvsconncp,structdpvsprotopp,intthoffset,intverdict){structtcphdrtcph,th;structdpvssynproxyackpakcettmbuf,tmbuf2;structlistheadsavembuf;structdpvsdestdestcpdest;unsignedconntimeout0;th指向tcp首部起始位置thmbufheaderpointer(mbuf,thoffset,sizeof(tcph),tcph);if(unlikely(!th)){verdictINETDROP;return(0);}
  ifdefCONFIGDPVSIPVSDEBUGRTELOG(DEBUG,IPVS,s:sequacksequccccpissynproxyucpstateu,func,ntohl(thseq),ntohl(thackseq),(thsyn)?S:,(thack)?A:,(thrst)?R:,cpflagsDPVSCONNFSYNPROXY,cpstate);endifINITLISTHEAD(savembuf);判断应答包状态,必须是syn和ack包,并且开启了synproxy,当前conn连接处于DPVSTCPSSYNSENT状态if((thsyn)(thack)(!thrst)(cpflagsDPVSCONNFSYNPROXY)(cpstateDPVSTCPSSYNSENT)){更新synproxyseq。delta序列号差值cpsynproxyseq。deltantohl(cpsynproxyseq。isn)ntohl(thseq);连接状态进入ESTABLISHEDcpstateDPVSTCPSESTABLISHED;获取连接超时时间conntimeoutdpvsgetconntimeout(cp);if(unlikely((conntimeout!0)(cpprotoIPPROTOTCP))){cptimeout。tvsecconntimeout;}else{cptimeout。tvsecpptimeouttable〔cpstate〕;}dpvstimeranddelay(cptimeout,1000000);更新dest上的连接统计信息if(dest){rteatomic32inc(destactconns);rteatomic32dec(destinactconns);cpflagsDPVSCONNFINACTIVE;}Savetcpsequenceforfullnatnat,insidetooutside保存序号rsendseq和rsendackif(DPVSFWDMODENATcpdestfwdmodeDPVSFWDMODEFNATcpdestfwdmode){cprsendseqhtonl(ntohl(thseq)1);cprsendackthackseq;
  ifdefCONFIGDPVSIPVSDEBUGRTELOG(DEBUG,IPVS,s:packetfromrs,sequ,acksequ,portuu,func,ntohl(thseq),ntohl(thackseq),ntohs(thsource),ntohs(thdest));endif}TODO:ipvssynproxysavefastxmitinfo?Freestoredsynmbuf,noneedforretransmitionanymoresynmbuf上保存了lbrs发起连接请求的数据报,此时连接正常完成,需要释放if(cpsynmbuf){rtepktmbuffree(cpsynmbuf);cpsynmbufNULL;spdbgstats32dec(spsynsaved);}在全局ackmbuf链表中删除自己的ackmbuf引用if(listempty(cpackmbuf)){FIXME:Maybeabughere,printerrmsgandgo。Attention:cpstatehasbeenchangedandweshouldstillDROPthesynackmbuf。RTELOG(ERR,IPVS,s:gotackmbufNULLpointer:acksavedun,func,cpacknum);verdictINETDROP;return(0);}WindowsizehasbeensettozerointhesynackpackettoClient。Ifgetmorethanoneackpackethere,itmeansclienthassentawindowprobeafteroneRTO。TheprobewillbeforwardtoRSandRSwillrespondawindowupdate。SoDPVShasnoneedtosendawindowupdate。设置窗口if(cpacknum1){synproxysendwindowupdate(tuplehashout(cp)。af,mbuf,cp,pp,th);}listforeachentrysafe(tmbuf,tmbuf2,cpackmbuf,list){listdelinit(tmbuflist);cpacknum;listaddtail(tmbuflist,savembuf);}assert(cpacknum0);调用packetxmit将缓存发送至rs侧的数据包发送至rs,其中包括第三次握手的ack数据包listforeachentrysafe(tmbuf,tmbuf2,savembuf,list){listdelinit(tmbuflist);synmbufwillbefreedcorrectlyifxmitfailed调用packetxmit将其发送至rscppacketxmit(pp,cp,tmbufmbuf);freedpvssynproxyackpakcetrtemempoolput(thisackmbufpool,tmbuf);spdbgstats32dec(spacksaved);}这个ack连接数据报不需要发送给client侧,所以此处返回dropverdictINETDROP;return(0);}elseif((thrst)(cpflagsDPVSCONNFSYNPROXY)(cpstateDPVSTCPSSYNSENT)){RTELOG(DEBUG,IPVS,s:getrstfromrs,sequacksequn,func,ntohl(thseq),ntohl(thackseq));Countthedeltaofseq如果是rst包,设置连接状态为DPVSTCPSCLOSEcpsynproxyseq。deltantohl(cpsynproxyseq。isn)ntohl(thseq);cpstateDPVSTCPSCLOSE;cptimeout。tvsecpptimeouttable〔cpstate〕;dpvstimeranddelay(cptimeout,1000000);thseqhtonl(ntohl(thseq)1);synproxyseqcsumupdate?return(1);}return(1);
  }
  原文链接:https:blog。csdn。netzjx345438858articledetails108106143

最美不过林青霞穿红裙,不管28岁还是68岁,同样美得明艳大方头条创作挑战赛红色的长裙,是喜庆的,也是热辣的,是张扬的,也是绚烂的。喜欢穿着红色长裙的姑娘,必然是自信张扬的。一抹浓艳的色彩,扫除生活的阴霾,给你最热烈的惊喜。喜……2分钟1打4反杀3人!4级必杀套路,无视防御塔!轻松带飞王者姜子牙白起组合详析(打野白起姜子牙伤害一览)这套组合最厉害的地方在于,能在2分钟时实现2个四级一起抓边被姜子牙伤害蹭到的单位,只要在3s内被击杀,姜子牙无论在……NBA早报湖人询价库兹马,詹皇评价塔图姆,考辛斯称保罗不是前关注NBA的朋友们,大家好!今天联盟安排了10场比赛,其中勇士对阵步行者这场关注度最高。勇士在威金斯缺阵的情况下开启了死亡六连客,他们昨天被雄鹿狂虐,今天背靠背对阵步行者,此前……Ansible服务器主机配置使用ansible来对远程主机进行部署的话。我们需要首先对远程注解进行配置。配置文件路径配置文件位于:etcansiblehosts路径下面。可以使用vi工具进行打……耐克为什么要把鞋越做越丑?妈妈见了要打人,外婆见了要拿针,这说的是破洞牛仔裤。一种长辈无法理解的时尚,裤子破了不补,还要穿出去招摇。往面子上说这是穷到没钱买新衣服的经济状况暴露无遗,往健康上说这是不注重……世青赛国乒四线告捷,女团保送晋级,法国16岁新星率队击败日本12月5日突尼斯,古老的非洲大陆上一场属于青少年的乒乓盛宴正如火如荼进行中。根据组委会的安排,本次共设置U19和U15两个组别的赛事,国乒方面在第一个比赛中捷报频频,U19男团……肯尼亚坦桑尼亚旅游日记(6)8月8日,安博塞利国家公园一纳曼加边境站一阿鲁沙(补遗)晴。晨起拍照,乞力马扎罗山顶部稍见积雪,然而看不真切,可能此处不是最佳位置吧。8:10出发去肯坦边境的纳曼加,仍然……湿热寒湿分不清,化湿会越来越湿,中医教你辨别清楚,正确调理湿热、寒湿分不清,化湿只会越来越湿。大家好,我是刘医生。有的人经常出油出汗,大腿根还会潮湿,舌苔很厚,知道自己是湿气重了,了解到参苓白术散是化湿的方子,吃了几包,发……中关村的不倒翁,张旋龙慧眼识二珠金山WPS4港商张旋龙接棒父亲张铠卿,更为人情练达,在中关村游刃有余。他的四六开规则被奉为佳话。一般合作,双方分成五五开,但他主动让利为四六开,我拿4成,你拿……1。2万亿大放水!房地产获六大银行授信,房价会涨吗?昨晚看了韩国对乌拉圭的直播,不得不说韩国队也有进步,但乌拉圭实在太水了,连个有效的配合都打不出来,最终0:0战平,不知又有多少赌狗站上了天台?巴西那场太晚熬不动,今早起来……散文岳母的三样美食岳母的三样美食文郭军一阵悦耳的手机铃声,把我从午休的神游梦幻中唤回现实。拿起枕边手机,听筒中传来再熟悉不过的声音:爸,我和团子想吃您做的汆丸子,晚上下班我们一家三口……剧本杀让蝉声渐响复盘解析剧透《让蝉声渐响》的故事起源于一桩杀人案,在案件发生的若干年后,在一栋豪华别墅里,6个各怀心事的玩家为了庆祝男主人的生日聚集在一起,此时突然有快递给6人送来了一套剧本杀游戏。……
成都出发1。5小时,直达千年银杏王,赏秋爬山好去处秋日生活打卡季秋末冬初,正是一年中登山赏银杏的最佳时间,在成都周边有许多不错的银杏观赏地。在距离成都市区大约1。5小时车程的地方,就生长着一颗千年树龄的银杏王,是当地赏银杏必去……上海男篮官宣,李春江救命稻草来了,倒数季军将翻身当上海花费巨资打造球队的时候,谁也不会想到它会落到如今这个地步,本赛季第一阶段比赛,3胜6负排名17。因为有很多原因可以解释如今这个状态,让一部分人开始怀疑李春江的执教能……南京鲁医生打人事件,老师沉默的背后是怕担责吗?南京鲁医生打人事件,热潮反增不减。持续牵动着各家长的心。事件引起了南京教育局的重视与关注,已要求相关幼儿园进行整改,已把整改任务交给了玄武区教育局,将整改任务落实执行中。此次事……斯诺克格局大变!3杰无缘世界前10,赵心童大跌,丁俊晖稳进22022年英锦赛正在进行中,目前仅剩1位世界前10,马克艾伦64淘汰克雷吉,搭上4强末班车,而世界第一奥沙利文、大满贯得主墨菲纷纷出局。至此,斯诺克格局大变,最新单赛季排名,7……回忆童年陪伴你的零食有哪些随着时光的流逝,回忆童年时代也是挺快乐的。陪伴的零食有冰棒,炒小麦、炒黄豆、小糖块、夹心饼干等等。熟红薯干,玉米爆的玉米花,还有烤红薯人,现在形势大好,小孩想吃什么都有。……加密货币交易平台FTX宣布破产据新华社纽约11月11日电知名加密货币交易平台FTX交易公司11日通过社交媒体发布公告说,该公司和FTX集团其他附属公司已经按照美国相关法律启动自愿破产程序。公告说,FT……家常豆腐的传统做法,香嫩爽滑又入味,好吃下饭,家里人都爱吃大家都知道要多吃豆制品,能够给人体补充必要的蛋白质。豆腐就是一种最常见的豆制品,主要是黄豆制作而成,被称为植物肉。就营养成分而言,豆腐的制作工艺保留了黄豆几乎所有的营养,所以营……懂得自己不需要什么,才是人生的大智慧苏格拉底说,人生在世,知道自己需要什么,只不过是一个人的本能;而懂得自己不需要什么,这却是一个人的智慧。饿了吃,困了睡,冷了穿衣,病了心情不好,这是自然而然的事,这是本能……网格之力简评复杂而精美,张扬着游戏人不经意的傲慢根据游戏官方自己的说法,《网格之力:女神的面具(GridForceMaskoftheGoddess)》是一款兼顾着格斗游戏的速度与角色扮演游戏的深度的网格动作游戏。这款游……曾1小时卖出50万台,5160mAh67W快充1亿像素,如今尽管5G时代,原以为会促进手机的销量,但事与愿违,手机市场出现了极大的销量下滑。但竞争从未停止,从高端机到百元机都有诸多机型可以选择,而如果你的预算控制在千元左右,可以考虑下去……米切尔将率克利夫兰打乱东部局面熟悉小比克斯塔夫的都知道,这位教练是联盟知名的摆烂神器。到了克利夫兰,骑士这状态反而是一年比一年猛。更是在上季打出44胜38负的战绩,自201718赛季后常规赛胜率首次突破五成……便秘的危害比你认知中要严重!这几点教你对因治秘,要重视日常拉肚子时,大家都会想着要紧急应对一下,找一找身边可以应对的药,进行治疗。同属于肠道问题的便秘却很难会得到大家的重视,人们往往会选择忽略它,主动去看医生吃药这么麻烦的事……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网