slingamn / namespaced-openvpn

Wrapper for OpenVPN on Linux solving various privacy issues
MIT License
312 stars 45 forks source link

Bittorrent through namespaced-openvpn #27

Open 8176135 opened 4 years ago

8176135 commented 4 years ago

Bittorrent applications (tried Deluge and qBitTorrent), when ran inside the protected namespace, won't be able to connect to trackers, with the error: no route to host.

Interestingly they can still connect to DHT, and find peers and download (slowly), but just can't connect to tracker.

I "fixed" it by changing the default route to go via the vpn gateway.

> ip route show
default via 10.8.2.1 dev tun0 
10.8.2.1 dev tun0 proto kernel scope link src 10.8.2.11 

So far it seems to work, but there probably is a reason this was not the default, and I don't know enough about networking to know what protections this change will break (or maybe this change is fine?).

Any help with properly fixing bittorrent tracker issue would be greatly appreciated :)

slingamn commented 4 years ago

This is a very interesting report, thanks :-)

Here's the output on my system using the current master branch of namespaced-openvpn (and iproute2 5.2.x on a 5.3 kernel):

shivaram@good-fortune:~$ ip route show
default dev tun0 scope link 
10.26.10.5 dev tun0 proto kernel scope link src 10.26.10.6 
shivaram@good-fortune:~$ ip route get 1.1.1.1
1.1.1.1 dev tun0 src 10.26.10.6 uid 1000 
    cache 
shivaram@good-fortune:~$ ip route get 127.0.0.1
local 127.0.0.1 dev lo src 127.0.0.1 uid 1000 
    cache <local> 

Although the default route is specified in slightly different ways in our two configurations, I don't understand how they would actually route any IPv4 addresses differently --- everything should be going through tun0 in both configurations.

Can you reproduce the problem with anything that isn't a bittorrent client (try curl for TCP or dig for UDP)? Failing that, could you get strace output from your bittorrent client? (You probably don't want to post the unredacted bittorrent straces, but it would help if you could find the syscall and the IP address that are failing).

8176135 commented 4 years ago

curl works with either routing for http trackers. And nc -u works with udp tracker hosts.

e.g.

curl -4 http://tracker.archlinux.org:6969/announce
curl: (52) Empty reply from server

Looking through the wireshark capture, it is successfully resolving the tracker address to ip, but just doesn't do anything with it. libtorrent must be doing something different to connect to the trackers.

I'm still looking through the strace.

slingamn commented 4 years ago

Makes sense. A couple tips: (1) use strace with -ff(2) "no route to host" is probably the errno EHOSTUNREACH (113), try grepping for that in the output.

8176135 commented 4 years ago

Tried strace -ff on both deluge and qbittorrent, both have no mention of EHOSTUNREACH of (113).

slingamn commented 4 years ago

Hmm, could also be ENETUNREACH (101)?

If you can find the thread/process that's doing the successful name resolution (by grepping for the domain name), you should be able to see the failing system call in the subsequent lines.

8176135 commented 4 years ago

Well, it seems my "fix" only works about half the time, with no apparent reason, sometimes when starting up the namespace and launching deluge or qbittorrent, it will just fail, and an hour later, magically work again, without even having to restart the namespace.

Anyway, when searching for archlinux I found these in the straces:

sendmsg(40, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="l\1\2\0010\0\0\0\2\0\0\0\242\0\0\0\1\1o\0\31\0\0\0/org/fre"..., iov_len=184}, {iov_base="\0\0\0\0\25\0\0\0tracker.archlinux.org\0\0\0"..., iov_len=48}], msg_iovlen=2, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 232
recvmsg(40, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="l\4\1\1\f\0\0\0\2\0\0\0\215\0\0\0\1\1o\0\25\0\0\0", iov_len=24}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 24
recvmsg(40, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="/org/freedesktop/DBus\0\0\0\2\1s\0\24\0\0\0"..., iov_len=148}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 148
recvmsg(40, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="l\3\1\0013\0\0\0\3\0\0\0u\0\0\0\6\1s\0\7\0\0\0", iov_len=24}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 24
recvmsg(40, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base=":1.1252\0\4\1s\0)\0\0\0org.freedesktop."..., iov_len=163}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 163
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
close(40)                               = 0
socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 40
setsockopt(40, SOL_IP, IP_RECVERR, [1], 4) = 0
connect(40, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("103.86.96.100")}, 16) = 0
poll([{fd=40, events=POLLOUT}], 1, 0)   = 1 ([{fd=40, revents=POLLOUT}])
sendto(40, "\341\0\1\0\0\1\0\0\0\0\0\0\7tracker\tarchlinux\3o"..., 39, MSG_NOSIGNAL, NULL, 0) = 39
poll([{fd=40, events=POLLIN}], 1, 5000) = 1 ([{fd=40, revents=POLLIN}])
ioctl(40, FIONREAD, [286])              = 0
recvfrom(40, "\341\0\201\200\0\1\0\2\0\r\0\0\7tracker\tarchlinux\3o"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("103.86.96.100")}, [28->16]) = 286
close(40)                               = 0

However, as far as I can tell, everything looks fine in the strace.

The only errors that is in that process are ENOENT (No such file or directory), and ENOPROTOOPT (Protocol Not Available) for SO_PEERSEC. Both of which also shows up when the applications are being ran outside of the namespace, and working fine.

No idea whats going on, probably going to just create a normal network namespace without a vpn attached and see what happens next.

slingamn commented 4 years ago

I couldn't reproduce this on my system with qbittorrent 4.1.7. I was able to connect to the Arch Linux http tracker (but not their UDP tracker, which qbittorrent said was "down"), and another well-known UDP tracker.

ghost commented 4 years ago

I can confirm this also happens on my Manjaro system with qbittorrent-nox v4.2.1 and kernel 5.4.23

slingamn commented 4 years ago

Thanks, that's helpful. Could you:

  1. See if the patch described in the first comment works?
  2. See if you can determine anything further from strace output?
ghost commented 4 years ago

With the patch http trackers do work, but not udp. I tried running strace on "strace -f -e trace=network -s 10000 nc -u udp://tracker.archlinux.org:6969" which resulted in "recvmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base=":1.3395\0\4\1s\0)\0\0\0org.freedesktop.DBus.Error.NameHasNoOwner\0\0\0\0\0\0\0\5\1u\0\2\0\0\0\10\1g\0\1s\0\0\7\1s\0\24\0\0\0org.freedesktop.DBus\0\0\0\0.\0\0\0Name \"org.freedesktop.resolve1\" does not exist\0", iov_len=163}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) = 163". Which is also a prominent message in my strace qbittorrent-nox logs

slingamn commented 4 years ago

Oh, that makes a lot of sense actually. That's systemd-resolved and it's recommended that you disable it in order to use namespaced-openvpn (although the recommendation may not be sufficiently prominent):

https://github.com/slingamn/namespaced-openvpn#dns-hardening

It's actually good to know that this fails, rather than successfully doing plaintext DNS lookups outside the namespace.

8176135 commented 4 years ago

@outnos Can you try another UDP tracker, I think udp://tracker.archlinux.org:6969 is just down. It didn't work for me even outside the namespaced-openvpn.

Other udp trackers seems to work for me.

ghost commented 4 years ago

So after trying with "Solus-4.1-Budgie" torrent i can see that adding the default gateway also fixes udp, so im gonna add that to my upscript, thanks for the help!

Its this for anyone interested: route add default gw $(ifconfig tun0 | grep "destination" | grep -o "[^ ]*$") tun0

slingamn commented 4 years ago

Do you have strace output with and without the patch?

The reason I'm hesitant to consider the patch is because I don't see how it can change anything --- it should not affect the routing of any address.

ghost commented 4 years ago

log.txt fixlog.txt

Yes, a noteable difference is: [pid 1025] openat(AT_FDCWD, "/run/systemd/machines/tracker.opentrackr.org", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) fix: [pid 1751] openat(AT_FDCWD, "/run/systemd/machines/tracker.opentrackr.org", O_RDONLY|O_CLOEXEC <unfinished ...>

Other than that i cant actually see the issue, it does seem to transfer some data back and forth, but qbittorrent still shows them as not working The files are me going into the webui, checking the status of the trackers on Solus-4.1-Budgie as the only torrent (waiting until resolved as working or not working) and shutting it down.

slingamn commented 4 years ago

I think the apparent difference there is spurious, you can see the ENOENT two lines later (I think the strace output just breaks off temporarily to capture a syscall on a different process):

[pid  1751] openat(AT_FDCWD, "/run/systemd/machines/tracker.opentrackr.org", O_RDONLY|O_CLOEXEC <unfinished ...>
[pid  1750] sendmsg(20, {msg_name={sa_family=AF_INET, sin_port=htons(57215), sin_addr=inet_addr("89.153.245.229")}, msg_namelen=16, msg_iov=[{iov_base="d1:ad2:id20:\351\356k*\271\0010\23R=37\245\267\231r\254!\352#"..., iov_len=115}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, MSG_NOSIGNAL <unfinished ...>
[pid  1751] <... openat resumed>)       = -1 ENOENT (No such file or directory)

I'll look around for other potential causes.

slingamn commented 4 years ago

Does disabling systemd-resolved change anything?

ghost commented 4 years ago

I disabled it before trying solus 4.1, so no

justinkb commented 4 years ago

This might be an upstream libtorrent issue