Tuesday, February 16, 2016

One Proxy To Rule Them All

Not all client/server applications make sense in a peer-to-peer environment or over a delay-tolerant network. Sometimes data is just too big or node specific to be shared over servals rhizome - think various local community websites - or doesn't make sense over DTN - like an SSH connection.

It would be way too time consuming porting these "legacy" applications to serval and giving them native MSP support. A quick and easy way to still use them is already there in servald. It supports the msp listen and msp connect commands that act similar to netcat.

Manual MSP


So lets get a local webserver into serval mesh:

root@n9:/tmp/pycore.35289/n9.conf# cat index.html
<html><body>test</body></html> 

root@n9:/tmp/pycore.35289/n9.conf# python -mSimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...

Use a new terminal for testing and setting up the forwarding:

root@n9:/tmp/pycore.35289/n9.conf# curl http://127.0.0.1:8000
<html><body>test</body></html> 

root@n9:/tmp/pycore.35289/n9.conf# servald id self
1
sid
C39309B71A19274E4947A99EE721DA0638D3E8596C2EA2821D0F10DEA5F22729

root@n9:/tmp/pycore.35289/n9.conf# servald msp listen --forward=8000 80

That's it!

So now lets try to reach this site through msp from another node.

root@n4:/tmp/pycore.35289/n4.conf# servald msp connect C39309B71A19274E4947A99EE721DA0638D3E8596C2EA2821D0F10DEA5F22729 80
GET / HTTP/1.0

HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/2.7.6
Date: Tue, 16 Feb 2016 12:25:43 GMT
Content-type: text/html
Content-Length: 36
Last-Modified: Fri, 12 Feb 2016 12:48:04 GMT

<html><body>test</body></html> 

So it works! But you don't want to setup each and every connection manually - Software should automatically map SIDs to serval and take care of connection setup and routing. Usually these kind of problems are solved by using a proxy as it is done by the tor project for example.

Automatic Connection


The SOCKS5 protocol has a nice feature that makes our life much easier. It can not only operate on a given IP address to relay a connection but also be given a FQDN and resolve it itself!
So we need a proxy server that intercepts all domain names and check if it is a valid SID - 64 bytes all hex. Easy enough, next we need to invoke msp connect with the supplied SID and port, relay stdin and stdout from servald to the connected TCP session and we're done.

A quick proof-of-concept socks5-serval was put together with a modified version of python-socks5, the changes were minimal and the result works quite good, it can still be used for regular IP connections as well as with FQDNs.

Here it is in action:

root@n4:/tmp/pycore.35289/n4.conf# python python-socks5-serval/socks5.py


Open another terminal to test the proxy server.

root@n4:/tmp/pycore.35289/n4.conf# curl --socks5-hostname localhost:1080 http://C39309B71A19274E4947A99EE721DA0638D3E8596C2EA2821D0F10DEA5F22729
<html><body>test</body></html> 

It worked! In our other terminal window where the proxy is running some debug output should also appear:

root@n4:/tmp/pycore.35289/n4.conf# python python-socks5-serval/socks5.py
[INFO:] Got one client connection
[INFO:] Checking atyp: 3
[INFO:] Client wants to connect to C39309B71A19274E4947A99EE721DA0638D3E8596C2EA2821D0F10DEA5F22729:80
[INFO:] Starting transform thread
[INFO:] Starting serval mode C39309B71A19274E4947A99EE721DA0638D3E8596C2EA2821D0F10DEA5F22729
[INFO:] Starting Resending
[INFO:] Client quit normally


Instead of checking for an 64 byte hex string to identify SIDs one could also say that clients must use the TLD .serval to identify a serval address. Then a proxy would only have to check the TLD to be sure but on the other hand 64 byte hex is not a FQDN so we should be safe.

SOCKS5-serval was just a quick'n'dirty hack and is not really production ready but it demonstrates quite well how endless the possibilities for serval meshs are and how our beloved regular applications can continue to work in a full serval-routed network.

No comments:

Post a Comment