PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /opt/imh-python/lib/python3.9/site-packages/pyroute2/netlink/nfnetlink
Viewing File: /opt/imh-python/lib/python3.9/site-packages/pyroute2/netlink/nfnetlink/nfctsocket.py
""" NFCTSocket -- low level connection tracking API See also: pyroute2.conntrack """ import socket from pyroute2.netlink import ( NETLINK_NETFILTER, NLA_F_NESTED, NLM_F_ACK, NLM_F_CREATE, NLM_F_DUMP, NLM_F_EXCL, NLM_F_REQUEST, NLMSG_ERROR, nla, ) from pyroute2.netlink.nfnetlink import NFNL_SUBSYS_CTNETLINK, nfgen_msg from pyroute2.netlink.nlsocket import NetlinkSocket IPCTNL_MSG_CT_NEW = 0 IPCTNL_MSG_CT_GET = 1 IPCTNL_MSG_CT_DELETE = 2 IPCTNL_MSG_CT_GET_CTRZERO = 3 IPCTNL_MSG_CT_GET_STATS_CPU = 4 IPCTNL_MSG_CT_GET_STATS = 5 IPCTNL_MSG_CT_GET_DYING = 6 IPCTNL_MSG_CT_GET_UNCONFIRMED = 7 IPCTNL_MSG_MAX = 8 try: IP_PROTOCOLS = { num: name[8:] for name, num in vars(socket).items() if name.startswith("IPPROTO") } except (IOError, OSError): IP_PROTOCOLS = {} # Window scaling is advertised by the sender IP_CT_TCP_FLAG_WINDOW_SCALE = 0x01 # SACK is permitted by the sender IP_CT_TCP_FLAG_SACK_PERM = 0x02 # This sender sent FIN first IP_CT_TCP_FLAG_CLOSE_INIT = 0x04 # Be liberal in window checking IP_CT_TCP_FLAG_BE_LIBERAL = 0x08 # Has unacknowledged data IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED = 0x10 # The field td_maxack has been set IP_CT_TCP_FLAG_MAXACK_SET = 0x20 # From linux/include/net/tcp_states.h TCPF_ESTABLISHED = 1 << 1 TCPF_SYN_SENT = 1 << 2 TCPF_SYN_RECV = 1 << 3 TCPF_FIN_WAIT1 = 1 << 4 TCPF_FIN_WAIT2 = 1 << 5 TCPF_TIME_WAIT = 1 << 6 TCPF_CLOSE = 1 << 7 TCPF_CLOSE_WAIT = 1 << 8 TCPF_LAST_ACK = 1 << 9 TCPF_LISTEN = 1 << 10 TCPF_CLOSING = 1 << 11 TCPF_NEW_SYN_RECV = 1 << 12 TCPF_TO_NAME = { TCPF_ESTABLISHED: 'ESTABLISHED', TCPF_SYN_SENT: 'SYN_SENT', TCPF_SYN_RECV: 'SYN_RECV', TCPF_FIN_WAIT1: 'FIN_WAIT1', TCPF_FIN_WAIT2: 'FIN_WAIT2', TCPF_TIME_WAIT: 'TIME_WAIT', TCPF_CLOSE: 'CLOSE', TCPF_CLOSE_WAIT: 'CLOSE_WAIT', TCPF_LAST_ACK: 'LAST_ACK', TCPF_LISTEN: 'LISTEN', TCPF_CLOSING: 'CLOSING', TCPF_NEW_SYN_RECV: 'NEW_SYN_RECV', } # From include/uapi/linux/netfilter/nf_conntrack_common.h IPS_EXPECTED = 1 << 0 IPS_SEEN_REPLY = 1 << 1 IPS_ASSURED = 1 << 2 IPS_CONFIRMED = 1 << 3 IPS_SRC_NAT = 1 << 4 IPS_DST_NAT = 1 << 5 IPS_NAT_MASK = IPS_DST_NAT | IPS_SRC_NAT IPS_SEQ_ADJUST = 1 << 6 IPS_SRC_NAT_DONE = 1 << 7 IPS_DST_NAT_DONE = 1 << 8 IPS_NAT_DONE_MASK = IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE IPS_DYING = 1 << 9 IPS_FIXED_TIMEOUT = 1 << 10 IPS_TEMPLATE = 1 << 11 IPS_UNTRACKED = 1 << 12 IPS_HELPER = 1 << 13 IPS_OFFLOAD = 1 << 14 IPS_UNCHANGEABLE_MASK = ( IPS_NAT_DONE_MASK | IPS_NAT_MASK | IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING | IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_OFFLOAD ) IPSBIT_TO_NAME = { IPS_EXPECTED: 'EXPECTED', IPS_SEEN_REPLY: 'SEEN_REPLY', IPS_ASSURED: 'ASSURED', IPS_CONFIRMED: 'CONFIRMED', IPS_SRC_NAT: 'SRC_NAT', IPS_DST_NAT: 'DST_NAT', IPS_SEQ_ADJUST: 'SEQ_ADJUST', IPS_SRC_NAT_DONE: 'SRC_NAT_DONE', IPS_DST_NAT_DONE: 'DST_NAT_DONE', IPS_DYING: 'DYING', IPS_FIXED_TIMEOUT: 'FIXED_TIMEOUT', IPS_TEMPLATE: 'TEMPLATE', IPS_UNTRACKED: 'UNTRACKED', IPS_HELPER: 'HELPER', IPS_OFFLOAD: 'OFFLOAD', } # From include/uapi/linux/netfilter/nf_conntrack_tcp.h IP_CT_TCP_FLAG_WINDOW_SCALE = 0x01 IP_CT_TCP_FLAG_SACK_PERM = 0x02 IP_CT_TCP_FLAG_CLOSE_INIT = 0x04 IP_CT_TCP_FLAG_BE_LIBERAL = 0x08 IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED = 0x10 IP_CT_TCP_FLAG_MAXACK_SET = 0x20 IP_CT_EXP_CHALLENGE_ACK = 0x40 IP_CT_TCP_SIMULTANEOUS_OPEN = 0x80 IP_CT_TCP_FLAG_TO_NAME = { IP_CT_TCP_FLAG_WINDOW_SCALE: 'WINDOW_SCALE', IP_CT_TCP_FLAG_SACK_PERM: 'SACK_PERM', IP_CT_TCP_FLAG_CLOSE_INIT: 'CLOSE_INIT', IP_CT_TCP_FLAG_BE_LIBERAL: 'BE_LIBERAL', IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED: 'DATA_UNACKNOWLEDGED', IP_CT_TCP_FLAG_MAXACK_SET: 'MAXACK_SET', IP_CT_EXP_CHALLENGE_ACK: 'CHALLENGE_ACK', IP_CT_TCP_SIMULTANEOUS_OPEN: 'SIMULTANEOUS_OPEN', } # From linux/include/uapi/linux/netfilter/nf_conntrack_tcp.h TCP_CONNTRACK_SYN_SENT = 1 TCP_CONNTRACK_SYN_RECV = 2 TCP_CONNTRACK_ESTABLISHED = 3 TCP_CONNTRACK_FIN_WAIT = 4 TCP_CONNTRACK_CLOSE_WAIT = 5 TCP_CONNTRACK_LAST_ACK = 6 TCP_CONNTRACK_TIME_WAIT = 7 TCP_CONNTRACK_CLOSE = 8 TCP_CONNTRACK_LISTEN = 9 TCP_CONNTRACK_MAX = 10 TCP_CONNTRACK_IGNORE = 11 TCP_CONNTRACK_RETRANS = 12 TCP_CONNTRACK_UNACK = 13 TCP_CONNTRACK_TIMEOUT_MAX = 14 TCP_CONNTRACK_TO_NAME = { TCP_CONNTRACK_SYN_SENT: "SYN_SENT", TCP_CONNTRACK_SYN_RECV: "SYN_RECV", TCP_CONNTRACK_ESTABLISHED: "ESTABLISHED", TCP_CONNTRACK_FIN_WAIT: "FIN_WAIT", TCP_CONNTRACK_CLOSE_WAIT: "CLOSE_WAIT", TCP_CONNTRACK_LAST_ACK: "LAST_ACK", TCP_CONNTRACK_TIME_WAIT: "TIME_WAIT", TCP_CONNTRACK_CLOSE: "CLOSE", TCP_CONNTRACK_LISTEN: "LISTEN", TCP_CONNTRACK_MAX: "MAX", TCP_CONNTRACK_IGNORE: "IGNORE", TCP_CONNTRACK_RETRANS: "RETRANS", TCP_CONNTRACK_UNACK: "UNACK", TCP_CONNTRACK_TIMEOUT_MAX: "TIMEOUT_MAX", } def terminate_single_msg(msg): return msg def terminate_error_msg(msg): return msg['header']['type'] == NLMSG_ERROR class nfct_stats(nfgen_msg): nla_map = ( ('CTA_STATS_GLOBAL_UNSPEC', 'none'), ('CTA_STATS_GLOBAL_ENTRIES', 'be32'), ('CTA_STATS_GLOBAL_MAX_ENTRIES', 'be32'), ) class nfct_stats_cpu(nfgen_msg): nla_map = ( ('CTA_STATS_UNSPEC', 'none'), ('CTA_STATS_SEARCHED', 'be32'), ('CTA_STATS_FOUND', 'be32'), ('CTA_STATS_NEW', 'be32'), ('CTA_STATS_INVALID', 'be32'), ('CTA_STATS_IGNORE', 'be32'), ('CTA_STATS_DELETE', 'be32'), ('CTA_STATS_DELETE_LIST', 'be32'), ('CTA_STATS_INSERT', 'be32'), ('CTA_STATS_INSERT_FAILED', 'be32'), ('CTA_STATS_DROP', 'be32'), ('CTA_STATS_EARLY_DROP', 'be32'), ('CTA_STATS_ERROR', 'be32'), ('CTA_STATS_SEARCH_RESTART', 'be32'), ) class nfct_msg(nfgen_msg): prefix = 'CTA_' nla_map = ( ('CTA_UNSPEC', 'none'), ('CTA_TUPLE_ORIG', 'cta_tuple'), ('CTA_TUPLE_REPLY', 'cta_tuple'), ('CTA_STATUS', 'be32'), ('CTA_PROTOINFO', 'cta_protoinfo'), ('CTA_HELP', 'asciiz'), ('CTA_NAT_SRC', 'cta_nat'), ('CTA_TIMEOUT', 'be32'), ('CTA_MARK', 'be32'), ('CTA_COUNTERS_ORIG', 'cta_counters'), ('CTA_COUNTERS_REPLY', 'cta_counters'), ('CTA_USE', 'be32'), ('CTA_ID', 'be32'), ('CTA_NAT_DST', 'cta_nat'), ('CTA_TUPLE_MASTER', 'cta_tuple'), ('CTA_SEQ_ADJ_ORIG', 'cta_nat_seq_adj'), ('CTA_SEQ_ADJ_REPLY', 'cta_nat_seq_adj'), ('CTA_SECMARK', 'be32'), ('CTA_ZONE', 'be16'), ('CTA_SECCTX', 'cta_secctx'), ('CTA_TIMESTAMP', 'cta_timestamp'), ('CTA_MARK_MASK', 'be32'), ('CTA_LABELS', 'cta_labels'), ('CTA_LABELS_MASK', 'cta_labels'), ('CTA_SYNPROXY', 'cta_synproxy'), ('CTA_FILTER', 'cta_filter'), ) @classmethod def create_from(cls, **kwargs): self = cls() for key, value in kwargs.items(): if isinstance(value, NFCTAttr): value = {'attrs': value.attrs()} if value is not None: self['attrs'].append([self.name2nla(key), value]) return self class cta_tuple(nla): nla_map = ( ('CTA_TUPLE_UNSPEC', 'none'), ('CTA_TUPLE_IP', 'cta_ip'), ('CTA_TUPLE_PROTO', 'cta_proto'), ) class cta_ip(nla): nla_map = ( ('CTA_IP_UNSPEC', 'none'), ('CTA_IP_V4_SRC', 'ip4addr'), ('CTA_IP_V4_DST', 'ip4addr'), ('CTA_IP_V6_SRC', 'ip6addr'), ('CTA_IP_V6_DST', 'ip6addr'), ) class cta_proto(nla): nla_map = ( ('CTA_PROTO_UNSPEC', 'none'), ('CTA_PROTO_NUM', 'uint8'), ('CTA_PROTO_SRC_PORT', 'be16'), ('CTA_PROTO_DST_PORT', 'be16'), ('CTA_PROTO_ICMP_ID', 'be16'), ('CTA_PROTO_ICMP_TYPE', 'uint8'), ('CTA_PROTO_ICMP_CODE', 'uint8'), ('CTA_PROTO_ICMPV6_ID', 'be16'), ('CTA_PROTO_ICMPV6_TYPE', 'uint8'), ('CTA_PROTO_ICMPV6_CODE', 'uint8'), ) class cta_protoinfo(nla): nla_map = ( ('CTA_PROTOINFO_UNSPEC', 'none'), ('CTA_PROTOINFO_TCP', 'cta_protoinfo_tcp'), ('CTA_PROTOINFO_DCCP', 'cta_protoinfo_dccp'), ('CTA_PROTOINFO_SCTP', 'cta_protoinfo_sctp'), ) class cta_protoinfo_tcp(nla): nla_map = ( ('CTA_PROTOINFO_TCP_UNSPEC', 'none'), ('CTA_PROTOINFO_TCP_STATE', 'uint8'), ('CTA_PROTOINFO_TCP_WSCALE_ORIGINAL', 'uint8'), ('CTA_PROTOINFO_TCP_WSCALE_REPLY', 'uint8'), ('CTA_PROTOINFO_TCP_FLAGS_ORIGINAL', 'cta_tcp_flags'), ('CTA_PROTOINFO_TCP_FLAGS_REPLY', 'cta_tcp_flags'), ) class cta_tcp_flags(nla): fields = [('value', 'BB')] class cta_protoinfo_dccp(nla): nla_map = ( ('CTA_PROTOINFO_DCCP_UNSPEC', 'none'), ('CTA_PROTOINFO_DCCP_STATE', 'uint8'), ('CTA_PROTOINFO_DCCP_ROLE', 'uint8'), ('CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ', 'be64'), ) class cta_protoinfo_sctp(nla): nla_map = ( ('CTA_PROTOINFO_SCTP_UNSPEC', 'none'), ('CTA_PROTOINFO_SCTP_STATE', 'uint8'), ('CTA_PROTOINFO_SCTP_VTAG_ORIGINAL', 'be32'), ('CTA_PROTOINFO_SCTP_VTAG_REPLY', 'be32'), ) class cta_nat(nla): nla_map = ( ('CTA_NAT_UNSPEC', 'none'), ('CTA_NAT_V4_MINIP', 'ip4addr'), ('CTA_NAT_V4_MAXIP', 'ip4addr'), ('CTA_NAT_PROTO', 'cta_protonat'), ('CTA_NAT_V6_MINIP', 'ip6addr'), ('CTA_NAT_V6_MAXIP', 'ip6addr'), ) class cta_protonat(nla): nla_map = ( ('CTA_PROTONAT_UNSPEC', 'none'), ('CTA_PROTONAT_PORT_MIN', 'be16'), ('CTA_PROTONAT_PORT_MAX', 'be16'), ) class cta_nat_seq_adj(nla): nla_map = ( ('CTA_NAT_SEQ_UNSPEC', 'none'), ('CTA_NAT_SEQ_CORRECTION_POS', 'be32'), ('CTA_NAT_SEQ_OFFSET_BEFORE', 'be32'), ('CTA_NAT_SEQ_OFFSET_AFTER', 'be32'), ) class cta_counters(nla): nla_map = ( ('CTA_COUNTERS_UNSPEC', 'none'), ('CTA_COUNTERS_PACKETS', 'be64'), ('CTA_COUNTERS_BYTES', 'be64'), ('CTA_COUNTERS32_PACKETS', 'be32'), ('CTA_COUNTERS32_BYTES', 'be32'), ) class cta_secctx(nla): nla_map = ( ('CTA_SECCTX_UNSPEC', 'none'), ('CTA_SECCTX_NAME', 'asciiz'), ) class cta_timestamp(nla): nla_map = ( ('CTA_TIMESTAMP_UNSPEC', 'none'), ('CTA_TIMESTAMP_START', 'be64'), ('CTA_TIMESTAMP_STOP', 'be64'), ) class cta_filter(nla): nla_flags = NLA_F_NESTED nla_map = ( ('CTA_FILTER_UNSPEC', 'none'), ('CTA_FILTER_ORIG_FLAGS', 'uint32'), ('CTA_FILTER_REPLY_FLAGS', 'uint32'), ) class cta_labels(nla): fields = [('value', 'QQ')] def encode(self): if not isinstance(self['value'], tuple): self['value'] = ( self['value'] & 0xFFFFFFFFFFFFFFFF, self['value'] >> 64, ) nla.encode(self) def decode(self): nla.decode(self) if isinstance(self['value'], tuple): self['value'] = (self['value'][0] & 0xFFFFFFFFFFFFFFFF) | ( self['value'][1] << 64 ) class cta_synproxy(nla): nla_map = ( ('CTA_SYNPROXY_UNSPEC', 'none'), ('CTA_SYNPROXY_ISN', 'be32'), ('CTA_SYNPROXY_ITS', 'be32'), ('CTA_SYNPROXY_TSOFF', 'be32'), ) FILTER_FLAG_CTA_IP_SRC = 1 << 0 FILTER_FLAG_CTA_IP_DST = 1 << 1 FILTER_FLAG_CTA_TUPLE_ZONE = 1 << 2 FILTER_FLAG_CTA_PROTO_NUM = 1 << 3 FILTER_FLAG_CTA_PROTO_SRC_PORT = 1 << 4 FILTER_FLAG_CTA_PROTO_DST_PORT = 1 << 5 FILTER_FLAG_CTA_PROTO_ICMP_TYPE = 1 << 6 FILTER_FLAG_CTA_PROTO_ICMP_CODE = 1 << 7 FILTER_FLAG_CTA_PROTO_ICMP_ID = 1 << 8 FILTER_FLAG_CTA_PROTO_ICMPV6_TYPE = 1 << 9 FILTER_FLAG_CTA_PROTO_ICMPV6_CODE = 1 << 10 FILTER_FLAG_CTA_PROTO_ICMPV6_ID = 1 << 11 FILTER_FLAG_ALL_CTA_PROTO = ( FILTER_FLAG_CTA_PROTO_SRC_PORT | FILTER_FLAG_CTA_PROTO_DST_PORT | FILTER_FLAG_CTA_PROTO_ICMP_TYPE | FILTER_FLAG_CTA_PROTO_ICMP_CODE | FILTER_FLAG_CTA_PROTO_ICMP_ID | FILTER_FLAG_CTA_PROTO_ICMPV6_TYPE | FILTER_FLAG_CTA_PROTO_ICMPV6_CODE | FILTER_FLAG_CTA_PROTO_ICMPV6_ID ) FILTER_FLAG_ALL = 0xFFFFFFFF class NFCTAttr(object): def attrs(self): return [] class NFCTAttrTuple(NFCTAttr): __slots__ = ( 'saddr', 'daddr', 'proto', 'sport', 'dport', 'icmp_id', 'icmp_type', 'family', '_attr_ip', '_attr_icmp', ) def __init__( self, family=socket.AF_INET, saddr=None, daddr=None, proto=None, sport=None, dport=None, icmp_id=None, icmp_type=None, icmp_code=None, ): self.saddr = saddr self.daddr = daddr self.proto = proto self.sport = sport self.dport = dport self.icmp_id = icmp_id self.icmp_type = icmp_type self.icmp_code = icmp_code self.family = family self._attr_ip, self._attr_icmp = { socket.AF_INET: ['CTA_IP_V4', 'CTA_PROTO_ICMP'], socket.AF_INET6: ['CTA_IP_V6', 'CTA_PROTO_ICMPV6'], }[self.family] def proto_name(self): return IP_PROTOCOLS.get(self.proto, None) def reverse(self): return NFCTAttrTuple( family=self.family, saddr=self.daddr, daddr=self.saddr, proto=self.proto, sport=self.dport, dport=self.sport, icmp_id=self.icmp_id, icmp_type=self.icmp_type, icmp_code=self.icmp_code, ) def attrs(self): cta_ip = [] cta_proto = [] cta_tuple = [] self.flags = 0 if self.saddr is not None: cta_ip.append([self._attr_ip + '_SRC', self.saddr]) self.flags |= FILTER_FLAG_CTA_IP_SRC if self.daddr is not None: cta_ip.append([self._attr_ip + '_DST', self.daddr]) self.flags |= FILTER_FLAG_CTA_IP_DST if self.proto is not None: cta_proto.append(['CTA_PROTO_NUM', self.proto]) self.flags |= FILTER_FLAG_CTA_PROTO_NUM if self.sport is not None: cta_proto.append(['CTA_PROTO_SRC_PORT', self.sport]) self.flags |= FILTER_FLAG_CTA_PROTO_SRC_PORT if self.dport is not None: cta_proto.append(['CTA_PROTO_DST_PORT', self.dport]) self.flags |= FILTER_FLAG_CTA_PROTO_DST_PORT if self.icmp_id is not None: cta_proto.append([self._attr_icmp + '_ID', self.icmp_id]) if self.icmp_type is not None: cta_proto.append([self._attr_icmp + '_TYPE', self.icmp_type]) if self.icmp_code is not None: cta_proto.append([self._attr_icmp + '_CODE', self.icmp_code]) if cta_ip: cta_tuple.append(['CTA_TUPLE_IP', {'attrs': cta_ip}]) if cta_proto: cta_tuple.append(['CTA_TUPLE_PROTO', {'attrs': cta_proto}]) return cta_tuple @classmethod def from_netlink(cls, family, ndmsg): cta_ip = ndmsg.get_attr('CTA_TUPLE_IP') cta_proto = ndmsg.get_attr('CTA_TUPLE_PROTO') kwargs = {'family': family} if family == socket.AF_INET: kwargs['saddr'] = cta_ip.get_attr('CTA_IP_V4_SRC') kwargs['daddr'] = cta_ip.get_attr('CTA_IP_V4_DST') elif family == socket.AF_INET6: kwargs['saddr'] = cta_ip.get_attr('CTA_IP_V6_SRC') kwargs['daddr'] = cta_ip.get_attr('CTA_IP_V6_DST') else: raise NotImplementedError(family) proto = cta_proto.get_attr('CTA_PROTO_NUM') kwargs['proto'] = proto if proto == socket.IPPROTO_ICMP: kwargs['icmp_id'] = cta_proto.get_attr('CTA_PROTO_ICMP_ID') kwargs['icmp_type'] = cta_proto.get_attr('CTA_PROTO_ICMP_TYPE') kwargs['icmp_code'] = cta_proto.get_attr('CTA_PROTO_ICMP_CODE') elif proto == socket.IPPROTO_ICMPV6: kwargs['icmp_id'] = cta_proto.get_attr('CTA_PROTO_ICMPV6_ID') kwargs['icmp_type'] = cta_proto.get_attr('CTA_PROTO_ICMPV6_TYPE') kwargs['icmp_code'] = cta_proto.get_attr('CTA_PROTO_ICMPV6_CODE') elif proto in (socket.IPPROTO_TCP, socket.IPPROTO_UDP): kwargs['sport'] = cta_proto.get_attr('CTA_PROTO_SRC_PORT') kwargs['dport'] = cta_proto.get_attr('CTA_PROTO_DST_PORT') return cls(**kwargs) def is_attr_match(self, other, attrname): l_attr = getattr(self, attrname) if l_attr is not None: r_attr = getattr(other, attrname) if l_attr != r_attr: return False return True def nla_eq(self, family, ndmsg): if self.family != family: return False test_attr = [] cta_ip = ndmsg.get_attr('CTA_TUPLE_IP') if family == socket.AF_INET: test_attr.append((self.saddr, cta_ip, 'CTA_IP_V4_SRC')) test_attr.append((self.daddr, cta_ip, 'CTA_IP_V4_DST')) elif family == socket.AF_INET6: test_attr.append((self.saddr, cta_ip, 'CTA_IP_V6_SRC')) test_attr.append((self.daddr, cta_ip, 'CTA_IP_V6_DST')) else: raise NotImplementedError(family) if self.proto is not None: cta_proto = ndmsg.get_attr('CTA_TUPLE_PROTO') if self.proto != cta_proto.get_attr('CTA_PROTO_NUM'): return False if self.proto == socket.IPPROTO_ICMP: ( test_attr.append( (self.icmp_id, cta_proto, 'CTA_PROTO_ICMP_ID') ) ) ( test_attr.append( (self.icmp_type, cta_proto, 'CTA_PROTO_ICMP_TYPE') ) ) ( test_attr.append( (self.icmp_code, cta_proto, 'CTA_PROTO_ICMP_CODE') ) ) elif self.proto == socket.IPPROTO_ICMPV6: ( test_attr.append( (self.icmp_id, cta_proto, 'CTA_PROTO_ICMPV6_ID') ) ) ( test_attr.append( (self.icmp_type, cta_proto, 'CTA_PROTO_ICMPV6_TYPE') ) ) ( test_attr.append( (self.icmp_code, cta_proto, 'CTA_PROTO_ICMPV6_CODE') ) ) elif self.proto in (socket.IPPROTO_TCP, socket.IPPROTO_UDP): ( test_attr.append( (self.sport, cta_proto, 'CTA_PROTO_SRC_PORT') ) ) ( test_attr.append( (self.dport, cta_proto, 'CTA_PROTO_DST_PORT') ) ) for val, ndmsg, attrname in test_attr: if val is not None and val != ndmsg.get_attr(attrname): return False return True def __ne__(self, other): return not self.__eq__(other) def __eq__(self, other): if not isinstance(other, self.__class__): raise NotImplementedError() if self.family != other.family: return False for attrname in ('saddr', 'daddr'): if not self.is_attr_match(other, attrname): return False if self.proto is not None: if self.proto != other.proto: return False if self.proto in (socket.IPPROTO_UDP, socket.IPPROTO_TCP): for attrname in ('sport', 'dport'): if not self.is_attr_match(other, attrname): return False elif self.proto in (socket.IPPROTO_ICMP, socket.IPPROTO_ICMPV6): for attrname in ('icmp_id', 'icmp_type', 'icmp_code'): if not self.is_attr_match(other, attrname): return False return True def __repr__(self): proto_name = self.proto_name() if proto_name is None: proto_name = 'UNKNOWN' if self.family == socket.AF_INET: r = 'IPv4(' elif self.family == socket.AF_INET6: r = 'IPv6(' else: r = 'Unkown[family={}]('.format(self.family) r += 'saddr={}, daddr={}, '.format(self.saddr, self.daddr) r += '{}('.format(proto_name) if self.proto in (socket.IPPROTO_ICMP, socket.IPPROTO_ICMPV6): r += 'id={}, type={}, code={}'.format( self.icmp_id, self.icmp_type, self.icmp_code ) elif self.proto in (socket.IPPROTO_TCP, socket.IPPROTO_UDP): r += 'sport={}, dport={}'.format(self.sport, self.dport) return r + '))' class NFCTSocket(NetlinkSocket): policy = { k | (NFNL_SUBSYS_CTNETLINK << 8): v for k, v in { IPCTNL_MSG_CT_NEW: nfct_msg, IPCTNL_MSG_CT_GET: nfct_msg, IPCTNL_MSG_CT_DELETE: nfct_msg, IPCTNL_MSG_CT_GET_CTRZERO: nfct_msg, IPCTNL_MSG_CT_GET_STATS_CPU: nfct_stats_cpu, IPCTNL_MSG_CT_GET_STATS: nfct_stats, IPCTNL_MSG_CT_GET_DYING: nfct_msg, IPCTNL_MSG_CT_GET_UNCONFIRMED: nfct_msg, }.items() } def __init__(self, nfgen_family=socket.AF_INET, **kwargs): super(NFCTSocket, self).__init__(family=NETLINK_NETFILTER, **kwargs) self.register_policy(self.policy) self._nfgen_family = nfgen_family def request(self, msg, msg_type, **kwargs): msg['nfgen_family'] = self._nfgen_family msg_type |= NFNL_SUBSYS_CTNETLINK << 8 return tuple(self.nlm_request(msg, msg_type, **kwargs)) def dump( self, mark=None, mark_mask=0xFFFFFFFF, tuple_orig=None, tuple_reply=None, ): """Dump conntrack entries Several kernel side filtering are supported: * mark and mark_mask, for almost all kernel * tuple_orig and tuple_reply, since kernel 5.8 and newer. Warning: tuple_reply has a bug in kernel, fixed only recently. tuple_orig and tuple_reply are type NFCTAttrTuple. You can give only some attribute for filtering. Example:: # Get only connections from 192.168.1.1 filter = NFCTAttrTuple(saddr='192.168.1.1') ct.dump_entries(tuple_orig=filter) # Get HTTPS connections filter = NFCTAttrTuple(proto=socket.IPPROTO_TCP, dport=443) ct.dump_entries(tuple_orig=filter) Note that NFCTAttrTuple attributes are working like one AND operator. Example:: # Get connections from 192.168.1.1 AND on port 443 TCP = socket.IPPROTO_TCP filter = NFCTAttrTuple(saddr='192.168.1.1', proto=TCP, dport=443) ct.dump_entries(tuple_orig=filter) """ if tuple_orig is not None: tuple_orig.attrs() # for creating flags cta_filter = { 'attrs': [['CTA_FILTER_ORIG_FLAGS', tuple_orig.flags]] } msg = nfct_msg.create_from( tuple_orig=tuple_orig, cta_filter=cta_filter ) elif tuple_reply is not None: tuple_reply.attrs() cta_filter = { 'attrs': [['CTA_FILTER_REPLY_FLAGS', tuple_reply.flags]] } msg = nfct_msg.create_from( tuple_reply=tuple_reply, cta_filter=cta_filter ) elif mark: msg = nfct_msg.create_from(mark=mark, mark_mask=mark_mask) else: msg = nfct_msg.create_from() return self.request( msg, IPCTNL_MSG_CT_GET, msg_flags=NLM_F_REQUEST | NLM_F_DUMP ) def stat(self): return self.request( nfct_msg(), IPCTNL_MSG_CT_GET_STATS_CPU, msg_flags=NLM_F_REQUEST | NLM_F_DUMP, ) def count(self): return self.request( nfct_msg(), IPCTNL_MSG_CT_GET_STATS, msg_flags=NLM_F_REQUEST | NLM_F_DUMP, terminate=terminate_single_msg, ) def flush(self, mark=None, mark_mask=None): msg = nfct_msg.create_from(mark=mark, mark_mask=mark_mask) return self.request( msg, IPCTNL_MSG_CT_DELETE, msg_flags=NLM_F_REQUEST | NLM_F_ACK, terminate=terminate_error_msg, ) def conntrack_max_size(self): return self.request( nfct_msg(), IPCTNL_MSG_CT_GET_STATS, msg_flags=NLM_F_REQUEST | NLM_F_DUMP, terminate=terminate_single_msg, ) def entry(self, cmd, **kwargs): """ Get or change a conntrack entry. Examples:: # add an entry ct.entry('add', timeout=30, tuple_orig=NFCTAttrTuple( saddr='192.168.122.1', daddr='192.168.122.67', proto=6, sport=34857, dport=5599), tuple_reply=NFCTAttrTuple( saddr='192.168.122.67', daddr='192.168.122.1', proto=6, sport=5599, dport=34857)) # set mark=5 on the matching entry ct.entry('set', mark=5, tuple_orig=NFCTAttrTuple( saddr='192.168.122.1', daddr='192.168.122.67', proto=6, sport=34857, dport=5599)) # get an entry ct.entry('get', tuple_orig=NFCTAttrTuple( saddr='192.168.122.1', daddr='192.168.122.67', proto=6, sport=34857, dport=5599)) # delete an entry ct.entry('del', tuple_orig=NFCTAttrTuple( saddr='192.168.122.1', daddr='192.168.122.67', proto=6, sport=34857, dport=5599)) """ msg_type, msg_flags = { 'add': [IPCTNL_MSG_CT_NEW, NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE], 'set': [IPCTNL_MSG_CT_NEW, NLM_F_ACK], 'get': [IPCTNL_MSG_CT_GET, NLM_F_ACK], 'del': [IPCTNL_MSG_CT_DELETE, NLM_F_ACK], }[cmd] if msg_type == IPCTNL_MSG_CT_DELETE and not ( 'tuple_orig' in kwargs or 'tuple_reply' in kwargs ): raise ValueError('Deletion requires a tuple at least') return self.request( nfct_msg.create_from(**kwargs), msg_type, msg_flags=NLM_F_REQUEST | msg_flags, terminate=terminate_error_msg, )