Can a server block multiple TCP connections from same machine?

Started by
4 comments, last by hplus0603 10 years, 5 months ago

For example, some commercial file sharing sites disallow simultaneous downloads from the same user using a free account.

Some people said the server does this by checking the source IP address, so tricks like using socks proxy can trick the servers.

My question is, for many people using the same ISP behind NAT, won't the server see all these people having the same source IP address? Won't blocking simulaneous downloads by identical IP would block all people behind NAT, even they are using different machines?

If that's true, is there any true method for server to tell TCP connections are originating from same machine?

Advertisement

You are right, in presence of NAT, there is no way (no easy, built-in way) to distinguish two machines behind NAT from two connections coming from one computer. NAT translates two different local IP addresses to the same externally visible address (only with different ports, just like two connections on the same machine would work, too).

The easiest and most obvious solution is to let users log in with username and password. Simply do not let any username log in more often than once simultaneously.

Another approach is that you send some "unique" identifier with every connection request, such as the MAC address or another of the computer's "serial numbers" that is reasonably unique (harddisk serial number, GPU model, local IP address). Store that identifier while a client is connected (not any longer, this is neither needed nor desirable), and do not allow another connection with the same identifier (or, the same identifier and the same publicly visible IP address to be sure -- otherwise two people might accidentially have the same cheap no-name ethernet card with a duplicate MAC and you block them. Yes, such cheap ethernet cards do exist.).

Obviously, this only works if you use your own client program and use a protocol that supports something like a "cookie" And, again obviously, since the client program is physically present at the user's computer, this can be forged by a moderately skilled user. Your users might also be grossly unhappy if it is revealed that you "spy on personal data". Which isn't really what you're doing, but in a very contrieved sense, one could see it that way, and certainly some very vocal people will publicly accuse you of doing exactly that, if they realize you're doing it.

Agreed -- the server can only see the IP source address, and in the case of NAT, everybody behind the same NAT may have the same IP address (large ISP load balance across multiple external IP addresses.)

For most services, there aren't that many users behind each NAT, so it's not a real problem -- especially when it's only for free accounts, and you want an incentive to pay, anyway.

Another way to try to separate users is to tie each connection to an account, and use some user-specific information to identify each account. To prevent users from creating multiple accounts, you have to be pretty strict, though, such as requiring a credit card payment and not allowing multiple accounts for the same credit card -- which in turn makes it hard for multiple kids in a single household to all have their own account, if mom only has one credit card.

In the end, the best balance in my opinion is to be pretty strict to free accounts, and to allow each paying account to be treated as a single user, even if the same person pays for more than one account (after all, that means more revenue :-)

enum Bool { True, False, FileNotFound };
All methods that purport to detect individual machines behind NAT can be spoofed or circumvented fairly trivially by a skilled reverse engineer. However, there are some options:
  • Generate a GUID for each machine your software is installed on. Submit this GUID during connection to "identify" the machine. This is easy to spoof but also trivial to implement and will stymie a good chunk of less-technical users.
  • Directly obtain some kind of identifying data about the host machine, such as MAC address, and use that for identification. This is hard to spoof but fails if users upgrade or replace hardware.
  • Remember that all IP connections can be uniquely identified by a 4-tuple consisting of host IP, host port, client IP, and client port. The remote (client) port chosen can be analyzed for patterns to detect large-scale repeat connections from behind NAT or other services. This is generally unreliable and hard to do effectively, though.
Your best bet (in my experience) is the GUID trick. Unless you're expecting thousands of incoming connections from the same IP, port allocation analysis is virtually impossible since you won't get enough data to analyze. It also assumes that the NAT implementation you're dealing with is fairly stupid in that it reveals port allocation patterns; most modern NAT implementations should in theory be doing secure random port allocation to defeat this kind of analysis.

Hardware signatures are fragile and annoying to people who tinker with their machines, despite being slightly harder to spoof. But again, a reverse engineer can easily find your code for retrieving hardware signatures and modify it to submit arbitrary machine IDs. It's only slightly more annoying to defeat than the GUID trick and far less trivial to implement and maintain, not to mention less portable.


This, like many security issues, is something best solved at a higher level. hplus enumerated some options for this already, but I thought I'd throw in another alternative: permit duplicate connections, but penalize them on some kind of curve. For instance, the first connection is "free", the second connection gets 85% bandwidth allocation, the third gets 50% bandwidth and extra latency, and so on. Exponential backoff is a decent model for implementing this and can be effective in disincentivizing use of open proxies and such. By the time a client hits enough duplicate connections to really make a difference to your service architecture, they'll be penalized so badly that it's not worth their effort, and the resulting load on your system is nominal by virtue of the fact that you're rate/throughput limiting the remote host.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

This is hard to spoof


Or trivial, if you (the user) know what the program is looking for, and are willing to patch the program, or use a re-writing proxy (which can be totally undetectable.)

permit duplicate connections


That doesn't really solve the user's problem, though. To limit bandwidth to duplicate connections, you'd need to detect those duplicates, and you're back where you started.
enum Bool { True, False, FileNotFound };

If we're assuming it was about bandwidth sharing and not security:

He would not know exactly from only the IP number, but if he throttles the connections independently for each group with same IP he would still save on bandwidth.

If you estimate its unlikely there are more than x real people behind the same NAT, and you only give first x connections 100% each and if more connections its equally shared (x*100%)/n, those people could still not abuse it to the max. They would maybe just get a x times speedup, but its limited.

The interesting thing is then how high x could get in reality for non-abusive use cases?

My main point is actually this:

If you provide value for users, you should charge for that value to cover your costs.

The set of things that can scale to large users at low costs (and thus allow "freemium" models) is actually fairly limited and often uninteresting, not to mention full of competitors.

If you can't make users want to pay for what you're doing, what you're doing probably isn't worth much to those users.

enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement