libtorrent doesn't always use external service to detect IPv6 / Leaks IPv6
Please provide the following information
libtorrent version (or branch): libtorrent-rasterbar: 2.0.7-1+b1
platform/architecture: Debian Linux bookworm x86_64
compiler and compiler version: unknown
please describe what symptom you see, what you would expect to see instead and how to reproduce it.
Hello,
I'm seeing this issue with qBittorrent 4.4.5, also see qbittorrent/qbittorrent#17970.
External IPv4 addresses are always detected through an external service. Relevant log lines in qBittorrent look like Detected external IP: $ipv4.
For IPv6, an external service is used to get the IP (this is correct). But in addition, it also just uses system IPv6s. Thus, there multiple IPv6 detected:
Detected external IP: $external_ipv6
...
Detected external IP: $system_ipv6
As a result, the system's IPv6 is being sent to trackers and leaked.
This is relevant when one is using a VPN that resides on a different machine, i.e. the router. The qBittorrent machine gets assigned the real (non-VPN) IPv6, but is still routed over the VPN in the end. Binding qBittorrent to the VPN's IPv6 is not possible, as the machine doesn't own that address - the router does.
Proposed solution: Allow disabling the auto-adding of system IPv6s to the external IP pool.
Thanks!
Repro:
- Set up qBittorrent machine with IPv4+IPv6
- Set up router with VPN
- Configure router to route all traffic from qBittorrent machine through VPN
- Start qBittorrent
- Observe qBittorrent log as it adds both the VPN's IPv6 and the system's IPv6 to the pool of external addresses
Thanks!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
not stale.
If this issue got more attention. I'd like to request that proper IPv4/v6 address selection to be implemented as well. https://github.com/qbittorrent/qBittorrent/issues/14155#issuecomment-1547001530
I'm not sure I follow the description in this ticket. My reading of qBittorrent issue 14155 is different from this ticket.
@haarp From the description of the ticket:
External IPv4 addresses are always detected through an external service. Relevant log lines in qBittorrent look like Detected external IP: $ipv4.
There is no external service used to detect one's external IP. I don't know what gives you that impression. Perhaps you refer to other peers as "services". Peers tell each other about the IP they see each other at.
For IPv6, an external service is used to get the IP (this is correct). But in addition, it also just uses system IPv6s. Thus, there multiple IPv6 detected:
Again, there's no "service". Peers tell each other which IP they're connected to. Trackers may also respond with the client's IP address.
Are you certain you're not connected to any peers via your system's IPv6 address?
As a result, the system's IPv6 is being sent to trackers and leaked.
Sending IP addresses to trackers is a problem. I've tried to remove this, but it turns out there are some communities that rely on this, specifically with private=1 torrents. So, there's currently a carve-out where IP addresses are sent to private trackers. Does that match your experience?
Proposed solution: Allow disabling the auto-adding of system IPv6s to the external IP pool.
If you want to just listen to specific IP addresses, just configure libtorrent to do so with the listen_interfaces setting.
Hey, thanks for the reply, @arvidn
Peers tell each other which IP they're connected to. Trackers may also respond with the client's IP address.
Yes, that's probably it. I assumed it was a service, but using trackers/peers for this makes sense.
Are you certain you're not connected to any peers via your system's IPv6 address?
Yes. All packets generated by the torrent client's user is tagged, and the router sends all tagged packets over the VPN. I see no way for the client to escape this. ...unless it's DNS shenanigans?
So, there's currently a carve-out where IP addresses are sent to private trackers. Does that match your experience?
Can't really relate, sorry. I have no experience with private trackers.
If you want to just listen to specific IP addresses, just configure libtorrent to do so with the listen_interfaces setting.
Unfortunately this is not possible in this setup, because:
Binding qBittorrent to the VPN's IPv6 is not possible, as the machine doesn't own that address - the router does.
So in summary:
The system's IPv6 ends up in the address pool, even tho that IPv6 is not used publically by the torrent client. The router sends the packets over a VPN instead.
Hypothesis 1: libtorrent looks at the system's IPv6 and simply adds it to the pool. Solution: Don't do that :)
Hypothesis 2: libtorrent sends the system's IPv6 to the tracker directly due to the private tracker issue mentioned by @arvidn above. This IPv6 then ends up in the pool aswell.
Hypothesis 3: My setup is flawed and somehow the client is able to bypass the VPN. I don't see how. Only DNS requests are resolved locally without the VPN being involved.
I don't know why VPN comes into the scope of this problem. But to clarify what I've added to the discussion, basically I also wonder how libtorrent figured out all possible IPv6 addresses to listen on.
- If libtorrent used any system calls to get the system's IPv6 then libtorrent should give users the possibility to choose to use only a temporary IPv6 address for better privacy.
- If libtorrent simply uses other peers' observation, then I don't know why the stable-private address is discovered in the first place. I've set up my NetworkManager to prefer a temporary IPv6 address for outgoing connection.
- Also, which IP got reported to the tracker is also a consequence of this problem.
If libtorrent used any system calls to get the system's IPv6 then libtorrent should give users the possibility to choose to use only a temporary IPv6 address for better privacy.
It does. The setting is called listen_interfaces.
If libtorrent simply uses other peers' observation, then I don't know why the stable-private address is discovered in the first place. I've set up my NetworkManager to prefer a temporary IPv6 address for outgoing connection.
libtorrent uses all interfaces by default. It sounds reasonable to pick IPv6 addresses that are temporary, if one is found. That's related to the ticket you linked to, not this one.
Also, which IP got reported to the tracker is also a consequence of this problem.
IP addresses aren't reported to trackers. Trackers look at the source IP of the connection.
All packets generated by the torrent client's user is tagged, and the router sends all tagged packets over the VPN. I see no way for the client to escape this. ...unless it's DNS shenanigans?
Before the packet is sent to the router, it picks an outgoing interface/source IP. libtorrent picks all interfaces by default. So from libtorrent's point of view, it will deal with the local interfaces.
If you want to just listen to specific IP addresses, just configure libtorrent to do so with the listen_interfaces setting. Unfortunately this is not possible in this setup, because: Binding qBittorrent to the VPN's IPv6 is not possible, as the machine doesn't own that address - the router does.
So, what do you want to achieve? (I'm pretty sure you want to pick a specific interface or source IP).
The system's IPv6 ends up in the address pool, even tho that IPv6 is not used publically by the torrent client. The router sends the packets over a VPN instead.
Suspicion 1: libtorrent looks at the system's IPv6 and simply adds it to the pool. Solution: Don't do that :)
what pool?
Suspicion 2: libtorrent sends the system's IPv6 to the tracker directly
Can you describe the symptom, sample, capture or measurement that gives you this impression?
Suspicion 3: My setup is flawed and somehow the client is able to bypass the VPN. I don't see how. Only DNS requests are resolved locally without the VPN being involved.
So, do you capture packets on your router's WAN port to see this?
Thank you for teaching me all the knowledge of, trackers, internet facing software (and mmap before). Really, a huge thanks!
So if I understand correctly, excepting for libtorrent's default behavior to listen on all IP address, there is nothing like "detection" and "parsing" of actual IP address functionalities in libtorrent. And I should feel relieved that if libtorrent's user chose the correct IP addresses they want to use, the trackers won't know other IP addresses that users didn't pass to that libtorrent function (listen_interfaces) and doesn't want trackers to know.
And, this "prefer temporary IPv6 address over stable address" functionality should be implemented in downstream qBittorrent client. So to solve my specific problem I should only continue the discussion there.
Is that right?
So if I understand correctly, excepting for libtorrent's default behavior to listen on all IP address, there is nothing like "detection" and "parsing" of actual IP address functionalities in libtorrent.
Only because you exempted it. When no listen interface is specified, libtorrent will enumerate interfaces and listen on all of them (with a few exceptions, like interfaces that are down etc.).
And I should feel relieved that if libtorrent's user chose the correct IP addresses they want to use, the trackers won't know other IP addresses that users didn't pass to that libtorrent function (listen_interfaces) and doesn't want trackers to know.
That's correct. This code snipped may be of interest. This is the carve-out for private trackers I talked about:
https://github.com/arvidn/libtorrent/blob/RC_2_0/src/torrent.cpp#L3056C2-L3076
It can be disabled by enabling anonymous_mode.
what pool?
I was assuming there was a pool of known external IP addresses. I stand corrected.
Can you describe the symptom, sample, capture or measurement that gives you this impression?
Sorry, suspicion was the wrong word. It was just a hypothesis.
So, what do you want to achieve? (I'm pretty sure you want to pick a specific interface or source IP).
Not quite. The point is that I have a external IPv6 that is different from the system IPv6, handled by the router. I verified multiple ways that the router properly forces qBittorrent's packets over this external IP (the exception being DNS request, which are resolved by a local nameserver not hooked up to this external IP)
libtorrent can't bind or listen to that external IP. It's not present on the machine it's running on, it belongs to the router.
Yet I'm seeing these logs in qBittorrent. They seem originate from libtorrent's external_ip_alert:
Detected external IP: $external_ipv6: This is the correct external IPv6. Given the information in this thread, this is probably due to trackers/peers responding with that IP.
Detected external IP: $system_ipv6: This shouldn't happen. Where did this come from? It is not the external IP of the client. Was or is something being leaked?
IPv4 doesn't have this problem.
Before the packet is sent to the router, it picks an outgoing interface/source IP. libtorrent picks all interfaces by default. So from libtorrent's point of view, it will deal with the local interfaces.
Exactly, this is correct behavior. libtorrent doesn't necessarily know (or need to know) how the packets ultimately get routed. That's the router's job.
Not quite. The point is that I have a external IPv6 that is different from the system IPv6, handled by the router
So you could bind to an interface that can route to your router (e.g. not loopback)
libtorrent can't bind or listen to that external IP. It's not present on the machine it's running on, it belongs to the router.
Right, but you don't really want (or need) libtorrent to bind to the VPN's external address anyway.
Detected external IP: $system_ipv6: This shouldn't happen. Where did this come from? It is not the external IP of the client. Was or is something being leaked?
You could know for sure by capturing packets with tcpdump or wireshark. Perhaps your client connected to itself via the IPv6 address. Or perhaps you have some other client on the local network you connected to.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.