Closed ioerror closed 9 years ago
( This allows a user to register with TextSecure through an HTTP/HTTPS proxy (eg: privoxy + Tor) but it does not allow for further usage that requires websockets. )
Thanks for the patch. The rest of proxy support can be added later.
The latest commit adds proxy support for the websocket stream. I've tested using a http-only localhost privoxy install and it seems to work but real-world usage reports would be appreciated.
I tested the current git tip ( 6bc446d7b33e9f5714f06bda8551263c14ead098 ) and found the following:
go build && http_proxy=127.0.0.1:8118 ./textsecure
PUT /v1/directory/tokens/ 401
Could not get contacts: Status code 401
Could not establish websocket connection: unexpected EOF
My firewall (which blocks everything except connections to my local http and socks proxy: I'm using Tails + privoxy) says nothing. As we can see it fails completely otherwise:
./textsecure
PUT /v1/directory/tokens/ 0
Could not get contacts: Put https://textsecure-service.whispersystems.org:443/v1/directory/tokens/: dial tcp 52.1.136.37:443: connection refused
Could not establish websocket connection: websocket.Dial wss://textsecure-service.whispersystems.org:443/v1/websocket/?login=%2B1771111001&password=XXXXXXXREDACTED: dial tcp 52.1.136.37:443: connection refused
So - something seems to not be working properly - I'm not sure what is happening though. Probably time to bust out tcpdump.
I'll do some tests with the official whisper server, I only did local tests recently.
it's related to https, but I am not sure yet what, I thought passing https_proxy fixed it but it does not, it just skips the proxy.
I haven't looked in detail but I think the trick you used for the CONNECT proxy doesn't do a proper wss:// setup.
OK - I've looked at the output on the wire and indeed it is the case that the websocket is just treating the socket as if it's http. That's bad news as it sends data without TLS - it assumes the socket is already setup with TLS (!) and so sends bare HTTP requests:
11:09:15.632263 IP (tos 0x0, ttl 64, id 49741, offset 0, flags [DF], proto TCP (6), length 358)
localhost.60092 > localhost.8118: Flags [P.], cksum 0xff5a (incorrect -> 0x3fb7), seq 145:463, ack 69, win 342, length 318
E..f.M@.@.yB.............T..M...P..V.Z..GET /v1/websocket/?login=%2B177XXX1&password=XXXXREDACTED HTTP/1.1
Host: textsecure-service.whispersystems.org:443
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: fVztNoE9uZhxQ4MYWBj4jw==
Origin: https://textsecure-service.whispersystems.org:443/v1/websocket/
Sec-WebSocket-Version: 13
In a quick one minute look at this:
It should be doing a TLS setup after the CONNECT request - since it doesn't do so, it just treats it as a normal HTTP request. This data is then sent to port 443 of the text secure servers. Anyone snooping on them will see a bare HTTP request (see above) send to the TLS port. The TLS server isn't happy and barfs. But the data is still sent over the HTTP proxy, over Tor, out of an exit node and to the text secure server. Whoops.
We need a way to tell the WebSocket code to do TLS after that CONNECT proxy setup - the current rwc object assumes you've done it all. That's bad news and means that the proxy support is totally broken.
It would probably make more sense to implement a proper Dial object with SOCKS5 support over the hacky HTTP CONNECT trick. Either that or we'd need a core websockets function to setup TLS on a rwc object. I guess either trick should work. In any case - registration works with the first patch but the second changeset is broken.
I've made some progress on the wss front, but the app now crashes in an unrelated place when sending messages. I've seen this with plain http/ws before.
Thanks for your testing and suggestions btw. It's my first time dealing with http tunneling and I am not that familiar with websockets either besides what's in this codebase.
Can you link to the changes as you go?
It was a single commit since my previous comment, the latest in the repo.
OK - I've since rebuilt from git tip and it is failing in a new way:
http_proxy=127.0.0.1:8118 ./textsecure
PUT /v1/directory/tokens/ 401
Could not get contacts: Status code 401
It hangs for quite some time and then it says:
Could not establish websocket connection: tls: oversized record received with length 20527
Each subsequent run says the same thing:
Could not establish websocket connection: tls: oversized record received with length 20527
TextSecure then exits with 0.
Good news is that it worked to do the following:
http_proxy=127.0.0.1:8118 ./textsecure -message="hello world" -to="Sally"
I can't seem to receive any messages though - it just hangs out and replying to that "hello world" - the replies don't ever show up.
Sending messages is done via the http(s) API, websockets are only used for receiving, and for seding keepalive pings. So ws is broken if receiving does not work, and I see something similar in my local tests.
So - just to recap - I registered freshly (sms verification with another phone) and it worked. Basic sending of messages seems to function. Receiving doesn't seem to function.
The receiving seems to properly create a connection to textsecure-service.whispersystems.org - it hangs out in an open (as an attached Tor stream) state for a while.
So ws is still broken when proxied. Sending messages should work even if we don't attempt to set up the websocket connection. I'll be looking into it some more.
The tunneling code was broken, I had tried upgrading the wrong connection to TLS. With the latest commit, I have wss working using local privoxy and local https whisper server. SHA: cd139bd8729f6b8e52c18337c228223e00a3f20f
the proxy url can now be set in the configuration file with something like proxy: http://192.168.1.10:8118 the environment variable is used as a fallback.
This patch adds support for HTTP proxies to client.Transport and it may be used like this: