torify/torsocks and TCP Fast Open

Hi, I tried to torify my wget-like application (https://github.com/rockdaboot/mget) and after some struggling I found that TFO is enabled by default (where available). I guess, the problem is TFO not using connect() but sendto(). Please enlighten me, what I can do (despite turning off TFO). Is it worth a patch or do you think patching libtorsocks has pitfalls or unwanted side-effects ? Tim

Hi, no answer yet, so I created a first 'works for me' patch to let torified TFO aware clients not leak silently. (I hope I am on the right list here) Please review and apply|comment. Tim On Tuesday 13 January 2015 15:25:35 Tim Ruehsen wrote:
Hi,
I tried to torify my wget-like application (https://github.com/rockdaboot/mget) and after some struggling I found that TFO is enabled by default (where available).
I guess, the problem is TFO not using connect() but sendto().
Please enlighten me, what I can do (despite turning off TFO).
Is it worth a patch or do you think patching libtorsocks has pitfalls or unwanted side-effects ?
Tim

Upps, I made a last second failure... Here is the amended (and working) patch. Tim On Wednesday 14 January 2015 14:55:58 Tim Ruehsen wrote:
Hi,
no answer yet, so I created a first 'works for me' patch to let torified TFO aware clients not leak silently.
(I hope I am on the right list here)
Please review and apply|comment.
On Tuesday 13 January 2015 15:25:35 Tim Ruehsen wrote:
Hi,
I tried to torify my wget-like application (https://github.com/rockdaboot/mget) and after some struggling I found that TFO is enabled by default (where available).
I guess, the problem is TFO not using connect() but sendto().
Please enlighten me, what I can do (despite turning off TFO).
Is it worth a patch or do you think patching libtorsocks has pitfalls or unwanted side-effects ?

On 14 Jan (16:25:17), Tim Ruehsen wrote:
Upps, I made a last second failure...
Here is the amended (and working) patch.
Hey! Sorry for the delayed response, too many things at once! :) I've done some fixes on the patch that I'll be merging in a jiffy, I've outlined them to you below. (mostly syntax thingy...)
Tim
On Wednesday 14 January 2015 14:55:58 Tim Ruehsen wrote:
Hi,
no answer yet, so I created a first 'works for me' patch to let torified TFO aware clients not leak silently.
(I hope I am on the right list here)
Please review and apply|comment.
On Tuesday 13 January 2015 15:25:35 Tim Ruehsen wrote:
Hi,
I tried to torify my wget-like application (https://github.com/rockdaboot/mget) and after some struggling I found that TFO is enabled by default (where available).
I guess, the problem is TFO not using connect() but sendto().
Please enlighten me, what I can do (despite turning off TFO).
Is it worth a patch or do you think patching libtorsocks has pitfalls or unwanted side-effects ?
From 3a775bf43d970c01fb955d7169f0da98be0a297c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20R=C3=BChsen?= <tim.ruehsen@gmx.de> Date: Wed, 14 Jan 2015 14:48:37 +0100 Subject: [PATCH] Allow TCP Fast Open clients go through tor.
This patch prevents TFO clients to silently leak when torified. TFO uses sendto() instead of connect()/send(). --- src/lib/Makefile.am | 2 +- src/lib/sendto.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib/torsocks.h | 19 +++++++++++++- 3 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 src/lib/sendto.c
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index d64b3f6..6e137f3 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -9,6 +9,6 @@ lib_LTLIBRARIES = libtorsocks.la libtorsocks_la_SOURCES = torsocks.c torsocks.h \ connect.c gethostbyname.c getaddrinfo.c close.c \ getpeername.c socket.c syscall.c socketpair.c recv.c \ - exit.c accept.c listen.c fclose.c + exit.c accept.c listen.c fclose.c sendto.c
libtorsocks_la_LIBADD = $(top_builddir)/src/common/libcommon.la diff --git a/src/lib/sendto.c b/src/lib/sendto.c new file mode 100644 index 0000000..af2550a --- /dev/null +++ b/src/lib/sendto.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015 - Tim R?hsen <tim.ruehsen@gmx.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License, version 2 only, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <assert.h> + +#include <common/log.h> +#include <common/utils.h> + +#include "torsocks.h" + +/* + * Using TCP Fast Open (TFO) uses sendto() instead of connect() with 'flags' + * set to MSG_FASTOPEN. Without this code, using TFO simply bypasses TOR + * without letting the user know. + * + * This solution simply ignores TFO and falls back to connect(). + * At the time the TOR server supports TFO, socks5.c (client code) could + * implement it in send_data() and connect_socks5().
Could you simply clarify this for me meaning what's needed in socks5 code for TFO to be supported? (no need for an extra comments, just how would I do that :)
+ */ + +/* sendto(2) + * args: int sockfd, const void *buf, size_t len, int flags, + * const struct sockaddr *dest_addr, socklen_t addrlen + */ +TSOCKS_LIBC_DECL(sendto, LIBC_SENDTO_RET_TYPE, LIBC_SENDTO_SIG) + +/* + * Torsocks call for sendto(2). + */ +LIBC_SENDTO_RET_TYPE tsocks_sendto(LIBC_SENDTO_SIG) +{ +#ifdef MSG_FASTOPEN + int ret; + + if ((flags&MSG_FASTOPEN) == 0) { + /* No TFO, fallback to libc sendto() */ + goto libc_sendto; + } + + DBG("TFO Sendto catched on fd %d", sockfd); + + ret = connect(sockfd, dest_addr, addrlen); + if (ret == 0) { + /* connection established, send payload */ + ret = send(sockfd, buf, len, flags&~MSG_FASTOPEN); + } + + return ret; + +libc_sendto: +#endif /* ifdef MSG_FASTOPEN */ + return tsocks_libc_sendto(LIBC_SENDTO_ARGS);
That symbol needs to be looked up (dlsym()) before you can use it so I did that in the function below. See accept.c how we do that. Big thanks for that! Really appreciated and one less leak also! :) Cheers! David

On Wed, 21 Jan 2015 15:26:56 -0500 David Goulet <dgoulet@ev0ke.net> wrote:
+/* + * Using TCP Fast Open (TFO) uses sendto() instead of connect() with 'flags' + * set to MSG_FASTOPEN. Without this code, using TFO simply bypasses TOR + * without letting the user know. + * + * This solution simply ignores TFO and falls back to connect(). + * At the time the TOR server supports TFO, socks5.c (client code) could + * implement it in send_data() and connect_socks5().
Could you simply clarify this for me meaning what's needed in socks5 code for TFO to be supported? (no need for an extra comments, just how would I do that :)
This doesn't really make sense when a proxy is in the picture. What would you include as the TFO payload? The "VER | NMETHODS | METHODS" SOCKS5 handshake? In the vast majority of the deployed configurations, the client code talks to tor over a loopback interface, so cutting out 1xRTT isn't worth the added code (There's a case to be made for using TFO for inter-relay traffic, but that's entirely orthogonal to this.). Regards, -- Yawning Angel

On Wednesday 21 January 2015 21:39:30 Yawning Angel wrote:
On Wed, 21 Jan 2015 15:26:56 -0500
David Goulet <dgoulet@ev0ke.net> wrote:
+/* + * Using TCP Fast Open (TFO) uses sendto() instead of connect() with 'flags' + * set to MSG_FASTOPEN. Without this code, using TFO simply bypasses TOR + * without letting the user know. + * + * This solution simply ignores TFO and falls back to connect(). + * At the time the TOR server supports TFO, socks5.c (client code) could + * implement it in send_data() and connect_socks5().
Could you simply clarify this for me meaning what's needed in socks5 code for TFO to be supported? (no need for an extra comments, just how would I do that :)
This doesn't really make sense when a proxy is in the picture. What would you include as the TFO payload? The "VER | NMETHODS | METHODS" SOCKS5 handshake?
In the vast majority of the deployed configurations, the client code talks to tor over a loopback interface, so cutting out 1xRTT isn't worth the added code (There's a case to be made for using TFO for inter-relay traffic, but that's entirely orthogonal to this.).
Right, TFO doesn't make much sense in a loopback scenario (on the other hand there is no impact). Adding the code is only worth if someone really asks for it and verifies a benefit. TFO comes into play for short-time connections or more exactly when RTT matters (as you mentioned). But to answer David's request (in short): TFO has to be globally enabled on your (Linux) system: # echo 1 > /proc/sys/net/ipv4/tcp_fastopen On the server side it is easy: // bind() setsockopt(sockfd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen)); // listen() On the client side it is sendto(fd, buffer, buf_len, MSG_FASTOPEN, ...); send() recv() instead of connect() send() recv() But you need a fallback to connect() if the above sendto() fails (e.g. due to TFO not enabled via /proc/). see http://edsiper.linuxchile.cl/blog/2013/02/21/linux-tcp-fastopen-in-your-sock... Regards, Tim

On 13 Jan (15:25:35), Tim Ruehsen wrote:
Hi,
I tried to torify my wget-like application (https://github.com/rockdaboot/mget) and after some struggling I found that TFO is enabled by default (where available).
I guess, the problem is TFO not using connect() but sendto().
Please enlighten me, what I can do (despite turning off TFO).
Is it worth a patch or do you think patching libtorsocks has pitfalls or unwanted side-effects ?
Can you tell me the torsocks version you are using. Also, how can I reproduce this. Is TFO something you have to set to the socket or enable with a sysctl or... ? Furthermore, providing the debug logs would also be helpful using the environment variable TORSOCKS_LOG_LEVEL=5 Thanks! David
Tim
_______________________________________________ tor-dev mailing list tor-dev@lists.torproject.org https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-dev

On Wednesday 14 January 2015 09:01:40 David Goulet wrote:
On 13 Jan (15:25:35), Tim Ruehsen wrote:
Hi,
I tried to torify my wget-like application (https://github.com/rockdaboot/mget) and after some struggling I found that TFO is enabled by default (where available).
I guess, the problem is TFO not using connect() but sendto().
Please enlighten me, what I can do (despite turning off TFO).
Is it worth a patch or do you think patching libtorsocks has pitfalls or unwanted side-effects ?
Can you tell me the torsocks version you are using. Also, how can I reproduce this. Is TFO something you have to set to the socket or enable with a sysctl or... ?
Hi David, Thanks for having a look at it. I am using Debian unstable, torsocks 2.0.0-3 Be aware that TFO is not using connect() but sendto() instead (and sendto has been removed from libtorsocks.so a while ago). see here for a good description http://edsiper.linuxchile.cl/blog/2013/02/21/linux-tcp-fastopen-in-your sockets/ To reproduce, you'll need a client that supports TFO. e.g. git clone https://github.com/rockdaboot/mget.git cd mget ./autogen.sh ./configure [Hint: mget currently does not use TFO with HTTPS, just with HTTP] Check your own IP src/mget -qO- checkip.dyndns.org|grep IP [Shows your current IP] Double check with wget wget -qO- checkip.dyndns.org|grep IP [Shows your current IP] Check torifying with TFO enabled (guess you have linux kernel >= 3.6.1) torify src/mget -qO- checkip.dyndns.org|grep IP [Shows your current IP] Check torifying with TFO disabled torify src/mget -qO- --no-tcp-fastopen checkip.dyndns.org|grep IP [Shows a Tor IP] Applying my patch (posted to the list) to the latest git master, I use for testing: LD_PRELOAD="/home/tim/src/torsocks/src/lib/.libs/libtorsocks.so" src/mget -qO- checkip.dyndns.org|grep IP [Shows a Tor IP, same with --no-tcp-fastopen] Tim

Sorry, I forgot:
git clone https://github.com/rockdaboot/mget.git cd mget git checkout develop ./autogen.sh ./configure
Tim

Hi, do you need any more information ? Tim Am Mittwoch, 14. Januar 2015, 16:53:58 schrieb Tim Ruehsen:
On Wednesday 14 January 2015 09:01:40 David Goulet wrote:
On 13 Jan (15:25:35), Tim Ruehsen wrote:
Hi,
I tried to torify my wget-like application (https://github.com/rockdaboot/mget) and after some struggling I found that TFO is enabled by default (where available).
I guess, the problem is TFO not using connect() but sendto().
Please enlighten me, what I can do (despite turning off TFO).
Is it worth a patch or do you think patching libtorsocks has pitfalls or unwanted side-effects ?
Can you tell me the torsocks version you are using. Also, how can I reproduce this. Is TFO something you have to set to the socket or enable with a sysctl or... ?
Hi David,
Thanks for having a look at it.
I am using Debian unstable, torsocks 2.0.0-3
Be aware that TFO is not using connect() but sendto() instead (and sendto has been removed from libtorsocks.so a while ago). see here for a good description http://edsiper.linuxchile.cl/blog/2013/02/21/linux-tcp-fastopen-in-your sockets/
To reproduce, you'll need a client that supports TFO. e.g. git clone https://github.com/rockdaboot/mget.git cd mget ./autogen.sh ./configure
[Hint: mget currently does not use TFO with HTTPS, just with HTTP]
Check your own IP src/mget -qO- checkip.dyndns.org|grep IP [Shows your current IP]
Double check with wget wget -qO- checkip.dyndns.org|grep IP [Shows your current IP]
Check torifying with TFO enabled (guess you have linux kernel >= 3.6.1) torify src/mget -qO- checkip.dyndns.org|grep IP [Shows your current IP]
Check torifying with TFO disabled torify src/mget -qO- --no-tcp-fastopen checkip.dyndns.org|grep IP [Shows a Tor IP]
Applying my patch (posted to the list) to the latest git master, I use for testing: LD_PRELOAD="/home/tim/src/torsocks/src/lib/.libs/libtorsocks.so" src/mget -qO- checkip.dyndns.org|grep IP [Shows a Tor IP, same with --no-tcp-fastopen]
Tim
participants (4)
-
David Goulet
-
Tim Ruehsen
-
Tim Rühsen
-
Yawning Angel