HTTP POST DATA elemzes (AnyPyProxy)
Udv, a kovetkezo config-al probalkozom a HTTP forgalom POST tipusu request_method-jainak adatat elemezni: " class myHttpProxy(HttpProxy): def config(self): HttpProxy.config(self) self.request["POST"] = (HTTP_REQ_POLICY, self.isok) def isok(self, method, url, version): url = unquote(url) if ( url.find("/xxx/index.php") > -1 ): self.request_stack["POST"] = (HTTP_STK_DATA, magicProxy ) class magicProxy(AbstractAnyPyProxy): def config(self): AbstractAnyPyProxy.config(self) def proxyThread(self): client = self.session.client_stream server = self.session.server_stream user = client.read(128) #itt majd elkovetek valamit a "user"-el, ha mar mukodik... ;) server.write(user) while user: try: user = client.read(128) server.write(user) except IOError, e: log("http.info", 2, e.__str__()); break " Jonak tunik ez igy? Hogyan tudnek a client_stream hosszanak megfelelo adatot kiolvasni mashogyan? (Exception nelkul?) Esetleg hogyan lehetne megadni, hogy csak a "Content-Length"-nek megfelelo adatot olvassak a stream-bol? Probaltam kinyerni a kovetkezo kodreszlet segitsegevel, de ugy tunik mintha a request_header feldolgozasa a request_stack-e utan lenne... " self.request_header["Content-Length"] = (HTTP_HDR_POLICY, self.getlength) def getlength(self, name, value): self.LENGTH = self.current_header_value return HTTP_HDR_ACCEPT " Kiprobaltam es olyan erdekesseget tapasztalok, hogy amikor elkuldom a POST kerest, akkor a browser-em nem kap vissza valaszt, pedig log-olva a stream-bol megjelenik a POST altal elkuldott adat... Lehet rosszul emlekszem, de mintha lett volna olyan allapot, amikor ez mukodott volna, de olyan sok variaciot kiprobaltam, hogy sajna mar nem tudom csak kepzeltem-e, hogy mukodott... :( Koszontem, Viktor
Szia, Vegre egy erdekes problema :) On Wed, 2007-05-23 at 10:56 +0200, Viktor Tuska wrote:
Udv,
a kovetkezo config-al probalkozom a HTTP forgalom POST tipusu request_method-jainak adatat elemezni:
" class myHttpProxy(HttpProxy):
def config(self): HttpProxy.config(self) self.request["POST"] = (HTTP_REQ_POLICY, self.isok)
def isok(self, method, url, version): url = unquote(url)
if ( url.find("/xxx/index.php") > -1 ): self.request_stack["POST"] = (HTTP_STK_DATA, magicProxy )
ez nagyjabol jonak tunik, gondolom a beagyazott proxy meg el is indul. Ezt a logokbol tudod kideriteni, tenyleg elindult?
class magicProxy(AbstractAnyPyProxy):
def config(self): AbstractAnyPyProxy.config(self)
def proxyThread(self): client = self.session.client_stream server = self.session.server_stream
user = client.read(128) #itt majd elkovetek valamit a "user"-el, ha mar mukodik... ;) server.write(user)
while user: try: user = client.read(128) server.write(user) except IOError, e: log("http.info", 2, e.__str__()); break "
Jonak tunik ez igy?
Az AnyPy proxy meglehetosen fapados (pl. blocking I/O-t hasznal, tehat full-duplex csatornakat nem lehet vele lekezelni), de alapvetoen jonak tunik. Fontos, hogy a HTTP-nel HTTP_STK_DATA tipusu stackelest kertel, azaz AnyPy csak az adatreszt fogja megkapni, a HTTP fejleceket nem.
Hogyan tudnek a client_stream hosszanak megfelelo adatot kiolvasni mashogyan? (Exception nelkul?)
A stream-nek nincs "hossza", legalabbis elore nem tudhato. Addig kell olvasnod, ameddig EOF-ot (0 hosszu stringet) nem kapsz. Latom az exception handler-t, rafut arra valamikor?
Esetleg hogyan lehetne megadni, hogy csak a "Content-Length"-nek megfelelo adatot olvassak a stream-bol? Probaltam kinyerni a kovetkezo kodreszlet segitsegevel, de ugy tunik mintha a request_header feldolgozasa a request_stack-e utan lenne...
" self.request_header["Content-Length"] = (HTTP_HDR_POLICY, self.getlength)
def getlength(self, name, value): self.LENGTH = self.current_header_value return HTTP_HDR_ACCEPT "
Jol alltal neki, sot elvileg a fejlec feldolgozas a stackeles elott van. Mibol gondolod, hogy nem? Nemi log jol jonne. Az AnyPy es a Http mas "objektum", igy a self-en keresztul nem tudsz adatot atadni. Erre valo a session, amit self.session -kent tudsz elerni. A beagyazott proxyk latjak a szulo proxy-k session-jeben levo valtozokat. Tehat pl: self.session.length = self.current_header_value Es akkor az AnyPy-ban ugyanugy self.session.length-kent tudsz ra hivatkozni. (a session-ben levo valtozokra valo hivatkozasrol a Session.py docstringjeben van egy leiras) (hint: self.session.http.<valtozo>) Arra figyelj, hogy Content-Length nem mindig van, bar bongeszo es Apache eseteben igen. (pl chunked encoding elvileg lehetseges bar az Apache utolso emlekeim szerint nem tamogatta).
Kiprobaltam es olyan erdekesseget tapasztalok, hogy amikor elkuldom a POST kerest, akkor a browser-em nem kap vissza valaszt, pedig log-olva a stream-bol megjelenik a POST altal elkuldott adat... Lehet rosszul emlekszem, de mintha lett volna olyan allapot, amikor ez mukodott volna, de olyan sok variaciot kiprobaltam, hogy sajna mar nem tudom csak kepzeltem-e, hogy mukodott... :(
Nemi log segitene itt is. Ja, megegy. Milyen Zorp verziot hasznalsz? -- Bazsi
Szia, koszontem szepen.
... gondolom a beagyazott proxy meg el is indul. Ezt a logokbol tudod kideriteni, tenyleg elindult?
Ugy nez ki elindult.
Az AnyPy proxy meglehetosen fapados (pl. blocking I/O-t hasznal, tehat full-duplex csatornakat nem lehet vele lekezelni), de alapvetoen jonak tunik.
Ez azt jelentene, hogy van olyan proxy is, ami nem ilyen "fapados" es hasonloan config-olhato?
Latom az exception handler-t, rafut arra valamikor?
Igen.
Az AnyPy es a Http mas "objektum", igy a self-en keresztul nem tudsz adatot atadni. Erre valo a session, amit self.session -kent tudsz elerni.
A beagyazott proxyk latjak a szulo proxy-k session-jeben levo valtozokat. Tehat pl:
self.session.length = self.current_header_value
Es akkor az AnyPy-ban ugyanugy self.session.length-kent tudsz ra hivatkozni. (a session-ben levo valtozokra valo hivatkozasrol a Session.py docstringjeben van egy leiras)
(hint: self.session.http.<valtozo>)
Arra figyelj, hogy Content-Length nem mindig van, bar bongeszo es Apache eseteben igen. (pl chunked encoding elvileg lehetseges bar az Apache utolso emlekeim szerint nem tamogatta).
Hm, ezek nagyon hasznos infok. Koszi. Magam sem ertem miert, de nem emlekeztem erre: self.getRequestHeader("Content-Length") Ezzel egyszerubb-e valt a helyzetem es kicsit aktualitasat veszitette a fejlec feldolgozas es stack-eles sorrendje. ;)
Nemi log segitene itt is.
Ja, megegy. Milyen Zorp verziot hasznalsz?
Most eppen a kovetkezon tesztelgettem: zorp:/etc/zorp# zorpctl version Zorp 3.0.14c Revision: devel@balabit.hu--zorp-1/zorp-core--mainline--3.0--patch-476 Compile-Date: Feb 7 2007 16:40:17 Config-Date: 2007/02/07 Trace: off Debug: off IPOptions: off IPFilter-Tproxy: off Netfilter-Tproxy: on Netfilter-Linux22-Fallback: on Linux22-Tproxy: off Conntrack: on Zorplib 3.0.6.9 Revision: devel@balabit.hu--zorp-1/zorp-lib--mainline--3.0--patch-145 Compile-Date: Jan 18 2007 17:28:18 Trace: off MemTrace: off Caps: on Debug: off StackDump: on Hosszas debug-olas utan Burjan Gabor kollegammal(koszi Gabor ;) ) oda jutottunk, hogy valoszinuleg a bajunk, hogy a request_stack-bol a server fele elmeno adatfolyam mar "chunked" modban (Transfer-Endcoding: chunked) tovabbitodik es a server ezt nem nagyon szereti. Valoszinuleg mar megvan a patch ehhez a "hires" webserver-hez, de most mar keso van, hogy kiprobaljam... remelhetoleg holnap kiderul... Van lehetoseg nem "chunked" modban kuldeni a stream-et? Viktor
Szia, On Wed, May 23, 2007 at 11:00:01PM +0200, Viktor Tuska wrote:
Van lehetoseg nem "chunked" modban kuldeni a stream-et?
A forrast bogaraszva nem igazan talaltunk ilyen lehetoseget, egy tesztrendszeren a csatolt patch es policy segitsegevel sikerul lebeszelni a zorpot az enchunkingrol. Kerdeznem, hogy mennyire nyultam melle a patch-csel :), illetve hogy terveztek-e ilyen feature-t a kereskedelmi valtozatba. buga
On Thu, 2007-05-24 at 10:23 +0200, Gabor Burjan wrote:
Szia,
On Wed, May 23, 2007 at 11:00:01PM +0200, Viktor Tuska wrote:
Van lehetoseg nem "chunked" modban kuldeni a stream-et?
A forrast bogaraszva nem igazan talaltunk ilyen lehetoseget, egy tesztrendszeren a csatolt patch es policy segitsegevel sikerul lebeszelni a zorpot az enchunkingrol. Kerdeznem, hogy mennyire nyultam melle a patch-csel :), illetve hogy terveztek-e ilyen feature-t a kereskedelmi valtozatba.
Az altalad kuldott patch-csel az a problema, hogy csak akkor mukodik, ha a gyerek proxy nem valtoztatja meg a stream hosszat. Es ha megteszi, akkor a Content-Length fejlecben hibas hossz megy at, es a kommunikacio fennakad. A megoldas az, hogy a HTTP proxynak meg kell mondani, hogy mennyi _lesz_ a hossz, mielott a gyerek proxy elkezd felfele adatot kuldeni. Igy a HTTP rendes content-length fejlecet kuld. Ezt a 3.0-ban csak C-ben irt proxybol lehet elerni, valahogy igy: ZProxyResultIface *iface; iface = z_proxy_find_iface(self->super.parent_proxy, Z_CLASS(ZProxyResultIface)); if (iface) { z_proxy_result_set_content_length(iface, content_length); z_object_unref(&iface->super); } A 3.1-ben ugyanezt az API-t kivittuk a kulso program stackelesehez egy egyszeru protokollal (ugyanaz, mint amit a Zorp-ZCV hasznal). Tehat, 3.0-ban C-ben kell irni az gyerek proxyt ahhoz, hogy a HTTP ne chunked modban kuldjon, 3.1-ben pedig akar kulso programbol is meg lehet ugyanezt tenni. Csatolok egy shell scriptet, ami lekeri a beagyazo proxytol a hosszt, majd ugyanazt tovabbkuldi. a shell script max. tesztelesi celokat szolgal, nincs benne hibakezeles. latszik belole a protokoll, meg ki tudod probalni, hogy tenyleg megoldja-e a problemadat. -- Bazsi
Szia, On Fri, May 25, 2007 at 04:39:24PM +0200, Balazs Scheidler wrote:
Az altalad kuldott patch-csel az a problema, hogy csak akkor mukodik, ha a gyerek proxy nem valtoztatja meg a stream hosszat. Es ha megteszi, akkor a Content-Length fejlecben hibas hossz megy at, es a kommunikacio fennakad.
Ahh, az vilagos volt, hogy egy csunya hack a patch es csak abban az esetben mukodik, hiszen ekkor meg nem ismert a modositott stream es - gondolom - pont ezert enchunkol a zorp. Csak ilyen adatokra is teszteltem, mert a streamet nem modositjuk, csak a streambol gyujtott adatokkal dolgozunk.
A megoldas az, hogy a HTTP proxynak meg kell mondani, hogy mennyi _lesz_ a hossz, mielott a gyerek proxy elkezd felfele adatot kuldeni. Igy a HTTP rendes content-length fejlecet kuld.
Ebben az esetben igazabol az egesz postot be kell olvasni elore, ugye?
Ezt a 3.0-ban csak C-ben irt proxybol lehet elerni, valahogy igy: [...] A 3.1-ben ugyanezt az API-t kivittuk a kulso program stackelesehez egy egyszeru protokollal (ugyanaz, mint amit a Zorp-ZCV hasznal).
Tehat, 3.0-ban C-ben kell irni az gyerek proxyt ahhoz, hogy a HTTP ne chunked modban kuldjon, 3.1-ben pedig akar kulso programbol is meg lehet ugyanezt tenni. Csatolok egy shell scriptet, ami lekeri a beagyazo proxytol a hosszt, majd ugyanazt tovabbkuldi.
A process stackelessel kapcsolatban egyebkent az volt az aggaly, hogy a forkok nagyon megfogjak a zorpot.
a shell script max. tesztelesi celokat szolgal, nincs benne hibakezeles. latszik belole a protokoll, meg ki tudod probalni, hogy tenyleg megoldja-e a problemadat.
Az eredeti (chunkolt cookie ertelmezesevel kapcsolatos) problema egyebkent megoldodott, a zorp mogott levo szerverrel volt gond. Az archivum kedveert, hatha valakinek jol jon: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6494180 Az infokat es a segitseget koszonom, ezzel es a C-ben irt proxyval kivancsisagbol azert eljatszok egy kicsit. buga
On Fri, 2007-05-25 at 17:38 +0200, Gabor Burjan wrote:
Szia,
On Fri, May 25, 2007 at 04:39:24PM +0200, Balazs Scheidler wrote:
A megoldas az, hogy a HTTP proxynak meg kell mondani, hogy mennyi _lesz_ a hossz, mielott a gyerek proxy elkezd felfele adatot kuldeni. Igy a HTTP rendes content-length fejlecet kuld.
Ebben az esetben igazabol az egesz postot be kell olvasni elore, ugye?
Nem feltetlenul, a 3.1-ben mar le lehet kerdezni a HTTP-tol, hogy szerinte mennyi lesz a hossz. Ez nem mindig van meg (pl. mert a kliens is chunkolva kuldi), de ha megvan, akkor tovabb lehet tolni.
Ezt a 3.0-ban csak C-ben irt proxybol lehet elerni, valahogy igy: [...] A 3.1-ben ugyanezt az API-t kivittuk a kulso program stackelesehez egy egyszeru protokollal (ugyanaz, mint amit a Zorp-ZCV hasznal).
Tehat, 3.0-ban C-ben kell irni az gyerek proxyt ahhoz, hogy a HTTP ne chunked modban kuldjon, 3.1-ben pedig akar kulso programbol is meg lehet ugyanezt tenni. Csatolok egy shell scriptet, ami lekeri a beagyazo proxytol a hosszt, majd ugyanazt tovabbkuldi.
A process stackelessel kapcsolatban egyebkent az volt az aggaly, hogy a forkok nagyon megfogjak a zorpot.
Hat, ha shell scripttel dolgoztok, akkor igaz lehet. Ezert irtam a remote stacking dolgot, ott unix domain socketen van kapcsolodas, es a gyerek futhat folyamatosan.
a shell script max. tesztelesi celokat szolgal, nincs benne hibakezeles. latszik belole a protokoll, meg ki tudod probalni, hogy tenyleg megoldja-e a problemadat.
Az eredeti (chunkolt cookie ertelmezesevel kapcsolatos) problema egyebkent megoldodott, a zorp mogott levo szerverrel volt gond. Az archivum kedveert, hatha valakinek jol jon:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6494180
Az infokat es a segitseget koszonom, ezzel es a C-ben irt proxyval kivancsisagbol azert eljatszok egy kicsit.
:) -- Bazsi
On Wed, 2007-05-23 at 23:00 +0200, Viktor Tuska wrote:
Szia,
koszontem szepen.
... gondolom a beagyazott proxy meg el is indul. Ezt a logokbol tudod kideriteni, tenyleg elindult?
Ugy nez ki elindult.
Az AnyPy proxy meglehetosen fapados (pl. blocking I/O-t hasznal, tehat full-duplex csatornakat nem lehet vele lekezelni), de alapvetoen jonak tunik.
Ez azt jelentene, hogy van olyan proxy is, ami nem ilyen "fapados" es hasonloan config-olhato?
Mivel latom, hogy kereskedelmit hasznaltok, ezert lehetosegetek van "programot" stackelni, ez joval kenyelmesebb, mert egyreszt akar non-blocking I/O is hasznalhato, masreszt pedig nem muszaj python-ban irni a beagyazott proxy-t. Ennek modja annyi, hogy a stackelesnel nem egy proxy osztalyt, hanem egy stringet adtok meg, amit a Zorp elindit, a 0-as fd-n megkapja a kliens fele, az 1-esen pedig a szerver fele meno streamet. Tehat pl: self.request_stack["POST"] = (HTTP_STK_DATA, "/usr/local/bin/check_post") Ez a GPL-ben nem, csak a kereskedelmiben elerheto. A 3.1 pedig meg tovabb bovitette ezt a lehetoseget, lehetoseg van "tavolra" stackelni, akar egy masik gepen futtatva a proxy egy reszet. Ennek szintaxisa: self.request_stack["POST"] = (HTTP_STK_DATA, (Z_STACK_REMOTE, SockAddrInet('127.0.0.1', 1318), "virus")) Az itt hasznalt protokoll egyenlore nem publikus, de valoszinuleg publikalhato. Mi ezt hasznaljuk a Zorp->ZCV kommunikaciohoz, virusellenorzeshez. A fentieknel persze lehet hasznalni SockAddrUnix-ot is, az valamivel gyorsabb.
Magam sem ertem miert, de nem emlekeztem erre: self.getRequestHeader("Content-Length") Ezzel egyszerubb-e valt a helyzetem es kicsit aktualitasat veszitette a fejlec feldolgozas es stack-eles sorrendje. ;)
ok.
Hosszas debug-olas utan Burjan Gabor kollegammal(koszi Gabor ;) ) oda jutottunk, hogy valoszinuleg a bajunk, hogy a request_stack-bol a server fele elmeno adatfolyam mar "chunked" modban (Transfer-Endcoding: chunked) tovabbitodik es a server ezt nem nagyon szereti.
Valoszinuleg mar megvan a patch ehhez a "hires" webserver-hez, de most mar keso van, hogy kiprobaljam... remelhetoleg holnap kiderul...
Van lehetoseg nem "chunked" modban kuldeni a stream-et?
Van, mindjart valaszolok Gabor levelere is. -- Bazsi
Balazs, koszontem szepen. Vegul kiderult, hogy valoban a webserver loadbalancer plugin-javal volt a problemank, a zorp tokeletesen mukodott. ;) Viktor
participants (3)
-
Balazs Scheidler
-
Gabor Burjan
-
Viktor Tuska