Hello,
Sorry for the delay, I finnally set on the quest to understand obfsproxy. So with the help of pdb and a few questions here and there I got to some places, and with a lot of more questions to ask.
## Studying the client
The client launches a connection on obfsproxy/pyofsproxypy do_external_mode() the launch_transport.launch_transport_listener method is where the socks listeners is set. Right after that the Twisted library reactor module is initiated with reactor.run() on line 107 of the file obfsproxy/pyobfsproxy.py
After that the Twisted event loop is started and it will listen to events that are set on methods like listenTCP() the wiki page about servers[1]
I've set a pdb.set_trace() on the buildProtocol() method in the file obfsproxy/network/socks.py and the backtrace looks like.
(Pdb) bt /usr/lib/python2.7/runpy.py(162)_run_module_as_main() -> "__main__", fname, loader, pkg_name) /usr/lib/python2.7/runpy.py(72)_run_code() -> exec code in run_globals /usr/lib/python2.7/pdb.py(1338)<module>() -> pdb.main() /usr/lib/python2.7/pdb.py(1314)main() -> pdb._runscript(mainpyfile) /usr/lib/python2.7/pdb.py(1233)_runscript() -> self.run(statement) /usr/lib/python2.7/bdb.py(400)run() -> exec cmd in globals, locals <string>(1)<module>() /home/masterkorp/Public/obfsproxy/bin/obfsproxy(16)<module>() -> run() /home/masterkorp/Public/obfsproxy/obfsproxy/pyobfsproxy.py(207)run() -> pyobfsproxy() /home/masterkorp/Public/obfsproxy/obfsproxy/pyobfsproxy.py(189)pyobfsproxy() -> do_external_mode(args) /home/masterkorp/Public/obfsproxy/obfsproxy/pyobfsproxy.py(108)do_external_mode() -> reactor.run() /usr/lib/python2.7/site-packages/twisted/internet/base.py(1192)run() -> self.mainLoop() /usr/lib/python2.7/site-packages/twisted/internet/base.py(1204)mainLoop() -> self.doIteration(t) /usr/lib/python2.7/site-packages/twisted/internet/epollreactor.py(396)doPoll() -> log.callWithLogger(selectable, _drdw, selectable, fd, event) /usr/lib/python2.7/site-packages/twisted/python/log.py(88)callWithLogger() -> return callWithContext({"system": lp}, func, *args, **kw) /usr/lib/python2.7/site-packages/twisted/python/log.py(73)callWithContext() -> return context.call({ILogContext: newCtx}, func, *args, **kw) /usr/lib/python2.7/site-packages/twisted/python/context.py(118)callWithContext() -> return self.currentContext().callWithContext(ctx, func, *args, **kw) /usr/lib/python2.7/site-packages/twisted/python/context.py(81)callWithContext() -> return func(*args,**kw) /usr/lib/python2.7/site-packages/twisted/internet/posixbase.py(614)_doReadOrWrite() -> why = selectable.doRead() /usr/lib/python2.7/site-packages/twisted/internet/tcp.py(1062)doRead() -> protocol = self.factory.buildProtocol(self._buildAddr(addr)) /home/masterkorp/Public/obfsproxy/obfsproxy/network/socks.py(183)buildProtocol() -> circuit = network.Circuit(self.transport_class())
It goes directly to this method from Twistedm, which confirms that all the SOCKS is set. This creates a new Circuit. And the like the documentation says a Circuit is a pair of connections between and the obfsproxy client and openvpn client (in this case) or obfsproxy server and OpenVPN server.
Then I set a pdb.set_trace() dataReceived() on obfsproxy/network/network.py well because of the name. And a backtrace looks like:
(Pdb) bt /usr/lib/python2.7/runpy.py(162)_run_module_as_main() -> "__main__", fname, loader, pkg_name) /usr/lib/python2.7/runpy.py(72)_run_code() -> exec code in run_globals /usr/lib/python2.7/pdb.py(1338)<module>() -> pdb.main() /usr/lib/python2.7/pdb.py(1314)main() -> pdb._runscript(mainpyfile) /usr/lib/python2.7/pdb.py(1233)_runscript() -> self.run(statement) /usr/lib/python2.7/bdb.py(400)run() -> exec cmd in globals, locals <string>(1)<module>() /home/masterkorp/Public/obfsproxy/bin/obfsproxy(3)<module>() -> import sys, os /home/masterkorp/Public/obfsproxy/obfsproxy/pyobfsproxy.py(205)run() -> pyobfsproxy() /home/masterkorp/Public/obfsproxy/obfsproxy/pyobfsproxy.py(187)pyobfsproxy() -> do_external_mode(args) /home/masterkorp/Public/obfsproxy/obfsproxy/pyobfsproxy.py(106)do_external_mode() -> reactor.run() /usr/lib/python2.7/site-packages/twisted/internet/base.py(1192)run() -> self.mainLoop() /usr/lib/python2.7/site-packages/twisted/internet/base.py(1204)mainLoop() -> self.doIteration(t) /usr/lib/python2.7/site-packages/twisted/internet/epollreactor.py(396)doPoll() -> log.callWithLogger(selectable, _drdw, selectable,fd, event) /usr/lib/python2.7/site-packages/twisted/python/log.py(88)callWithLogger() -> return callWithContext({"system": lp}, func,*args, **kw) /usr/lib/python2.7/site-packages/twisted/python/log.py(73)callWithContext() -> return context.call({ILogContext: newCtx},func, *args, **kw) /usr/lib/python2.7/site-packages/twisted/python/context.py(118)callWithContext() -> return self.currentContext().callWithContext(ctx,func, *args, **kw) /usr/lib/python2.7/site-packages/twisted/python/context.py(81)callWithContext() -> return func(*args,**kw) /usr/lib/python2.7/site-packages/twisted/internet/posixbase.py(614)_doReadOrWrite() -> why = selectable.doRead() /usr/lib/python2.7/site-packages/twisted/internet/tcp.py(214)doRead() -> return self._dataReceived(data) /usr/lib/python2.7/site-packages/twisted/internet/tcp.py(220)_dataReceived() -> rval = self.protocol.dataReceived(data) /home/masterkorp/Public/obfsproxy/obfsproxy/network/socks5.py(163)dataReceived() -> self.processEstablishedData(data) /home/masterkorp/Public/obfsproxy/obfsproxy/network/socks.py(107)processEstablishedData() -> self.circuit.dataReceived(self.buffer, self) /home/masterkorp/Public/obfsproxy/obfsproxy/network/network.py(152)dataReceived() -> if self.closed:
Its not too far away for the previous backtrace
Inside the method I try to see what the heck is going on. (Pdb) print self <obfsproxy.network.network.Circuit instance at 0x7fbbec1c3758>
This is the circuit itself, passing self seems a into the methods seems a print self common thing to do. I verihave no idea why.
(Pdb) print conn <obfsproxy.network.socks.OBFSSOCKSv5Protocol object at 0x7fbbec1b75d0>
Conn is a socks connections. I wonder how can I extract the source IP from it.
(Pdb) print data <obfsproxy.network.buffer.Buffer object at 0x7fbbec1b7510>
data is butter object. Apparently is a First In First Out data container. Not sure where this object was initially created.
I've tried to use the peek method, whiting pdb. (Pdb) print data.peek(n=100) 8£öä¢ÂZ
Passing n=<whatever> always shows that same string. Maybe that is just it, kinda like an initial hanshake ?
Just a few steps foward here. there is a log.debug 2015-01-22 17:25:35,162 [DEBUG] circ_0x7fbbec1c3758: upstream: Received 16bytes.
Ok I think I am on the right path.
Then the receivedUpstream() on obfsproxy/network/transports/scramblesuit/scramblesuit.py
A few steps forward in: if self.protoState == const.ST_CONNECTED:
Where the const.ST_CONNECTED comes from ? printing shows an value of "2" which on this case its equal to self.protoState, that I think it means that obfsproxy client is connected to obfsproxy Server correct me if I am wrong
Then the data send to sendRemote. which obfsucates the data itself and reads from the Buffer object.
In here I could not get info about the SOCKS client Ip address. Wich is weird.
Can you shed some light ?
Thanks in advance?
[1] https://twistedmatrix.com/documents/current/core/howto/servers.html
-- Regards, Alfredo Palhares