From 4de1748c6fa46e66707d2a0a75a102ebc73d3547 Mon Sep 17 00:00:00 2001 From: bol-van Date: Thu, 13 Jun 2024 12:17:03 +0300 Subject: [PATCH] tpws: --split-tls option. sniext mode for --tlsrec --- tpws/params.h | 9 +-- tpws/tamper.c | 83 +++++++++++++---------- tpws/tpws | Bin 0 -> 73416 bytes tpws/tpws.c | 179 +++++++++++++++++++++++++++++--------------------- 4 files changed, 158 insertions(+), 113 deletions(-) create mode 100644 tpws/tpws diff --git a/tpws/params.h b/tpws/params.h index 13bc36a..793c30c 100644 --- a/tpws/params.h +++ b/tpws/params.h @@ -13,8 +13,8 @@ #define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3 #define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60 -enum splithttpreq { split_none = 0, split_method, split_host }; -enum tlsrec { tlsrec_none = 0, tlsrec_sni, tlsrec_pos }; +enum httpreqpos { httpreqpos_none = 0, httpreqpos_method, httpreqpos_host }; +enum tlspos { tlspos_none = 0, tlspos_sni, tlspos_sniext, tlspos_pos }; enum bindll { unwanted=0, no, prefer, force }; #define MAX_BINDS 32 @@ -47,9 +47,10 @@ struct params_s bool hostcase, hostdot, hosttab, hostnospace, methodspace, methodeol, unixeol, domcase; int hostpad; char hostspell[4]; - enum splithttpreq split_http_req; - enum tlsrec tlsrec; + enum httpreqpos split_http_req; + enum tlspos tlsrec; int tlsrec_pos; + enum tlspos split_tls; bool split_any_protocol; int split_pos; bool disorder, disorder_http, disorder_tls; diff --git a/tpws/tamper.c b/tpws/tamper.c index 0f6a468..a483805 100644 --- a/tpws/tamper.c +++ b/tpws/tamper.c @@ -9,7 +9,7 @@ #include // pHost points to "Host: ..." -bool find_host(uint8_t **pHost,uint8_t *buf,size_t bs) +static bool find_host(uint8_t **pHost,uint8_t *buf,size_t bs) { if (!*pHost) { @@ -23,6 +23,24 @@ bool find_host(uint8_t **pHost,uint8_t *buf,size_t bs) return !!*pHost; } +static size_t tls_pos(enum tlspos tpos_type, size_t tpos_pos, const uint8_t *tls, size_t sz, uint8_t type) +{ + size_t elen; + const uint8_t *ext; + switch(tpos_type) + { + case tlspos_sni: + case tlspos_sniext: + if (TLSFindExt(tls,sz,0,&ext,&elen,false)) + return (tpos_type==tlspos_sni) ? ext-tls+6 : ext-tls+1; + break; + case tlspos_pos: + return tpos_pos; + } + return 0; +} + + static const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS /","PUT /","DELETE /","CONNECT /","TRACE /",NULL }; // segment buffer has at least 5 extra bytes to extend data block void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,size_t *size, size_t *split_pos, uint8_t *split_flags) @@ -200,10 +218,10 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si } switch (params.split_http_req) { - case split_method: + case httpreqpos_method: *split_pos = method_len - 1 + params.methodeol + (params.methodeol && !params.unixeol); break; - case split_host: + case httpreqpos_host: if (find_host(&pHost,segment,*size)) *split_pos = pHost + 6 - bRemovedHostSpace - segment; break; @@ -220,7 +238,7 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si } else if (IsTLSClientHello(segment,*size,false)) { - size_t tpos=0,elen; + size_t tpos=0,spos=0; const uint8_t *ext; if (!ctrack->l7proto) ctrack->l7proto=TLS; @@ -239,39 +257,38 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si } else { - switch(params.tlsrec) + spos = tls_pos(params.split_tls, params.split_pos, segment, *size, 0); + + if ((5+*size)<=segment_buffer_size) { - case tlsrec_sni: - if (TLSFindExt(segment,*size,0,&ext,&elen,false)) - tpos = ext-segment+1; // between typical 1st and 2nd char of hostname - break; - case tlsrec_pos: - tpos = params.tlsrec_pos; - break; - default: - break; - } - if (tpos && (5+*size)<=segment_buffer_size) - { - // construct 2 TLS records from one - uint16_t l = pntoh16(segment+3); // length - if (l>=2) + tpos = tls_pos(params.tlsrec, params.tlsrec_pos, segment, *size, 0); + if (tpos>5) { - // length is checked in IsTLSClientHello and cannot exceed buffer size - if (tpos>=l) tpos=1; - VPRINT("making 2 TLS records at pos %zu",tpos) - memmove(segment+5+tpos+5,segment+5+tpos,*size-(5+tpos)); - segment[5+tpos] = segment[0]; - segment[5+tpos+1] = segment[1]; - segment[5+tpos+2] = segment[2]; - phton16(segment+5+tpos+3,l-tpos); - phton16(segment+3,tpos); - *size += 5; + // construct 2 TLS records from one + uint16_t l = pntoh16(segment+3); // length + if (l>=2) + { + // length is checked in IsTLSClientHello and cannot exceed buffer size + if ((tpos-5)>=l) tpos=5+1; + VPRINT("making 2 TLS records at pos %zu",tpos) + memmove(segment+tpos+5,segment+tpos,*size-tpos); + segment[tpos] = segment[0]; + segment[tpos+1] = segment[1]; + segment[tpos+2] = segment[2]; + phton16(segment+tpos+3,l-(tpos-5)); + phton16(segment+3,tpos-5); + *size += 5; + // split pos present and it is not before tlsrec split. increase split pos by tlsrec header size (5 bytes) + if (spos && spos>=tpos) spos+=5; + } } } - - if (params.split_pos < *size) - *split_pos = params.split_pos; + + if (spos && spos < *size) + { + VPRINT("split pos %zu",spos); + *split_pos = spos; + } if (params.disorder_tls) *split_flags |= SPLIT_FLAG_DISORDER; if (params.oob_tls) *split_flags |= SPLIT_FLAG_OOB; diff --git a/tpws/tpws b/tpws/tpws new file mode 100644 index 0000000000000000000000000000000000000000..9aa91f122066e54cd14d32cf142f2b86e70e437a GIT binary patch literal 73416 zcmeF4dwf*Y_2_4k3dWi$f`oY9Fy1)-uM1|n1*5oQEMU~pzI zr^f;6yRBAgt+my*wpCtLOn4+>YYX@&6|La&3=u(8L=p`8GcN?Jg&_S>D^0eED%*zZ;LT%dI}n;p@mL z=8|&FPPt~MT>9JN*faf|wx`G_|0^7OW`Ad^on3CKQ!e|v8lLh=e@h+mx$1-PYQ?=2W&ps-_?$O>F;!XS5Qvu@<07J=JZ_Y)Yol0D5vmv8l7*ul{}uar%$`_{PWJ9 zKKZQa(`H8Ioi(rG{IkwKZ}6O1gU?YSh+HN7mtvzXA1lq#EI7xEo}8!+r}@dfe$IWN zKknV{72G!Wc4KFsw&TC)w`ue@v&6T)E8VW-TdZ+PH}s>rsdrj8_BpW|J}-2GKeZeApXvtRqZ@hpb%TGd z8~iEV;6vTWIlmiy@9jp;Z@S?h?uP&NZuoEPhW_eq@HcdWf2SLH-tUHfWjFNxZt&-K z!{_;K=v%wN-_{ME7rU`fv>W>Q-L%W&-QeeTBhQoF;48b~b5l3+oR0h@{LlV0b;Eyq zH+T~U-xeQscT;b&8#(K`;q!}b>Rs6lpPFv!?bQwa;%@5wxEuW6yOHPYZtA_cn|g4yKdZtxA=@bA+N|0UhfPwR$Wrn4pd&;Ib4@q& z3%ik1))U|6pKaaH--ANmM*mqi_y@b;)1P|#dXD#aPJ@6?dLI1@*C#7X*FSGN^i^5( zA5vWSlw{#O%sX$FX=b@+VsK3D#K}`;Pq}H@obZ&{V`@iCpEYyJm`OKIpW>M~@unHG zW=@DV&vd6g$&YTuLXJQ(X`s$^=^F8%bCr_L0xoJxH zrrEP1jdMIRrp(|URn>=YYn(DMJZt)_xl?9OoIb0b!c)Q%XNG4r%H4UBCN@l)IcfT| z+oyOMC_V>d-#l~D4DMuPpEz+E*viU@4Rh)z&1^s-(bKWlj7igGf@yFGDdNp&^vs!d z6OzEjGp%8wunfgg})DdUhH-(%9%2d=45%!k)$m)}7NheOf)H z#%!L3hUt+xQ$_JPlvEWq-lp2n2B#w(*vS!en?7Yqqo;mSqX;l@B9hcM-lke;&J=_d z7z-c+!qLbxZ<;u3=JeYzvfWCQ65+U?X)A2dID1z8j7f8D_S}e_JPlK3&z?2glUB+x z$lOWO!We4y%}9bf&-P54RgaBq0aTm8ce?mEvQ7!lo<3~`1rU_Fl$O&Pq)HSI&$cT- z^+}UG*hXrbR9`=((RPx#G?_@4E--N-Br|7;%T5YUqt&oq{nSag;XG={_{bdFM<^)G zjQXC2xwEI?ppCOdP+BQGss3g$)x?HL)9}lTMbh-)X?WkLP;mH&iRTQi%v_b9m$^Kb zbz_>K6MI1hH#Bo~Zs+ZD2X|hdGuTBUF(!w#VJ>Ta`J2l+RQ}4EuqS_QT-U$(--^xk z^!gUOy^@vkz4`y&{CYaI3q>B+ZXRjsUY?^I&Yj#kC9faFK$0c=kE)vx=Y3 zbI5_iieH|`hp*?#j-&f^xJST`UeA4-xbo}4xQ+X5oM9;8$ef zS3CITEPR`T-EKsn;h%Bv%~|+0 z4t{4AzQw_NPVFjxn}aXO!oTL=tFrLB9Q+Mg_`ME3nuR~?;8$efbDj9voP|Hy!M}8p zEvMvK)4n2pv&Ds%oMQU3-Gv{LM)JMWg&*g_TQ2-$7e2kdkon`o%M?C(w}@6 zUSvvt3SD>x-pr@ih3}ogdORgAd>`F8qZq{BjrmA{YK47k-!vzruz0 zyYNrC@E5!A&$#fHxbUl8_$n8^*@X|d@GrUW!(I3-F8l}=e!B}_?ZWSL;cHxY%Y`55 z!tZn8N4f9^U3lGv_c-I4#Q2~KpYOt7>cSVg@XnG+-7R+ELoWIf7rxeoALPPc?!pgo z;YYjh6)t?83t#2JU*W>*F8q})e4Pt_l?y-Kg&*U>-{8WJb>XMF@K?L=jV}Cn7k-`# z|3eo(>cU^+!Z*3_lG{#ymb>uRrjdL<QVh{GVCiGwsAfdhFwT z-SlnVOL{ZW9M0+3qQ^GoZ%_<7hCas8wEZ2Y{)#W{B#+Qfl{@=WyE-~LmMd6NUHem8 zGq5C-_orGiuq2ZAr~Z_IC4sy@^~($_iR1mLpJZT381GLl&cKpH*q^#314|-)e`-<& zmW1*C)D;<662<#dfeb7O`u(Z$4BSV-12eEBiub4bW?)GW?@xI%uq1}}r#?NB)>jh3 z=%0Zl5sdyBSQ5bKpMfRui~bo{629o4fhEz4{ux*jyy%~SC9#YC8CVj!=%0Zlk&FHr zSQ5DCpMfQDi~bo{61MwO12eEBYSBLfOM({tGq5CP(f@E-{}Ki7%D@8^yfp($0v7!< zuq0m5KLbm`75y`?BwEow151Jx{WGv6R?$BLOF|X>Gq5C5(LV!A0u}u;up~~=KLeks z;DH%f5~b*$fh9qT{ux*jqv-!lT7TKtq5U(kBuHuh3@nLJ^v}SO5JmqCEQwI`&%lxZ zMgI&eiBI&;z>@Gp{|qdNPV~>flHf%D3@nLF^v}SO&_w?XEQw6oKLbkw6a6!=BrefE z153gZ{l8A@U!~w(8CVjO=%0ZlF^T>eSQ3)xpMfP2iT)W_5|HShfhF;X{ux*jj_99( zCDDlf8CVjG=%0Zlv55W|SQ3ippMgUP9+-h8fr$PYSQ3ZmpMfP|i2jGt`b(ma_RqkQ zAVmKREQvw%&%lxpME?vdi9qzvz>)w&{|qdNKlIPQ;}m>L29^XM`e$HC{GopamV_Vr zXJAS6p??OJ1Rw36fhDnr{%M$K|4K@tJ?$j%9r*Vjc7=bP1wWDn-=761v*1J)ydVpX zWWh7C;3-+~by@J(EVwocuE~P^S@6&-_^d4W)GYXfEVw8OF35s?S@7Wxy4v@PEO<{A z{6QA{b{7147W_&UyeSKQAq##k3;ul;{Oc_Eku3QBEI643C$iuLS#Tr^o{R4 zFlOvk`r?n}^rIf@Q|jUR$y|?TvTo*`DibcoK4gTA`tLo!T`f_>^gQZs{SqMDPfz+^;L3WOIaj<{i(kP_J^6g; z4R9)NUQ@-=K{xIwt@uoTO0V}_42MLs)^rss06jUq^aefIFOdhMbshZCjlH3y|4oJ} z>r}>S-K;LHKqwKGd)1}IdNN+R(*cI0L1WN&%1ZoIkf`-aEU z8ZTx21h3yQjADYn@O2&WHb*#)#tOG3?_F#@Z%>7^E+z*5!~_`d<5-O7Ct*%xd$5(`lia z#Eym4R9jM`tsGq#Opb1@H4f^@p*O#U(WKeyxH&-n6w9A}9p|;0V@h=>%Ab&?w6;l; z#5R`LO2n}+Z6h;plo>rB)tl87>&e>WP0f0;E>E=s%HTiNYD|Z+@rQ7~z#3_whHB#| z)EtVCI<*wH-5CWdjbkf1JSTOE%`ape!luhUr<6#gC&!f5)s(-l8)HgKVh3}yxPk1{ zE5@7$QBCDdCEBtjTp?XQgzPBaQ3UwTT1aPXgMi z9@Lf-xm#)r|3_+yY){v;@t~^dCEW~{7As>n7#9c3k$Iv^oiQ@cItN{JGlUz`u5F9s z7?;{S)nz*yVwJs(#kO1CiivdNZ>hWJ^V&&Ow$`x?-q_cL*rB+zuyY{iP+;Bi5JdUchjk)C1hJ^%V6V28H^OFzpsHzO)V= zW5?g&F9{j@s3T}>YJXhxjopEq+Fc7Ekw!~g#)ZgK?Z`A4ICYcq z#i+<5_XgSb61v>GOx^P&8;=;9jBshc)KVv+S@ik+cnNW&P{MF>=%v4MOimxXoK_E*<4U9}B(`Zw_Yk3#OJ8ogbmA=#lv$E4 zV-280YCTx(q^Q(Kyxzr4>)Fr2cewC`$YMI{i(+a$c~!oZgJq?coKBOs#nSE*SgqQk z+Q^llTAUh<3y2-zdxh}5R`~v=lW*FUev2}xXZYjDLCm1KL&$p0V-jAJQw0!q{8p-S!UjgBkH6MWjLi?FoP^HTzVyGJ+MM#7r25ZFr6V^W)i0Q;;RBFv0;WaRujUz&S? zYVM^8Y6=-&RU7*$H(){jfBQ<=hAv+xPG~L0d@?QA z0KHjV8d5V4DP!A15&!hduPCR=Gk}DwSN2lDJyL;kvUik-BHtLQFir6oRAZKy9GZjL zN=Iuo4xU<}WPX<$_b~%=l(!z?mTiI5t7@{#hq_o1hok=yjm2md?6v5_J6u?Ym{Z5h;!O4|3%_c3bS- zoY?w2?T{fkc9Z^N9Revnk| zca_w5HZ?MmvdN&upB2+2!=-hs93TsFzq~nQ?6-dKi8SWk01JvoxvWXh8SjEP=3n+P zLaAw%woKLwwUr;=8lr67k5v`>mQlsusWn~2`_RB0>B^g(ZcwyKh(;lYs$!!xOjYr| z7MBp%pldUkfgX5~fXO^-db11wb(ZD$y_%s#{eNM>;RzpW4t<6T)Bgm2ttrHEi9%1) zGf*S>cPcVUrH<2}|5svSt!5v6?>a<{`Y#j-wRnub+}`X@JKjH0*7T(; zG0Wa$qgSs#V9lQ;ME+B-ON(_bp&_E>e`ZR=o#}L z5iik}-UfhH5UqqL?aJGvYg}(fir*lub&K$wZb!1XAgT~{Ef$gh@htH@9jYw2IKG^O zB(<6G8WBfInLZ%eUj{l&Ad#p2d5T9UzV>WbrFn!!+|g26W@ylVjFGH=h)frPu;K_K z^AO2zmhTA~Td&vAAol*gx-m5j(VHo;i_#rMzk1E%`Mh&}27dFKVlm%(`Kmk^E@JC! z2}H7W)~jQuGmdZQoIm|k(GR^xzRHg1#y-8}lS}lLgSoo5Ro{AqHL>X%>oCag*lEw} z(&a_IsQ(eldLn0xW%NG>N}BJ3a39_Dj|8xSyU}MdvbOpn(0Q+;tjAqGHJ6)?Ji@PY zy&p5&^W9cU*OkzTMx((>eY49 z1bUkc=a{JIS9l-``8ADz&{>z@e*vRef^1)0oDn*de6}>I?tUqwo~O!bL2EKf(M1We z#g@*slo?DJS^eqexlCr`U#W88(!%zJ&i0YmtM5T0qDrD89MO#hxYxP5_seSIVA(#& zEet9@fG}_#V*Mkf1d1K>&b^wDKZMeHS*vcGTO;*}1;7?dxSD_oLo9$z*uf@taM9eS zf{WYaF3sO&vF#g#xm7D7;D{gSMvbTaoxp13 z=uqu%-GiWEPGoanKvHdqz9@3=yU)mpo#y6y( z5J}h84X%ps2{-D=kzU+N8WSVthmtpUSigg9P+E6K_(r|ugPiuGg-@%pc&qI+nYAg57Et6$1EAT^N!QU$Pio8&3d@eeL zx=fKVLVL>PU($bq#%Doeo1WMfp4QsKQ?0Gi8UnGea>66zt9O{0t?!wrH2oVP;~mES zwiaoHwRo>5_11^B-gGpCwlpG+v_tzqm>_ zzQ$q|B1D&l98})inpf&kf@$$LV5fxB;_X}pjStog;#-L%!aoV3q=OeyFwhtF{%9fgl6}xSR zf4+yEkCJxC*`C6hBQ<_5;3D3EOB-R0=i~23Hd4~Te zNuK8Llc~d4GTnaBMS1D_%gk|kNZ*ut+jZZ(G_UfqJT1`=UN#@qq&P_&l|<)D^F!uv zQl7_z&K;Srm%kkBwMB~$h1@Ys;se-a=*8}qbgvVkzmRe34${}IY+vuGWN z>dGt8;1?jwEBjSmm8ZquBUUs<% zxl=_S*`oY{-H%Kki}a-7#!t9zgLNjdyBt`Jx4K!h;dYo+j>`{gt7&BtKH7cFgt#h? zS?~cy@y$zo(z@dk@}FJc*+>{2x-yB1QPbuLvA&r*L;gwUa(buqQJKTeq< z%A^yfs!R^mSRL?}GK(lAPidpo^gX;?M$3gIHE|a0WEt&zR8XsV1;>7Mj%tyqZzD$hKxFi~ z!Kwn*tH>=w{S|t0s<-_q83$~>hgDCHoSLD0+MzsMD5)7bYr7%}@0g%W=WLfaC!f(N3+D}|z`@fOaSRbm~Iai~8 zY0^!Ih5Q3`^X7blOFkSTuSoz(hl})hmlc#YsCZ$o4|QWdOT<^M(vt%&z*tvcEEyRr z17}xVb|=;fC8zcXR=z#EUrPL)^-^pTk?d_Pz5$TU?i$aq679bA!+J5+LUb!KBytXnw`c=u?y-1ShcE$;PY`L-^&jYzqYRIkws2blSjvn#d z>Wf}-Ot`1h?$Jfw+{kAfg~&->(GfkAGxwwDA|DDd|HyR~YN+nhEB9#+xLrcpqlR>1 z?8q6~k}X(^0lfzyYh2HkorQsxck`=zZ4pqu^@m{5OIX|`OExIa2qo*hAP4J}t=gSz zYx2sO*ij zn3elxU)s>J9=|%6dux>*Ys+arKI4xK)s-)Y&yf_D_e(`EKwCAJrN5OYD`AN98d_Re z_#c4(t=rJ7+IUILvl5#FG-@qV*!!CUB`x8jb)zz93~7JIX}2}vD(zcsdx(Lt$3H=- zV@JlTViw0L7=Y%KzN42!};FEwV(AE`#V|5JiDOri(qm6p}Bm!ya$UzDD=9 z+4ks9non$?t=gtn?w=jdV~28Yy-3-D(2bupaHQfQy=;9jIV?}zJYHs+dTe)|w(5dV z@+Qon@*jHTmRnyX22NmzkyKcEJ_ri)<=u*#^zewA%wmaP`5Ia_QRg1L(wh5<9hvpS z=J0ww8Nl~bx;E01SaGs7l>T47jd(&A4EOWtX1>|yPfdNk&$x=azaFt#^Uh#;CpJ~j zNo3kj?5og@-wNz@ae)Jbg{^EhjtP)()002SC)q(ieN~TrbWkt*iXbsQmWsNj7c6zk zn_E)3OzHYWsZzFX`#5RdTEo)YhBLQSsa_aY8y~H$1G38BkQg?vR^s^-Hu~btrtcM^ zOt=^MR&Ck$5FT$y+zG9cSaNc*q&iPcJ+(v(0=g^9Dp%e@sx$trDo}fq)MmZ(x>R)A zgE9XM*u(l!SlT14-2Uocb{e1stlEN3{HTM&NF$1YJ*n%t#?DT@ON;+SQISbV+{7Kx zv~Z0*tbF2R>vmgTZj*f!FO{Ld(o3MDbCAO^QjEdr>B6>|GB`B^@RJ%6W!8Gkk@~)> z4gX@U)e8da+E>BWDQr~a0beHgYVfA-7h7!`iIAy(G0HCI{_o^|9!fFtz64JBs}hu? zM&6o2xMVV6wIXTJIAO!_kNcti7D*4z=qhP3lG?5{jRMvW5v7ZN$=rKL7xx%c-fTA^ zsqhoz5YZsov5&okVAEpbkO`Ub%J>>D%0JncUt&Fja5DcYl;m+f3En=|p4U`DzPy

D7N8E>6j-G7Ocsc00m#D8#r?884 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 literal 0 HcmV?d00001 diff --git a/tpws/tpws.c b/tpws/tpws.c index 22f17da..e672fc1 100644 --- a/tpws/tpws.c +++ b/tpws/tpws.c @@ -172,7 +172,8 @@ static void exithelp(void) " --hostlist-auto-debug=\t; debug auto hostlist positives\n" "\nTAMPER:\n" " --split-http-req=method|host\t\t; split at specified logical part of plain http request\n" - " --split-pos=\t\t; split at specified pos. split-http-req takes precedence for http.\n" + " --split-tls=sni|sniext\t\t\t; split at specified logical part of TLS ClientHello\n" + " --split-pos=\t\t; split at specified pos. split-http-req or split-tls take precedence for http.\n" " --split-any-protocol\t\t\t; split not only http and https\n" #if defined(BSD) && !defined(__APPLE__) " --disorder[=http|tls]\t\t\t; when splitting simulate sending second fragment first (BSD sends entire message instead of first fragment, this is not good)\n" @@ -191,7 +192,7 @@ static void exithelp(void) " --methodspace\t\t\t\t; add extra space after method\n" " --methodeol\t\t\t\t; add end-of-line before method\n" " --unixeol\t\t\t\t; replace 0D0A to 0A\n" - " --tlsrec=sni\t\t\t\t; make 2 TLS records. split at SNI. don't split if SNI is not present\n" + " --tlsrec=sni|sniext\t\t\t; make 2 TLS records. split at specified logical part. don't split if SNI is not present\n" " --tlsrec-pos=\t\t\t; make 2 TLS records. split at specified pos\n" #ifdef __linux__ " --mss=\t\t\t\t; set client MSS. forces server to split messages but significantly decreases speed !\n" @@ -253,6 +254,28 @@ void save_default_ttl(void) } } +bool parse_httpreqpos(const char *s, enum httpreqpos *pos) +{ + if (!strcmp(s, "method")) + *pos = httpreqpos_method; + else if (!strcmp(s, "host")) + *pos = httpreqpos_host; + else + return false; + return true; +} +bool parse_tlspos(const char *s, enum tlspos *pos) +{ + if (!strcmp(s, "sni")) + *pos = tlspos_sni; + else if (!strcmp(s, "sniext")) + *pos = tlspos_sniext; + else + return false; + return true; +} + + void parse_params(int argc, char *argv[]) { int option_index = 0; @@ -302,40 +325,41 @@ void parse_params(int argc, char *argv[]) { "hostpad",required_argument,0,0 },// optidx=21 { "domcase",no_argument,0,0 },// optidx=22 { "split-http-req",required_argument,0,0 },// optidx=23 - { "split-pos",required_argument,0,0 },// optidx=24 - { "split-any-protocol",optional_argument,0,0},// optidx=25 - { "disorder",optional_argument,0,0 },// optidx=26 - { "oob",optional_argument,0,0 },// optidx=27 - { "oob-data",required_argument,0,0 },// optidx=28 - { "methodspace",no_argument,0,0 },// optidx=29 - { "methodeol",no_argument,0,0 },// optidx=30 - { "hosttab",no_argument,0,0 },// optidx=31 - { "unixeol",no_argument,0,0 },// optidx=32 - { "tlsrec",required_argument,0,0 },// optidx=33 - { "tlsrec-pos",required_argument,0,0 },// optidx=34 - { "hostlist",required_argument,0,0 },// optidx=35 - { "hostlist-exclude",required_argument,0,0 },// optidx=36 - { "hostlist-auto",required_argument,0,0}, // optidx=37 - { "hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=38 - { "hostlist-auto-fail-time",required_argument,0,0}, // optidx=39 - { "hostlist-auto-debug",required_argument,0,0}, // optidx=40 - { "pidfile",required_argument,0,0 },// optidx=41 - { "debug",optional_argument,0,0 },// optidx=42 - { "local-rcvbuf",required_argument,0,0 },// optidx=43 - { "local-sndbuf",required_argument,0,0 },// optidx=44 - { "remote-rcvbuf",required_argument,0,0 },// optidx=45 - { "remote-sndbuf",required_argument,0,0 },// optidx=46 - { "socks",no_argument,0,0 },// optidx=47 - { "no-resolve",no_argument,0,0 },// optidx=48 - { "resolver-threads",required_argument,0,0 },// optidx=49 - { "skip-nodelay",no_argument,0,0 },// optidx=50 - { "tamper-start",required_argument,0,0 },// optidx=51 - { "tamper-cutoff",required_argument,0,0 },// optidx=52 + { "split-tls",required_argument,0,0 },// optidx=24 + { "split-pos",required_argument,0,0 },// optidx=25 + { "split-any-protocol",optional_argument,0,0},// optidx=26 + { "disorder",optional_argument,0,0 },// optidx=27 + { "oob",optional_argument,0,0 },// optidx=28 + { "oob-data",required_argument,0,0 },// optidx=29 + { "methodspace",no_argument,0,0 },// optidx=30 + { "methodeol",no_argument,0,0 },// optidx=31 + { "hosttab",no_argument,0,0 },// optidx=32 + { "unixeol",no_argument,0,0 },// optidx=33 + { "tlsrec",required_argument,0,0 },// optidx=34 + { "tlsrec-pos",required_argument,0,0 },// optidx=35 + { "hostlist",required_argument,0,0 },// optidx=36 + { "hostlist-exclude",required_argument,0,0 },// optidx=37 + { "hostlist-auto",required_argument,0,0}, // optidx=38 + { "hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=39 + { "hostlist-auto-fail-time",required_argument,0,0}, // optidx=40 + { "hostlist-auto-debug",required_argument,0,0}, // optidx=41 + { "pidfile",required_argument,0,0 },// optidx=42 + { "debug",optional_argument,0,0 },// optidx=43 + { "local-rcvbuf",required_argument,0,0 },// optidx=44 + { "local-sndbuf",required_argument,0,0 },// optidx=45 + { "remote-rcvbuf",required_argument,0,0 },// optidx=46 + { "remote-sndbuf",required_argument,0,0 },// optidx=47 + { "socks",no_argument,0,0 },// optidx=48 + { "no-resolve",no_argument,0,0 },// optidx=49 + { "resolver-threads",required_argument,0,0 },// optidx=50 + { "skip-nodelay",no_argument,0,0 },// optidx=51 + { "tamper-start",required_argument,0,0 },// optidx=52 + { "tamper-cutoff",required_argument,0,0 },// optidx=53 #if defined(BSD) && !defined(__OpenBSD__) && !defined(__APPLE__) - { "enable-pf",no_argument,0,0 },// optidx=53 + { "enable-pf",no_argument,0,0 },// optidx=54 #elif defined(__linux__) - { "mss",required_argument,0,0 },// optidx=53 - { "mss-pf",required_argument,0,0 },// optidx=54 + { "mss",required_argument,0,0 },// optidx=54 + { "mss-pf",required_argument,0,0 },// optidx=55 #ifdef SPLICE_PRESENT { "nosplice",no_argument,0,0 },// optidx=55 #endif @@ -498,18 +522,22 @@ void parse_params(int argc, char *argv[]) params.tamper = true; break; case 23: /* split-http-req */ - if (!strcmp(optarg, "method")) - params.split_http_req = split_method; - else if (!strcmp(optarg, "host")) - params.split_http_req = split_host; - else + if (!parse_httpreqpos(optarg, ¶ms.split_http_req)) { fprintf(stderr, "Invalid argument for split-http-req\n"); exit_clean(1); } params.tamper = true; break; - case 24: /* split-pos */ + case 24: /* split-tls */ + if (!parse_tlspos(optarg, ¶ms.split_tls)) + { + fprintf(stderr, "Invalid argument for split-tls\n"); + exit_clean(1); + } + params.tamper = true; + break; + case 25: /* split-pos */ i = atoi(optarg); if (i>0) params.split_pos = i; @@ -520,10 +548,10 @@ void parse_params(int argc, char *argv[]) } params.tamper = true; break; - case 25: /* split-any-protocol */ + case 26: /* split-any-protocol */ params.split_any_protocol = true; break; - case 26: /* disorder */ + case 27: /* disorder */ if (optarg) { if (!strcmp(optarg,"http")) params.disorder_http=true; @@ -538,7 +566,7 @@ void parse_params(int argc, char *argv[]) params.disorder = true; save_default_ttl(); break; - case 27: /* oob */ + case 28: /* oob */ if (optarg) { if (!strcmp(optarg,"http")) params.oob_http=true; @@ -552,7 +580,7 @@ void parse_params(int argc, char *argv[]) else params.oob = true; break; - case 28: /* oob-data */ + case 29: /* oob-data */ { size_t l = strlen(optarg); unsigned int bt; @@ -565,35 +593,33 @@ void parse_params(int argc, char *argv[]) else params.oob_byte = (uint8_t)bt; } break; - case 29: /* methodspace */ + case 30: /* methodspace */ params.methodspace = true; params.tamper = true; break; - case 30: /* methodeol */ + case 31: /* methodeol */ params.methodeol = true; params.tamper = true; break; - case 31: /* hosttab */ + case 32: /* hosttab */ params.hosttab = true; params.tamper = true; break; - case 32: /* unixeol */ + case 33: /* unixeol */ params.unixeol = true; params.tamper = true; break; - case 33: /* tlsrec */ - if (!strcmp(optarg, "sni")) - params.tlsrec = tlsrec_sni; - else + case 34: /* tlsrec */ + if (!parse_tlspos(optarg, ¶ms.tlsrec)) { fprintf(stderr, "Invalid argument for tlsrec\n"); exit_clean(1); } params.tamper = true; break; - case 34: /* tlsrec-pos */ + case 35: /* tlsrec-pos */ if ((params.tlsrec_pos = atoi(optarg))>0) - params.tlsrec = tlsrec_pos; + params.tlsrec = tlspos_pos; else { fprintf(stderr, "Invalid argument for tlsrec-pos\n"); @@ -601,7 +627,7 @@ void parse_params(int argc, char *argv[]) } params.tamper = true; break; - case 35: /* hostlist */ + case 36: /* hostlist */ if (!strlist_add(¶ms.hostlist_files, optarg)) { fprintf(stderr, "strlist_add failed\n"); @@ -609,7 +635,7 @@ void parse_params(int argc, char *argv[]) } params.tamper = true; break; - case 36: /* hostlist-exclude */ + case 37: /* hostlist-exclude */ if (!strlist_add(¶ms.hostlist_exclude_files, optarg)) { fprintf(stderr, "strlist_add failed\n"); @@ -617,7 +643,7 @@ void parse_params(int argc, char *argv[]) } params.tamper = true; break; - case 37: /* hostlist-auto */ + case 38: /* hostlist-auto */ if (*params.hostlist_auto_filename) { fprintf(stderr, "only one auto hostlist is supported\n"); @@ -649,7 +675,7 @@ void parse_params(int argc, char *argv[]) params.hostlist_auto_filename[sizeof(params.hostlist_auto_filename) - 1] = '\0'; params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice. break; - case 38: /* hostlist-auto-fail-threshold */ + case 39: /* hostlist-auto-fail-threshold */ params.hostlist_auto_fail_threshold = (uint8_t)atoi(optarg); if (params.hostlist_auto_fail_threshold<1 || params.hostlist_auto_fail_threshold>20) { @@ -657,7 +683,7 @@ void parse_params(int argc, char *argv[]) exit_clean(1); } break; - case 39: /* hostlist-auto-fail-time */ + case 40: /* hostlist-auto-fail-time */ params.hostlist_auto_fail_time = (uint8_t)atoi(optarg); if (params.hostlist_auto_fail_time<1) { @@ -665,7 +691,7 @@ void parse_params(int argc, char *argv[]) exit_clean(1); } break; - case 40: /* hostlist-auto-debug */ + case 41: /* hostlist-auto-debug */ { FILE *F = fopen(optarg,"a+t"); if (!F) @@ -680,48 +706,48 @@ void parse_params(int argc, char *argv[]) params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0'; } break; - case 41: /* pidfile */ + case 42: /* pidfile */ strncpy(params.pidfile,optarg,sizeof(params.pidfile)); params.pidfile[sizeof(params.pidfile)-1]='\0'; break; - case 42: + case 43: params.debug = optarg ? atoi(optarg) : 1; break; - case 43: /* local-rcvbuf */ + case 44: /* local-rcvbuf */ #ifdef __linux__ params.local_rcvbuf = atoi(optarg)/2; #else params.local_rcvbuf = atoi(optarg); #endif break; - case 44: /* local-sndbuf */ + case 45: /* local-sndbuf */ #ifdef __linux__ params.local_sndbuf = atoi(optarg)/2; #else params.local_sndbuf = atoi(optarg); #endif break; - case 45: /* remote-rcvbuf */ + case 46: /* remote-rcvbuf */ #ifdef __linux__ params.remote_rcvbuf = atoi(optarg)/2; #else params.remote_rcvbuf = atoi(optarg); #endif break; - case 46: /* remote-sndbuf */ + case 47: /* remote-sndbuf */ #ifdef __linux__ params.remote_sndbuf = atoi(optarg)/2; #else params.remote_sndbuf = atoi(optarg); #endif break; - case 47: /* socks */ + case 48: /* socks */ params.proxy_type = CONN_TYPE_SOCKS; break; - case 48: /* no-resolve */ + case 49: /* no-resolve */ params.no_resolve = true; break; - case 49: /* resolver-threads */ + case 50: /* resolver-threads */ params.resolver_threads = atoi(optarg); if (params.resolver_threads<1 || params.resolver_threads>300) { @@ -729,10 +755,10 @@ void parse_params(int argc, char *argv[]) exit_clean(1); } break; - case 50: /* skip-nodelay */ + case 51: /* skip-nodelay */ params.skip_nodelay = true; break; - case 51: /* tamper-start */ + case 52: /* tamper-start */ { const char *p=optarg; if (*p=='n') @@ -745,7 +771,7 @@ void parse_params(int argc, char *argv[]) params.tamper_start = atoi(p); } break; - case 52: /* tamper-cutoff */ + case 53: /* tamper-cutoff */ { const char *p=optarg; if (*p=='n') @@ -759,11 +785,11 @@ void parse_params(int argc, char *argv[]) } break; #if defined(BSD) && !defined(__OpenBSD__) && !defined(__APPLE__) - case 53: /* enable-pf */ + case 54: /* enable-pf */ params.pf_enable = true; break; #elif defined(__linux__) - case 53: /* mss */ + case 54: /* mss */ // this option does not work in any BSD and MacOS. OS may accept but it changes nothing params.mss = atoi(optarg); if (params.mss<88 || params.mss>32767) @@ -772,7 +798,7 @@ void parse_params(int argc, char *argv[]) exit_clean(1); } break; - case 54: /* mss-pf */ + case 55: /* mss-pf */ if (!pf_parse(optarg,¶ms.mss_pf)) { fprintf(stderr, "Invalid MSS port filter.\n"); @@ -780,7 +806,7 @@ void parse_params(int argc, char *argv[]) } break; #ifdef SPLICE_PRESENT - case 55: /* nosplice */ + case 56: /* nosplice */ params.nosplice = true; break; #endif @@ -802,6 +828,7 @@ void parse_params(int argc, char *argv[]) exit_clean(1); } if (!params.resolver_threads) params.resolver_threads = 5 + params.maxconn/50; + if (params.split_tls==tlspos_none && params.split_pos) params.split_tls=tlspos_pos; if (*params.hostlist_auto_filename) params.hostlist_auto_mod_time = file_mod_time(params.hostlist_auto_filename); if (!LoadIncludeHostLists())