Opened 8 years ago

Last modified 8 months ago

#776 reopened Enhancement

Option: Bind outgoing connections to local port

Reported by: peterdk Owned by: charles
Priority: Normal Milestone: None Set
Component: libtransmission Version: 1.91
Severity: Normal Keywords: patch-needed
Cc: transmission@…, tiennou7@…, tom@…, elsdoerfer, zl29ah@…, kenden@…

Description

I am using QoS at home to manage my bittorrent traffic. Unfortunately not all trafic is caught with the L7 and IPP2P filters. Though it is possible to set incoming ports, it is not possible yet to define the outgoing port(s). QoS filtering is therefore not really possible, only if one would totally define all traffic except www traffic as "low" class.

A solution to this problem is to bind all the outgoing bittorrent connections to a specified local port instead of just letting the OS randomly assigning a unique port for every single one.

Azureus has implemented this and this allowd for a easy QoS rule that filters all traffic coming from the defined port. It is a ideal solution for home QoS filtering without having any effect on the QoS of ISP's, so possible encryption doesn't need to be turned off.

I have spoken with wereHamster on IRC in the Transmission channel and the first conclusion was that it is not possible to initiate more connections from a single port. After some research it appeared that this is not true.

Someone from the Azureus channel explained to us how it could be done:

[17:55] <wereHamster> so I'd like to know how it's possible to initiate multiple connections from the same port :)
[17:58] <The_8472> tools -> options -> connections -> advanced network settings -> bind to port
[17:58] <wereHamster> I know, but how is it technically done, bind() fails if the port is already taken (EADDRINUSE
[17:59] <The_8472> use SO_REUSEADDR
[18:01] <wereHamster> This socket option tells the kernel that even if this port is busy (in the TIME_WAIT state), go ahead and reuse it anyway. If it is busy, but with another state, you will still get an address already in use
[18:02] <wereHamster> error.
[18:02] <The_8472> that only applies to the same socket pair
[18:03] <The_8472> if it's a different socket pair then it does what you want
[18:03] <wereHamster> ok, thanks

Attachments (4)

bind.patch (5.0 KB) - added by charles 8 years ago.
first cut at implementing this. patch is against svn trunk
bind.r9230.patch (4.3 KB) - added by tiennou 7 years ago.
Patch against r9320 + settings.json
ticket-776-bind-local-port.patch (4.9 KB) - added by wereHamster 6 years ago.
ticket-776-bind-local-port-2.patch (4.8 KB) - added by elsdoerfer 6 years ago.

Download all attachments as: .zip

Change History (66)

comment:1 Changed 8 years ago by peterdk

Hmm, not really a clear request :).

The Conclusion is: I would like to see the option "bind to local port" implemented in Transmission.

Changed 8 years ago by charles

first cut at implementing this. patch is against svn trunk

comment:2 Changed 8 years ago by charles

Unix networking isn't really my specialty, so I'd appreciate it if someone could look over my shoulder here & review the patch.

comment:3 Changed 8 years ago by peterdk

Something from the Azureus wiki: that maybe is good to know.

  • Bind to local Port This sets outgoing connections to a fixed source port. This can be used with full cone NAT routers to reduce the number of NAT table entries and thus prevent crashes on some router models. When the outgoing port is bound to the same as the incoming port that might even solve NAT problems on full cone NAT routers.

Note: Binding to the same port as the incoming port works under Windows 2k and greater only. Unix users should use a different port. It's not working at all under Mac OS X.

comment:4 Changed 8 years ago by peterdk

  • Cc transmission@… added

comment:5 Changed 8 years ago by charles

I'm not going to check this in until someone with more experience in Unix networking has reviewed it.

comment:6 Changed 8 years ago by Chinstrap

Should be trivial to implement. The question is, do we make it always work this way, or make it an option? If it's always this way, just modify tr_netBind to always use the publicPort, and tr_netBind no longer needs to accept a port argument. If not, wrap the references to the socket variable in tr_netBind to check if we should use the passed argument for port, or the publicPort from config.

I'm willing to code this up myself once it is decided in which way it should be implemented.

comment:7 Changed 8 years ago by Chinstrap

I stand corrected. Not trivial to implement. We actually already Do The Right Thing™ for all connections when we are setting up our listener/nat/upnp/etc, but network connections for peer-io are handle by libevent, which does not do the right thing, apparently. Changing this would require major changes to libevent.

comment:8 Changed 8 years ago by charles

  • Resolution set to wontfix
  • Status changed from new to closed

comment:9 Changed 8 years ago by charles

  • Resolution wontfix deleted
  • Status changed from closed to reopened

comment:10 Changed 8 years ago by Chinstrap

Okay, I gave this a good go. And it works great...as long as you only are connected to a certain peer on a single torrent. As soon as you see the same peer on multiple torrents you will start failing to connect (identical source and destination ports between identical hosts, clearly a problem). The odds of this are relatively low on your average public torrent. Happens about 300 times in 10 seconds on a private tracker in my tests. I considered simply incrementing the port number when this happens and trying again which had two problems. One, it meant I had to break down and rebuild the socket every time it happened, which you started to actually notice after a few torrents. Two, with the same peer on MANY torrents, you start at your beginning port and have to run through that whole iteration x+1 times where x=the number of shared torrents you've conflicted on already. So once on the second torrent, twice on the third torrent, etc. By the 10th shared torrent you've had to break down and rebuild something like 54 sockets just to connect to a single peer for a single chunk. If you are sharing these 10 torrents with 100+ shared peers, holy crap, you spend all day creating and destroying sockets and never moving any data. At that point, you are better off with the old random port method.

I can only imagine what my testing this looked like to my poor router.

comment:11 Changed 8 years ago by charles

  • Resolution set to wontfix
  • Status changed from reopened to closed

comment:12 Changed 7 years ago by wadeb

  • Resolution wontfix deleted
  • Status changed from closed to reopened

I came upon this report, patch and discussion after Transmission killed my internet connection. I was at the point of switching ISPs before realizing that my low bandwidth Transmission transfer was the culprit!

Why not specify a range from which random ports will be chosen? A good sized range, say 62000-63000, would avoid the problem reported by Chinstrap.

Most routers let you specify QoS for a range of ports. My Linksys WRT310N with stock firmware allows me to assign three ranges of ports to a single protocol.

Chinstrap, would you be willing to post your final patch? Thanks!

comment:13 Changed 7 years ago by charles

  • Keywords patch-needed added; bind to local port tcp SO_REUSEADDR removed

comment:14 Changed 7 years ago by tiennou

It works perfectly, but the problem pointed out by Chinstrap above still applies : you can't make multiple connections to the same peer on the same addr:port pair without eating EADDRINUSE, at least not on OS X.

comment:15 Changed 7 years ago by wadeb

Awesome, thanks for updating the patch!

Did you try out picking the port randomly from a user defined range? That should at least reduce the instances of EADDRINUSE and allow a future reconnect attempt to succeed.

(I'm not sure what tr_sessionGetPeerPort( session ) does, that's why I'm asking)

comment:16 Changed 7 years ago by charles

I'm uncomfortable with this patch because I don't fully understand the implications.

Maybe this should be disabled by default, and enabled via settings.json? Seems to me anyone doing home QoS filtering wouldn't be scared off by editing settings.json by hand.

Changed 7 years ago by tiennou

Patch against r9320 + settings.json

comment:17 Changed 7 years ago by tiennou

@wadeb: It just forces T to use the same port (the one you set in the prefs) for outgoing connections. Right now it was defaulting to the OS default port range, which made it cumbersome to apply QoS, since you couldn't tell the difference between T outgoing connections and e.g. your browser (which use the same default port range).

@charles: I added a new settings.json parameter, "bind-local-port", initially disabled, which will force T to bind its outgoing ports to the same one as the incoming. The underlying issue is that SO_REUSEADDR works only if you're always creating connections to different hosts. The problem (that Chinstrap highlighted above) appears under the following conditions :

  • There's a peer that tracks two torrents (say 1 and 2)
  • We connect to it, handshaking we're interested in torrent 1.
  • We then try to open another connection to exchange torrent 2. Now when we try connecting to it, we will eat EADDRINUSE since we already have a connection with this host.

There is no obvious fix, or it would require tweaking our beloved Bittorrent protocol itself to contain the torrent info_hash in every message, and not just in the handshake, s.t we can maintain only one connection to a peer, independent of the torrent info_hash. On the other hand, maybe it doesn't happen so much, and it's a transient problem, since closing the first connection will allow others to be made subsequently...

comment:18 Changed 7 years ago by wadeb

@tiennou: Gotcha. My point is that the EADDRINUSE problem you are discussing with charles would be solved if you pick a random outgoing port within a range, instead of a single port. Just add separate TR_PREFS_KEY_BIND_OUTGOING_PORT_MIN and TR_PREFS_KEY_BIND_OUTGOING_PORT_MAX keys, and pick a random port in between them when creating an outgoing connection. That will allow users to establish QoS without the EADDRINUSE problem when multiple connections are attempted to the same peer.

comment:19 Changed 7 years ago by tiennou

  • Cc tiennou7@… added

@wadeb: It could effectively be done, but that would only make it less likely to fail (as opposed to fixing it once and for all ;-)) since it could reopen another connection to the same host with the same local port, even randomly chosen. Another solution (based on Chinstrap research above) would be to add a global list of outgoing connection which would be used to tell if we already have opened a connection to this host, preventing socket creation/destruction. That might require quite a bunch of changes, and could turn out to be completely impractical from a performance standpoint.

I guess I'll wait for charles's advice. The current patch works as expected, given the probability of connecting twice to the same peer is (in a public swarm that is) pretty low.

comment:20 Changed 7 years ago by wadeb

@tiennou: With a random choice, there is still a tiny chance of picking an already used port. But if the user gives a range of say 100 ports, it would be incredibly low. When enabled, your patch makes it impossible to connect twice to the same peer (a reduction in functionality). With a random choice, it would only take a few tries to connect.

Choosing randomly from a range would be a minor change to the patch you've already posted. If in the future, someone decides to do the complex solution involving a list of outgoing ports, it will still need a range of ports from the prefs file. So that patch would be a more logical next step from the patch I am proposing.

comment:21 Changed 7 years ago by tiennou

Because I had a doubt, I checked something : a peer that we fail to connect to at least once will be marked as unreachable, and we will never attempt to connect to it again. We will accept its incoming connection, but it will never be clean again. It's not actually unreachable, since it's caused by the local network stack. I'm not sure how to distinguish between unreachable and "failed-because-already-connected", so it means :

  • Using a random port range can fix the issue with same peer on multiple swarms, to a point.
  • It can still fail if we happen (out of luck, I agree) to reconnect to the same peer on the same random port that we chosen earlier, marking it as unreachable while it's not technically true.

I'll update the patch later with the local-random-range-thing.

@charles: I find it strange that an unreachable peer be "dropped" like that. Couldn't it be marked as reachable again whenever it connects successfully to us ?

comment:22 Changed 7 years ago by charles

@charles: I find it strange that an unreachable peer be "dropped" like that. Couldn't it be marked as reachable again whenever it connects successfully to us ?

I think there are two sides to this. Unreachable peers are often (maybe even usually) due to the peers' incoming peer ports being closed/firewalled/etc, so just because they can connect to us, doesn't mean we should add them to our list of peers to try connecting to later.

comment:23 Changed 7 years ago by bocadillodeatun

I'm also facing the same QoS / traffic shaping problem in my LAN. The ones I share the LAN with are all on Windows and using uTorrent, which has solved the problem by allowing a SOURCE port range for outgoing connections to be specified.

I've been observing how connections get established in uTorrent when this option is enabled: if the range is configured to be from port "x" to port "x+y" (which, btw, can only be configured from the advanced setting tab... which would be an extra aid to place this option in T in the "settings.json" file), then uTorrent will always try to set the source port of new connections to "x". Only when it fails, it will try x+1, x+2 and so on.

So... it turns out that MOST connections are from port "x". Only a few of them from x+1 or x+2 (usually those connections performed to a peer which we are already connected to using "x"), and some rare ones from some other port x+? (does not seem to follow any logic)

Anyway... it looks like, when trying to establish a new outgoing connection, uTorrent just uses the first port from the pre-configured range (instead of just trying any random OS-provided port between 1025 and 65000). Only when the "bind()" call fails (for any reason... we don't really need to worry about this. It's the OS responssability to tell when a specific port is not valid), it tries some other port (usually the next one).

I guess T could do the same (as it is the ONLY way to apply QoS rules!)

So... I would suggest to create two nwe entries in "settings.json":

  • "outgoing_port". If it is set to "0" (default) it would just let the OS pick a source port for the outgoing connection (that's what's happening now) and ignore the "outgoing_port_max" entry. It it's value is any other than "0", then that would be our "x" (ex: 60000)
  • "outgoing_port_max". This is our "x+y" :) Ex: 60500

All this seems to be what tiennou last said. How that patch going? :)

comment:24 Changed 7 years ago by wereHamster

  • Cc tom@… added

Changed 6 years ago by wereHamster

comment:25 Changed 6 years ago by wereHamster

  • Version changed from 1.06 to 1.91

For those who want to see the full history, please take a look at the excellent, recently introduced new feature on github: compare view: http://github.com/wereHamster/transmission/compare/master...ticket/776-bind-local-port. The feature branch consists of two commits but I only attached the cumulative patch here. For a detailed explanation what each commit does take a look at the corresponding commit messages on github as I don't want to repeat the text here.

comment:26 Changed 6 years ago by elsdoerfer

  • Cc elsdoerfer added

Sorry for being noisy, but what's the current status on this? I'd really like to see this make it into trunk.

comment:27 Changed 6 years ago by wereHamster

1) Take my patch. 2) Port to latest version 3) ??? 4) profit

comment:28 Changed 6 years ago by elsdoerfer

Porting the patch seems really quite straightforward, just a handful of merge conflicts due to new lines added in both heads overlapping:

http://github.com/miracle2k/transmission/compare/master...ticket/776-bind-local-port

It also compiles and seems to work:

michael@sweetwater:~/.config/transmission$ netstat -pn | grep trans
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 192.168.178.21:51413    71.104.161.193:59368    ESTABLISHED 13572/transmission-
tcp        0      1 192.168.178.21:51414    89.210.229.122:41092    SYN_SENT    13572/transmission-
tcp      100      0 192.168.178.21:51414    187.138.0.175:34163     ESTABLISHED 13572/transmission-
tcp        0      1 192.168.178.21:51414    86.166.248.119:35982    SYN_SENT    13572/transmission-
tcp        0      1 192.168.178.21:51414    71.1.120.103:11309      SYN_SENT    13572/transmission-
tcp    65588      0 192.168.178.21:51414    116.47.33.33:53528      ESTABLISHED 13572/transmission-
tcp       93      0 192.168.178.21:51414    97.122.171.227:26564    ESTABLISHED 13572/transmission-
tcp    43139      0 192.168.178.21:51414    85.224.215.134:44110    ESTABLISHED 13572/transmission-
tcp        0      1 192.168.178.21:51414    96.53.26.210:60708      SYN_SENT    13572/transmission-
tcp    64569      5 192.168.178.21:51414    68.63.123.6:57471       ESTABLISHED 13572/transmission-
tcp    65580     10 192.168.178.21:51414    27.32.7.235:23644       ESTABLISHED 13572/transmission-
....

Changed 6 years ago by elsdoerfer

comment:29 Changed 6 years ago by charles

elsdoerfer, could you refactor this s.t. the goto is removed?

comment:30 Changed 6 years ago by elsdoerfer

Without goto:

http://github.com/miracle2k/transmission/compare/master...ticket/776-bind-local-port

Could also be written as "while(!port_found)" rather than while(1), if that is preferable.

comment:31 follow-up: Changed 6 years ago by elsdoerfer

I've updated the github fork to the newest trunk version.

What's the status on step (3)? ;)

comment:32 in reply to: ↑ 31 Changed 6 years ago by wereHamster

Replying to elsdoerfer:

What's the status on step (3)? ;)

That remains a mystery, hence the '???' ...

comment:33 Changed 6 years ago by mn

i'm new here, but i would realy need this feature. is this dead, or just waiting for months to get into a trunk?

comment:34 Changed 6 years ago by rberger

This is the main reason I'm not using transmission but azureus. The latter's been having this feature at least for the 4 years I've been using it. And, for the average home user, RAM is much easier to get than upstream bandwidth. So, with my recent server upgrade to 8GB, I don't really care about the 600MB azureus is eating right now RSS wise. But I do care about the traffic shaping the source port bind allows me to do, and thus make full use of my bandwidth without having interactive apps suffer.

comment:35 Changed 5 years ago by Tiver

I had been using a feature like this with Azureus and uTorrent. I'd love to switch over to Transmission, but the lack of this feature is blocking me from doing so.

What needs to happen for this to be integrated? It looks like a year ago it was updated to patch latest trunk and some other fixes made, but then it just sort of died off. Wild guess it needs to be updated again to the trunk, but if say I or someone else updated the patch what else needs to happen for it to make it into the trunk?

comment:36 Changed 5 years ago by iluha

I have used qBittorrent (http://www.qbittorrent.org/). It has similar feature: a user-definable port-range for outgoing connections. In advanced setting it is possible to set "Outgoing ports(Min)" and "Outgoing ports(Max)".

This must be easier to implement and gives more control over traffic in network.

comment:37 Changed 5 years ago by roeme

Alright, this seems to be of use for some users. Before further work gets done on this, I'd like to know from the OP and/or contributors if the bandwith limiting available in T 2.42 isn't sufficient enough? I let T work at my home all day and night, but not with full speed (something like 95%) - this allows me to still have a snappy ssh console.

Or do you simply want to have all available bandwith, and as soon as other, more important applications are used, have the bandwidth available to BT reduced accordingly?

Thanks

comment:38 Changed 5 years ago by headofbucket

I don't want to use internal bandwidth limiting, I want to limit transmission's ports so that my routers and firewalls can properly characterize it.

comment:39 Changed 5 years ago by daenney

I'll try and explain best I can.

I agree with the Transmission developers that for most people Transmission's internal bandwidth limiting will suffice. However, I like a few others am not most people and have taken to using QoS in our network to ensure that certain services always have a set amount of bandwidth available and that less important services do not steal bandwidth from more critical things.

In order to do this most is done port-base. For example I have a qdisc om my eth0 telling it that port 22, aka SSH, is seriously important, needs to be allotted at least 128kbps and has priority 1, the highest it can get meaning it can borrow additional bandwidth from services with a lower priority when needed and services with a lower priority can never infringe on SSH's allotted minimum bandwidth.

Similarly, HTTP and HTTPS-traffic are set up with a qdisc that gives them 256kbps and a priority of 5, meaning that if necessary SSH can steal bandwidth from HTTP in order to ensure its function.

The same most of us would like to do to Transmission, give it a qdisc with perhaps even no bandwidth at all and just a priority set to 999 which essentially means it can use whatever bandwidth is available but will have the relinquish it to any service set with a higher priority. This ensures that Transmission can use the full bandwidth of our connection without actually hampering other, more critical, services.

The beauty of this solution is that it is universal through your network, packets are tagged with it and switches/routers that support this can then also manage their queue's accordingly ensuring a snappy network without manually having to cap bandwidth in different applications. It also becomes a lot easier to manage than having 10 different applications with each their own bandwidth limitation rules.

To do this however we need to be able to know which ports Transmission is using, outgoing, something that is currently random. Though some of this QoS can be done on L7 the second SSL comes into play you're mostly lost.

comment:40 Changed 5 years ago by soehest

I would like this addition as well. Because of QOS as described above. But also if working with strict firewall which limits outgoing connections. This is now impossible with Transmission which is a very nice client but does lack such a basic function as specifying outgoing ports.

comment:41 Changed 4 years ago by mk.fg

Allow me to pitch in with another use-case for "everything from a single port" - SNORT (IDS) in my network dies in flames from time to time because it has to process bittorrent traffic (there are probably multiple PCRE's being ran over every packet as we speak), but since I have some power over (most) torrent daemons, I can easily exclude traffic from a single port from NFQUEUE.
Alternative with random-range (which I think exists) is leaving too large blind spot for virii in that range or possibly limiting the number of outgoing connections.

So, if it's not that hard (and I see that patches were proposed already, which I will probably be trying to apply in a minute), please add/merge this functionality into mainline.

comment:42 Changed 4 years ago by matthijs

I have another usecase for this: I have a daemon that listens on port 3991 and which is restarted every now and then. Sometimes it happens that, in the time that the deamon takes to restart, transmission opens up a connection to another peer using port 3991 as the source port. When the daemon is then starting again, it fails to listen on that port, since Transmission has taken it.

Arguably, this isn't Transmissions fault really, but given the large amount of connections it uses, it's the single biggest cause of this problem. Incidentally, the patch in this ticket would fix my problem (technically, just setting SO_REUSEADDR would be enough, but actually guaranteeing the source ports used by Transmission are chosen from some high range would be even better).

comment:43 Changed 4 years ago by rberger

Any progress on this yet? Just downloaded 2.73 and still had to patch it for a source port bind. Like I've been patching every version I upgraded to for years.

Just in case anybody's still wondering: built-in rate limiting is not enough. QOS, like the Linux traffic shaping I'm doing on my router, is able to dynamically prioritize traffic. This is particularly useful when the goal is to saturate upstream bandwidth while still using interactive applications, like VoIP or fast paced online games.

And that saturating upstream actually is a goal should be evident from most connections being asymmetrical, like the "A" in ADSL. I.e. seeding to a given ratio being a lot more of an issue than just leeching.

I hope people do recognize and appreciate this simple yet essential point.

comment:44 Changed 4 years ago by L29Ah

  • Cc zl29ah@… added

bump

comment:45 Changed 3 years ago by Bugmenot

Just setting up QoS myself and am disappointed that Transmission on OS X drags behind other clients in regards to this feature.

comment:46 Changed 3 years ago by randominhabitant

I'm also following this Transmission QoS thread with great interest as I need to find a way to defend my VoIP traffic, son's gaming activity, telnet, and interactive ssh sessions while providing Transmission 2.75 (13675) with as much bandwidth as possible.

My network connection has 4Mb/up which appears to translate to about 500kB/s up in Transmission. With experimenting I've found nothing over 50kB/s upload speed allows for a decent VoIP call. So I currently use scheduled times and Alternative Speed limits from 8:00-23:00 to solve this issue. I would really like to find a way to help Transmission be a good network citizen with QoS while using the "Require encryption" option so I can give it more than 10% of my available bandwidth. Currently, Wondershaper-Linux, is the only solution I know about for QoS. I've been monitoring my network with Wireshark trying to come up with workable solutions. Nothing so far.

I explored my options with Azureus-Vuse and qBittorrent and have made the decision to tough it out with Transmission because of good Transmission application reliability and Transmission's Blocklist feature. Both of these are more important to me than my current QoS needs. I really would like to have a solid QoS solution for my infrastructure to allow me to unleash Transmmission! Thank you for all your effort so far.

comment:47 follow-up: Changed 3 years ago by iluha

It is possible to set port-range in settings-file (~/.config/transmission/settings.json in linux).

Just edit these lines to set your own range:

  "peer-port-random-high": 65535,
  "peer-port-random-low": 49152,

comment:48 Changed 3 years ago by randominhabitant

Most of this thread appears to focus on QoS with one solution; bind Transmission to a predictable port-range to allow cooperation with QoS network management solutions. This is one possible solution. There might be others.

I don't know if it will help, but I found this QoS article contrasting what is achievable using Linux QoS with what appears to be a better QoS solution by Cisco to shed more light on the QoS issue. http://www.softwareopal.com/qos/default.php?p=linux103-voip

This short article makes me wonder if Transmission can include any of these ideas in software design with the idea of being a better network citizen? Followed by the question, should Transmission include any of these ideas? (or do they belong somewhere else?) Maybe some of these ideas are easier to implement in Transmission than binding to specific ports and will result in improvement?

I looked for a forum to discuss the Transmission-QoS topic and couldn't find it, so I'm generalizing this issue thread to QoS for this posting. Apologies in advance.

comment:49 in reply to: ↑ 47 ; follow-up: Changed 3 years ago by Tiver

Replying to iluha:

It is possible to set port-range in settings-file (~/.config/transmission/settings.json in linux).

Just edit these lines to set your own range:

  "peer-port-random-high": 65535,
  "peer-port-random-low": 49152,

This has nothing to do with this ticket. These options, combined with peer-port-random-on-start, cause the listening port for transmission to be randomized on start. The listening port only affects incoming connections. This ticket is about binding the local port for outgoing connections.

Basically, outgoing connections currently use a purely random port selected by the OS, and connect remotely to whatever IP the other side is listening on. Combined with encryption this makes a nightmare for QoS.

As for the Cisco stuff, no I don't see that being useful. Far as I can tell it's marking the VoIP traffic based on the protocol, and marking traffic. This is the exact thing you can't do once you're dealing with an encrypted connection. The entire point of the encrypted connection is to avoid any protocol detection and instead appear the same as other encrypted connections.

comment:50 follow-up: Changed 3 years ago by mk.fg

To be fair, OSes seem to allow associating bound sockets with app that holds handles to them, and then mangling packets based on that info.

In linux, for instance, I imagine it might be possible to use --uid/gid matchers and a simple SNAT (rewrite packet source) rule to make kernel send these packets from the same port. I think kernel should be able to distinguish incoming packets on such nat'ted connections (e.g. if it's done using "src_ip, src_port, dst_ip, dst_port" tuples), and rewrite stuff back for them just fine.

Failing that, (on linux) uid/gid matchers can be used with "ip rule" (iproute2) to specify traffic classes for "tc" (linux QoS subsystem) and shape it as necessary right on the machine where transmission runs, if one has control over it.

And if router that should do the shaping is linux and transmission host is cooperative, one might just route/wrap/isolate all transmission traffic to e.g. ipip tunnel to that machine ("ip tunnel") and then mix it's easily-distinguishable (by source interface) traffic there with any other as necessary.

That's not to say that I won't like having much a simplier option, just to say that there are some options that don't necessarily involve DPI of encrypted traffic.

comment:51 in reply to: ↑ 49 Changed 3 years ago by randominhabitant

Replying to Tiver:

Regarding the Cisco approach, what specifically caught my eye was: "...LFI reduces delay and jitter by breaking up large datagrams and interleaving low-delay traffic packets with the resulting smaller packets." and

"RTPC is a technology that helps RTP run more efficiently, especially over lower-speed links, by compressing the RTP/UDP/IP header from 40 bytes to 2 to 5 bytes."

These two concepts may be at too low a level for Transmission to operate on directly, but could something like smaller data packets be useful and possible for Transmission to accomplish?

On my VoIP calls, if I let the Alternative rate go much above 50 kB/s the listener on the other end will say things like "the line has significant static which makes speech carried by the call difficult to understand. This may be due to a burst of large datagrams sharing the same link. Perhaps smaller datagrams, or a different throttling algorithm could reduce or remove this effect? By different throttling algoithm, I'm thinking high accuracy timer to evenly space each data packet in time, and/or making smaller data packets, leaving gaps for smaller VoIP packets to fill. Perhaps we need a separate VoIP button (next to Alternative Speed Limits) to apply these different algorithms, reverting to original "bulk" delivery behavior when VoIP isn't selected until experience can show us what works. (just a straw-man thought/concept to be kicked around).

Replying to iluha:

  "peer-port-random-high": 65535,
  "peer-port-random-low": 49152,

... These options, combined with peer-port-random-on-start, cause the listening port for transmission to be randomized on start. The listening port only affects incoming connections. This ticket is about binding the local port for outgoing connections.

Thank you for clarifying the application of these settings. I suspected as much from parameter naming, but it's nice to see my hunch backed up in writing.

... Far as I can tell it's marking the VoIP traffic based on the protocol, and marking traffic. This is the exact thing you can't do once you're dealing with an encrypted connection. The entire point of the encrypted connection is to avoid any protocol detection and instead appear the same as other encrypted connections.

So the very thing P2P protocol does by design to circumvent overzealous ISP's is now hindering our own QoS efforts. ;) Catch-22!

And if encryption isn't used, some ISP's (cough-cough; Comcast) will eventually block your traffic. I say this from my own experience from a year or more past.

I'm hoping these two last statements are overly simplistic and there is an actual solution to the QoS issue. Basically some of us have complex enough networks that our own microcosms are now facing some of the same issues as our upstream providers. Ah, progress! ;)

comment:52 in reply to: ↑ 50 Changed 3 years ago by randominhabitant

Replying to mk.fg: ...

And if router that should do the shaping is linux and transmission host is cooperative, one might just route/wrap/isolate all transmission traffic to e.g. ipip tunnel to that machine ("ip tunnel") and then mix it's easily-distinguishable (by source interface) traffic there with any other as necessary.

That's not to say that I won't like having much a simplier option, just to say that there are some options that don't necessarily involve DPI of encrypted traffic.

Thank you for posting this thought as I never would have considered the following solution which does work (for me) without IP Tunneling or new code! And I too, would appreciate a "simpler" solution.

Summary

  1. Setup a separate IP interface (alias device) for Transmission to use by itself on the machine running Transmission. i.e. Host machine device eth0 is configured with 192.168.1.7 and an alias device "eth0:Choked" made with 192.168.1.91
  2. Bind Transmission to the new 192.168.1.91/24 IP by modifying settings.json entries

"bind-address-ipv4": "192.168.1.91", "rpc-bind-address": "192.168.1.91",

  1. Since my Transmission machine is behind my firewall, I had to modify a forwarding rule to forward TCP packets from port 51413 to 192.168.1.91
  2. (optional) update DNS and Reverse DNS tables to give the new IP a name

i.e. transmission=192.168.1.91 [FQDN = transmission.mydomain.com]

  1. Setup your QoS software to throttle anything coming from 192.168.1.91 (the new transmission.mydomain.com machine)

PRO's:

  • All transmission network traffic (bind-address-ipv4), including the web interface (rpc-bind-address) now come from what looks like a separate machine on the network.
  • QoS management solutions can throttle a separate "Transmission" machine and all its generated network traffic.
  • The Transmission web interface can be accessed by name http://transmission:9091/transmission or http://192.168.1.91:9091/transmission

CON's

  • Requires Admin level access to your network. i.e. This should work for home use and most home routers (D-Link, Linksys, Netgear, etc) have all the necessary features. My emergency backup D-Link DIR-655 router box even has QoS built in, and is "green". My Linux server is my "router" and is currently performing these functions.
  • Requires enough technical understanding to configure and know where to configure. Beyond the abilities of most home users.
  • Linux - just add an "alias" to the adapter with new IP to create a new network interface.
  • MS-Windows - I don't know how to add a "new pseudo adapter" to accomplish the same functionality. A second "real" adapter for Transmission traffic could be added (USB ethernet adapter or some such other interface). Or maybe there is a better way to do this with MS-Windows QoS mechanisms?
  • MAC (OS-X) I would hope to find similar config options to Unix-Linux. If not, try a separate physical adapter, wired or WiFi?.

This solution seems obvious in hindsight. I verified this solution by watching network traffic with Wireshark from both the router and the "Transmission" machine perspectives. Now Transmission traffic isn't mixed in with other machine network traffic on the same IP and can be managed. Thanks mk.fg for the thought which produced this idea.

Now I just need to get my QoS solution running right... ;)

comment:53 Changed 3 years ago by randominhabitant

Good News - Bad News

Do you know the difference between Theory and Reality? (I was up most of the night figuring this out)

In "Theory" now that I have separated Torrent traffic from other traffic, I can manage the two streams separately and my problem should be solved. Just apply QoS software and bing, bang, boom, we're done. [sarcastic - "Right"]

In "Reality" I tried three different software QoS solutions {Wondershaper HTB, Wondershaper CBQ, and a new, still in development qos 1.0.1-1.1} and none are effective enough to solve the VoIP traffic mixed with Torrent traffic problem. I'm talking real VoIP traffic using G711 uLaw codecs and "standard" phone equipment, not Skype or Google Hangout, though these applications are impacted differently.

First for anyone wanting the "best" of what I found, here is the order from most desirable to not best:

  1. Wondershaper HTB 1.1a (WS-HTB)- Older and still very good solution. Looks like last changes were around 2003.
    • Has best dynamic performance range from low load to high traffic load.
    • Interactive SSH, TELNET, HTTP/HTTPS traffic stay nice and responsive even with heavy unlimited Torrent traffic (original design goal)
    • Under high Torrent load on a 4000kb/s uplink (20,000kb/s down) 1500MTU (required for MS-X-Box) ping times were at best around 100mS, jitter was high; rtt min/avg/max/mdev = 72.954/115.086/155.284/22.149 ms.
    • Hard to find that "magic" Uplink Bandwidth number to make this work right. On my 4000kb/s uplink, I finally settled on 2200 as the best performance number to use.
  2. qos 1.0.1-1.1 - Appears to use the same bucket mechanism as Wondershaper HTB, just a different algorithm for managing the data stream. Algorithm depends on "reserved high priority bandwidth". I didn't play with these parameters, just left them at default 256kb/s.
    • VoIP performance seemed to be about the same as Wondershaper HTB 1.1a
    • Torrent throughput was about half of WS-HTB which made me shift focus to WS-HTB.
    • If VoIP traffic quality were better, I'd probably try to stick with this solution. Since VoIP results didn't seem to be audibly better, and data throughput worse, I abandoned this path. Since this solution is still in development, it's worth continuing to watch.
  3. Wondershaper CBQ 1.1a - Performance seemed considerably more limited than Wondershaper HTB. Didn't spend a lot of time determining "why?"

X-Box was off during this testing. Internet network traffic was mix of 95% Transmission, 2% VoIP, 3% misc (son gaming, and voice communication). Focus was on VoIP call quality/performance during Torrent activity. My son was online gaming through about half of this evaluation. He did complain when his ping times went from 10-15mS to 100mS as diminished response seems to hinder his ability to compete. At 300mS he can't play. I'm not a gamer, so all I have is his input.

If I reduce network traffic to Torrent 50kB/s then as before, call quality is okay and ping times drop back to 10-20mS. Torrent limiting to ~150kB/s and calls were not "good", but still usable. Above 150kB/s and call quality was unusable. As near as I can tell the issue is "jitter".

While watching incoming torrent packets with Wireshark, I notice many, if not all, have flags set disallowing fragmentation of large data packets. Without the ability to break packets into smaller deliverable chunks and no ability to better control the time spacing of these large data packets (real-time delivery) it will be very difficult to allow torrent programs much more than a small fraction of network bandwidth during prime time hours.

My own home network is wired Gigabit with about 25 active+15 powered down IP devices connected to two fairly new "green" switches. My Linux box (AMD FX-8120 based) performs all the internal network routing with my one IP internet presence. With a wired network, my results related here are about as good as they're going to get. Wireless adds more delay and unpredictability to IP packet delivery for devices on either end of the connection.

I did find a Windows 7 way to separate torrent traffic from the rest of the machines IP communication similar to what I described earlier for Linux. In the network adapter IPv4 properties the IP setup has to be static or fixed with "Use the following IP address:". Then the "Advanced" button will allow a second IP to be associated with the same adapter. Dynamic settings or "Obtain an IP address automatically" in Windows 7 will clear out this additional IP area. Windows XP is able to associate both a Dynamic IP and Static IP with the same adapter. This is important because tools like Wondershaper can only work on an IP or range of IP's, like "192.168.1.90/29" which defines IP's .88, .89, .90, .91, .92, .93, .94, .95 as being in the range of hosts operated on. So all machines creating torrent traffic need to be using one of these IP's for their torrent program for Wondershaper to "see" and manage traffic.

Conclusion

While not scientifically "conclusive", I've developed a theory that until VoIP jitter can be better controlled, I'm unable to manage the coexistence of VoIP and Torrent traffic when torrent traffic exceeds ~10% of my ISP provided network bandwidth using currently identified software tools.

I can't solve this issue until QoS solutions improve, torrent design is modified to better coexist with other traffic, or I can afford to have two internet connections, one for VoIP and one for data, or some combination of these three. Until then, I can't allocate more than ~10% of my internet network bandwidth to Torrent traffic except during late night, early morning operating hours (about 8 hours).

Current "Alternative Speed Limits" do allow me to manage this well enough that I don't need to completely shutdown Torrent activity for VoIP calls to work.

I'll continue to look for solutions. Next stops are my VoIP provider to find out what equipment and techniques they use. And any real-time QoS leads I can find to reduce jitter (make VoIP packet delivery times more predictable, even if it means delaying other packet delivery with deadtime to deliver VoIP traffic at the right time).

comment:54 Changed 3 years ago by rberger

Just dropping my 2 cents on some recent posts of randominhabitant.

(1) Alias interfaces

An alias interface is actually a good solution. Another is throwing the bittorrent daemon into a dedicated virtual machine (also having it's own IP), which has the additional benefit of more security through insulation.

That's always been a concern of mine anyway. Since the entire world can potentially connect to my bittorrent daemon, what if there's a bug that could potentially be exploited to gain access to my system?

So running a dedicated KVM virtual machine specifically for the transmission daemon limits this risk to the specific VM.

(2) Traffic shaping

From my experience, traffic shaping really only works when just seeding. Because the buffers you're having control over are just those of your own router, and not those of your ISP's.

The main problem there has always been that the home LAN network speed (100MBit or 1GBit for example) is usually much faster than the internet link speed. So when seeding, your router usually starts buffering pretty soon, and that's where you can actually prioritize traffic to some actual benefit.

The moment your ISP starts buffering though all bets are off, and that's typically happening when you're leeching/downloading too, potentially even saturating your the downstream pipe. And while you can shape that traffic too on your router, it's of little use the moment your ISP's routing buffers kick in.

Still, since internet connections are typically asymmetrical, as mine is, much more time is usually spent just seeding, to maintain ratio. And that's why traffic shaping still is of actual use.

I'm myself using a manual setup (through a script invoking 'tc' I wrote a couple of years ago, on the basis of the findings of http://sourceforge.net/projects/adsl-optimizer/ ), and it's giving me much less latency on VoIP and gaming traffic than without shaping. But as said, this only when having negligible traffic downstream, i.e. when just/mostly seeding.

comment:55 Changed 3 years ago by peterdk

Long time ago I started this request. :) I see it still hasn't really been implemented, with a lot of discussion about it ofcourse.

Main reason why I wanted to see this implemented was that I want to have full upload bandwith available to transmission, but when I do something else, like downloading, dropbox syncing, or whatever non-bittorrent uploading/downloading, I want it to automatically be scaled down and totally not prioritized. Only limiting the upload rate does achieve it a bit, and my network at home isn't that problematic anymore these days as it was when I started this request. However, to have automatic QOS is so much more pleasant then having to manage this manually, either by stopping uploads when bandwidth is needed or by severely limiting upload speeds.

That said, I currently run Transmission again, now on Linux, after using utorrent for a while on windows. I love the speed Transmission gives me, especially upload speed, utorrent didn't really uploaded at high speeds. I think creating a 'alias network interface' is the best workaround mentioned here for me.

I still hope it will get implemented some day, but I understand this is mainly a feature we 'nerds' would love to have. However, I really think it helps all kind of people with allowing them to do proper QOS.

Well, back to uploading. :)

comment:56 Changed 3 years ago by randominhabitant

I'd like to add a couple more thoughts on this subject:

With network card aliasing, I am able to separate Torrent traffic from other network traffic. From this point of view the original thrust of this posting asking to help identify and separate torrent traffic is addressed.

The issue for me is still the impact of even moderate Torrent traffic volume on G.711u Asterisk VoIP traffic. Current QoS technology solutions I reviewed aren't able to address this need for my installation. What I need to find is a QoS solution which is VoIP aware and will manage the VoIP packet delivery correctly. So far the only solution I can find is from a clever fellow in Denmark http://www.smartsharesystems.com/. He wants $1050 for his lowest end solution (I contacted him). My "home" budget needs a price about an order of magnitude smaller than this price. Free (not including my time) would be even better. When I start running a business from my home, this price will be acceptable. Until then, this is a show stopper for me.

The problem is the QoS solutions I reviewed don't appear to ensure small 214 byte VoIP packets will be sent with consistent ~20mS (50Hz) timing when mixed with even moderate volumes of torrent traffic. And, I don't know why. This might be because I don't yet understand how HTB mechanisms work or are implemented under Linux. If the QoS mechanism could move VoIP packets to the front of the line and either provide no delivery delay, or a constant short delivery delay (<~40mS), I suspect VoIP quality would appear rock solid, even with heavy torrent traffic. I suspect if VoIP were handled right by QoS solutions that quality would remain excellent as long as transmission rates are kept low enough to prevent network data buffering in the ISP provided modem.

BTW, the largest Torrent packet I saw with Wireshark is only 4230 bytes (4.2KB). I have a 5Mb uplink. Transmitting a 4.2KB packet should only represent about 7mS of time on a 5Mb uplink. Jitter that small shouldn't be a problem. So what I want appears possible, in theory.

Until a nice out of the box QoS solution which correctly handles jitter and latency for VoIP comes along, or I can figure out how to build one with something like Firewall Builder http://www.fwbuilder.org, I'm stuck. Torrent traffic will have to be capped at 50KB/Sec during the hours I'm not in bed asleep.

If any of you knows a QoS solution I can look at to address Torrent/VoIP-Asterisk for my Linux system, I'd like to hear from you.

BTW, my name is Craig.

comment:57 Changed 3 years ago by subterfugium

Giving my thought here too.

I recently switched from windows+utorrent to linux and transmission. On win+utorrent setup I had outgoing (passive transfer ports) set to 40000-60000 and these ports were set as "Low priority" ports in my router config. As said previous comments, I can allow transmission to take full capacity of my WAN connections but if there's other connections with higher priority they will be processed before transmission traffic. I found other ticket suggesting to change TOS from default to lowcost but not sure how that is going to work.

This feature would be nice.

comment:58 Changed 20 months ago by liebezeit

comment:59 Changed 11 months ago by kadehen

  • Cc kenden@… added

comment:60 Changed 8 months ago by mbtmzc

This was a very useful discussion, but unfortunate that there is still no built-in solution for having Transmission work with QOS engines that have become commonplace in wireless routers. I guess I'll try setting up dual IP addresses as suggested by randominhabitant.

comment:61 Changed 8 months ago by mbtmzc

Are there OS X equivalents to the following preference settings in Transmission?

  • bind-address-ipv4
  • rpc-bind-address

comment:62 Changed 8 months ago by mbtmzc

I set up an alias IP address on my ethernet card, and running Transmission through it is kind of working. The one issue I see is that it looks like Transmission is still mapping the peer listening port in my router to the actual local IP address of my computer rather than to the alias IP address, while at the same time, Transmission is apparently looking for incoming connections on the alias address. The result is no incoming connections.

Note: See TracTickets for help on using tickets.