In a Linux/C++ TCP server I need to prevent a malicious client from opening multiple sockets, otherwise they could just open thousands of connections until the server crashes.
What is the standard way for checking if the same computer already has a connection on the server? If I do it based off of IP address wouldn't that mean two people in the same house couldn't connect to the server at the same time even if they are on different computers?
Any info helps!
Thanks in advance.
TCP in itself doesn't really provide anything other than the IP address for identifying clients. A couple of (non-exclusive) options:
1) Limit the number of connections from any IP address to a reasonable number, like 10 or 20 (depending on what your system actually does.) This way, it will prevent malicious DoS attacks, but still allow for reasonable usability.
2) Limit the maximum number of connections to something reasonable.
3) You could delegate this to a higher-layer solution. As a part of your protocol, have the client send a unique identifier that is generated only once (per installation, etc). This could be easily spoofed, however.
I believe 1 and 2 is how many servers handle it. Put them in config files, so they can be tuned depending on the scenario.
There is only IP address to base "is this the same sender", unless you have some sort of subscription/login system (but then someone can try to log in a gazillion times at once, since there must be some sort of handshake for logging in).
If two clients are using the same router (that uses NAT or some similar scheme), your server will see the same IP address, so allowing only one connection per IP address wouldn't work very well for "multiple users from the same home". This also applies if they are for example using a university network or a company network.
So depending on what you are supplying and how many clients you can expect from the same place, you may need to go a fair bit higher than 10. Of course, if you log when this happens, and you see a fair number of "looks like valid real users failing to get in", you can adjust the number.
It may also make sense to have some sort of "rolling average", so you accept X new connections per Y seconds from each IP address, rather than having a fixed maximum number. This is meaningful if connections last quite some time... For short duration connections, it's pretty pointless...
Related
I am running a server (that uses tornado python) on a single AWS instance and I am running into spikes in websocket latency.
Profiling the round trip time from when a websocket message is sent to the client, which then immediately sends an ack message back to the server, to when the server receives the ack message yields an average of <.1 second, however I note sometimes it goes up to 3 seconds. Note: there are no spikes when running the server locally.
What could be the cause or fix for this? I looked at the CPU usage and it only goes up to 40% max. The spikes are not correlated with heavy traffic (2 or 3 clients usually) and the client's internet seems fine. I find it hard to believe the instance is going beyond capacity with such low usage.
The fact that the spike is 3 seconds is actually telling you a lot more than you may suspect, about the nature of the problem.
It's packet loss.
TCP, as you likely know, is said to provide "reliable" transport, guaranteeing that payload sent is received by the far end in the order in which it was sent, because TCP reassembles things in the correct order before delivering the payload. One significant way in which this is accomplished is by the automatic retransmission of packets that are considered to have been lost.
You'll never guess the default initial timer value for retransmissions of lost packets. Or, perhaps, now, you will.
It's 3 seconds in many, if not most, implementations, based on standards established several years ago in a time when the bandwidth and latency of today's transmission links were unheard of, perhaps unimagined.
You won't see evidence of the retransmission at at the websocket server or the client software, because TCP shields the higher layers from knowing that it occurs... but 3 seconds is a dead giveaway that this is exactly the problem.
You'll see the retransmissions of the traffic occurring if you observe the network traffic with a packet sniffer, though that will only serve to confirm that this is the issue.
It could be loss from server to client, or loss from client to server. The latter is generally more likely, since clients often have a lower amount of available upstream bandwidth... but the directionality of the packet loss doesn't clearly indicate the physical location where it is occurring. Unless your client keeps track of local time, so that request and response initiation times can be correlated, you don't know whether the delay is in the message, or in the acknowledgement.
Under relatively light load, it seems unlikely that the problem is on your instance or in the AWS network on your side, and you obviously can't connect a sniffer to arbitrary points on the Internet to pinpoint the problem.
Given a case like this, it may be easier -- and surprisingly feasible -- to prove where the problem isn't, rather than where it is.
One technique for this would be to create a deliberate detour for the traffic through different equipment located elsewhere -- such as a different AWS region or another cloud provider.
First, of course, you'll want to learn to spot these retransmissions using wireshark.
Then, configure a proxy server at a different location, using a simple TCP connection proxy -- such as HAProxy, or even a simple tool like redir or socat.
Such a configuration will listen for connections from clients, and when one is established, will create a new TCP connection to the destination (your websocket server) but -- importantly -- they only tie the two connections together at the payload level -- not the TCP level, and of course nothing lower -- so retransmissions will only be seen on the wire at all between this intermediate server and the end of the connection with the packet loss problem. The other end will show no evidence of the retransmissions -- just data arriving later than expected.
For this test to be meaningful, the proxy needs to be located away from the server and the client, and with no meaningful common infrastructure -- hence the suggestion of placing it in a different AWS region. A different availability zone in the same region may share common Internet infrastructure at some level, so that's not far enough away for this purpose.
If client <--> proxy <--> server shows TCP retransmissions on the path between proxy and server, and not between client and proxy, the problem really is likely to be in your server, its hardware, network, or Internet connection, and you'll have to proceed accordingly.
Conversely (and, I would suggest, more likely) if the path between proxy and server is free of retransmissions but the path between client and proxy is still dirty, you have eliminated the server and its infrastructure as the source of the problem. How to proceed is up to you, but at this point you do know what the problem... isn't.
Two other possibilities:
Both sides remain dirty, which is the least likely scenario. Rule 1 of troubleshooting is to assume initially that you only have one problem, not two.
Or, both sides are suddenly and unexectedly clean when traffic uses this setup, which suggests thay your test setup has routed around a broken piece of the Internet. You've "solved" it but have no idea how. We'll also hope this isn't the outcome, but given the vagaries of the global Internet, it's not unthinkable that your stack may include components like this, with geolocation-DNS-based selection of an intermediate endpoint. This seems like a convolution but does have its place.
Such a tactic is actually part of the logic behind the S3 transfer acceleration feature. The content is not any closer to the end user, but the TCP connection from the browser is being terminated on equipment in the AWS edge network, at a location that is often nearer to the browser, and a second TCP connection back to the bucket is established, with the payload connected together... and, yes, it's faster and more stable, with the significance of the change becoming more notable as distance and connection quality vary.
I have a large number of machines (thousands and more) that every X seconds would perform an HTTP request to a Jetty server to notify they are alive. For what value of X should I use persistent HTTP connections (which limits number of monitored machines to number of concurrent connections), and for what value of X the client should re-establish a TCP connection (which in theory would allow to monitor more machines with the same Jetty server).
How would the answer change for HTTPS connections? (Assuming CPU is not a constraint)
This question ignores scaling-out with multiple Jetty web servers on purpose.
Update: Basically the question can be reduced to the smallest recommended value of lowResourcesMaxIdleTime.
I would say that this is less of a jetty scaling issue and more of a network scaling issue, in which case 'it depends' on your network infrastructure. Only you really know how your network is laid out and what sort of latencies are involved in order to come up with a value of X.
From an overhead perspective the persistent HTTP connections will of course have some minor effect (well I say minor but depends on your network) and the HTTPS will again have a larger impact....but only from a volume of traffic perspective since you are assuming CPU is not a constraint.
So from a jetty perspective, it really doesn't need to be involved in the question, you seem to ultimately be asking for help optimizing bytes of traffic on the wire so really you are looking for the best protocol at this point. Since with HTTP you are having to mess with headers for each request you may be well served looking at something like spdy or websocket which will give you persistent connections but are optimized for low round trip network overhead. But...they seem sort of overkill for a heartbeat. :)
How about just make them request at different time? Assume first machine request, then you pick a time to response to that machine as the next time to heart beat of that machine (also keep the id/time at jetty server), the second machine request, you can pick another time to response to second machine.
In this way, you can make each machine perform heart beat request at different time so no concurrent issue.
You can also use a random time for the first heart beat if all machines might start up at the same time.
I've been reading around on the www but just can't get the most important basics of P2P.
The diagram is like this:
[peer1]<-->[dsl-router1]<-->[central server]<-->[dsl-router2]<-->[peer2]
I'm developing a chat software on the central server. Chat messages being transfered thru' the central server well by now, however, I need to make the p2p file sharing feature because the bandwidth (the cable bandwith, not the transfer limit) of the server supposed for transfering chat messages only.
The problem is that, my software on central server knows the IPs and ports of router1 and router2, but not the peer1 and peer2 as these peers are behind the routers and don't have IP addresses.
How to actually transfer some data from peer1 to peer2 and vice versa without having this data passing thru' central server?
(and the worst case is that there is a wireless router between peer and dsl-router)
There are two basic ways of doing this. The new way is to use IGDP (opening a port via uPnP). This is described quite well here:
http://www.codeproject.com/Articles/13285/Using-UPnP-for-Programmatic-Port-Forwardings-and-N
If neither of the two nodes have a router supporting uPnP then another alternative is TCP hole punching, which is not perfect but works quite well in practice. This is described here:
http://www.brynosaurus.com/pub/net/p2pnat/
During some situations, "routers" supplied by the ISP may run on bridge mode, which directly exposes the peer computer on the internet (the computer gets a public internet address). If at least one side has this configuration (or in a similar situation that the peer client is not behind another device), then things should be rather straight forward: simply assign the central server's job to whoever that have this privilege.
In the other case where both peers only have a local address (e.g. 192.168.0.2) assigned to their computers, it would then be rather difficult to get through the routers; clients behind routers are for the most part unreachable from the outside unless they originated the request. Then, one solution to the problem is port forwarding. By doing port forwarding, either through explicitly written rules or UPnP, some ports on the peer computer is exposed to the public internet, as in the first situation where instead of only some ports the entire computer is exposed.
If you are without either of these, then there is no simple way to avoid sending through the central server. Though you could, potentially, find other peers who have the capability to transfer for others.
I need to write a win32 c/c++ application which will be able to determine whether the PC it's running on is connected to one of 2 networks. The first network is the company LAN (which has no internet connection) and the second network is a standalone switch with a single PC connected to it (the PC that the program is running on).
I'm pretty new to network programming but so far I have tried testing to see if a network drive which is held on our LAN can be mapped. This works fine if the PC is connected to the LAN, the drive mapping succeeds so so LAN detection is successful. However, if the PC is connected to the switch, this results in a VERY long timeout which is not a suitable as it will delay the program so much as to make it unusable.
Does anyone have any alternative suggestions?
I'm using c/c++ in VS 6.0
[Update]
Whilst trying a few different ideas and looking at some of the suggestions below I thought I should update with some additional information as many (if not all) of the suggestions I don't think will work.
(1) The aforementioned LAN has no external connections at all, it is completely isolated so no resolving of external DNS or pinging websites is possible.
(2) Hostname, MAC address, IP, Default Gateway, Subnet etc etc (basically everything you see in ipconfig -all) are all manually configured (not dynamic from the router) so checking any of these settings will return the same whether connected to the LAN or the switch.
(3) Due to point (2), any attempts to communicate with the switch seem to be unsuccessful, in fact almost all networking commands (ping, arp etc) seem to fail - I think due to the machine trying to connect to the LAN when it isn't there :-(
One thing I have found which works is pinging the default gateway IP which times out when connected to the switch. This is sort of ok as I can reduce the timeout of ping so it doesn't just hang for ages but it feels like a bit of a hack and I would certainly appreciate any better solutions.
Thanks
As far as TCP/IP is concerned there is no such thing as a LAN on WAN. There are a set of non-internet routable addresses like 192.168.x.x and 10.x.x.x but these are sometimes used by ISP short of IP addresses.
You best bet is to use Asynchronous APIs when making TCP/IP connections. WIN32 defines a whole buch of OVERLAPPED APIs for this purpose. This will prevent your application from grinding to a halt while waiting for a remote connection.
Alternatively put the socket stuff into another thread and then only notify the UI when the operation is done.
I would first try to differentiate between the two using information available locally--that is, from your computer. Does the output of ipconfig /all differ depending on which network you're connected to? If so, exploit that difference if you can.
Is it possible to get the MAC address of the standalone switch? Of the switch that controls the company LAN? That would be a sure way to tell. Unless somebody cloned the MAC address.
If you try using the existence or non-existence of some network service to determine which network you're connected to, you can never be sure. For example, if you failed to map that network drive, all you know is that the network drive isn't available. You can't say for certain that you're not connected to the company LAN. Same is true if you use ping. Lack of response from a particular machine means only that the machine didn't respond.
Various things you can look at for differentiation:
DNS domain name (GetComputerNameEx)
MAC address of gateway (ping it, then GetIpNetTable)
Routing table(do you have a gateway and default route on the company LAN)
WNet discovered network resources (WNetOpenEnum, WNetEnumResource)
Ability to resolve external hostnames (try a 5-10 names like www.google.com, www.microsoft.com and so on, if one resolves you should have internet)
You'll have to decide how many indicators are "enough" to decide you're on one or the other LAN though if tests fail. Then keep retrying until you have a definite result.
http://msdn.microsoft.com/en-us/library/aa366071%28v=VS.85%29.aspx has a lot of network related functions that you can experiment with to create further indicators.
i'm reading about way to implemnt client-server in the most efficient manner, and i bumped into that link :
http://msdn.microsoft.com/en-us/library/ms740550(VS.85).aspx
saying :
"Concurrent connections should not exceed two, except in special purpose applications. Exceeding two concurrent connections results in wasted resources. A good rule is to have up to four short lived connections, or two persistent connections per destination "
i can't quite get what they mean by 2... and what do they mean by persistent?
let's say i have a server who listens to many clients , whom suppose to do some work with the server, how can i keep just 2 connections open ?
what's the best way to implement it anyway ? i read a little about completion port , but couldn't find a good examples of code, or at least a decent explanation.
thanks
Did you read the last sentence:
A good rule is to have up to four
short lived connections, or two
persistent connections per
destination.
Hard to say from the article, but by destination I think they mean client. This isn't a very good article.
A persistent connection is where a client connects to the server and then performs all its actions without ever dropping the connection. Even if the client has periods of time when it does not need the server, it maintains its connection to the server ready for when it might need it again.
A short lived connection would be one where the client connects, performs its action and then disconnects. If it needs more help from the server it would re-connect to the server and perform another single action.
As the server implementing the listening end of the connection, you can set options in the listening TCP/IP socket to limit the number of connections that will be held at the socket level and decide how many of those connections you wish to accept - this would allow you to accept 2 persistent connections or 4 short lived connections as required.
What they mean by, "persistent," is a connection that is opened, and then held open. It's pretty common problem to determine whether it's more expensive to tie up resources with an "always on" connection, or suffer the overhead of opening and closing a connection every time you need it.
It may be worth taking a step back, though.
If you have a server that has to listen for requests from a bunch of clients, you may have a perfect use case for a message-based architecture. If you use tightly-coupled connections like those made with TCP/IP, your clients and servers are going to have to know a lot about each other, and you're going to have to write a lot of low-level connection code.
Under a message-based architecture, your clients could place messages on a queue. The server could then monitor that queue. It could take messages off the queue, perform work, and place the responses back on the queue, where the clients could pick them up.
With such a design, the clients and servers wouldn't have to know anything about each other. As long as they could place properly-formed messages on the queue, and connect to the queue, they could be implemented in totally different languages, and run on different OS's.
Messaging-oriented-middleware like Apache ActiveMQ and Weblogic offer API's you could use from C++ to manage and use queues, and other messaging objects. ActiveMQ is open source, and Weblogic is sold by Oracle (who bought BEA). There are many other great messaging servers out there, so use these as examples, to get you started, if messaging sounds like it's worth exploring.
I think key words are "per destination". Single tcp connection tries to accelerate up to available bandwidth. So if you allow more connections to same destination, they have to share same bandwidth.
This means that each transfer will be slower than it could be and server has to allocate more resources for longer time - data structures for each connection.
Because establishing tcp connection is "time consuming", it makes sense to allow establish second connection in time when you are serving first one, so they are overlapping each other. for short connections setup time could be same as for serving the connection itself (see poor performance example), so more connections are needed for filling all bandwidth effectively.
(sorry I cannot post hyperlinks yet)
here msdn.microsoft.com/en-us/library/ms738559%28VS.85%29.aspx you can see, what is poor performance.
here msdn.microsoft.com/en-us/magazine/cc300760.aspx is some example of threaded server what performs reasonably well.
you can limit number of open connections by limiting number of accept() calls. you can limit number of connections from same source just by canceling connection when you find out, that you allready have more then two connections from this location (just count them).
For example SMTP works in similar way. When there are too many connections, it returns 4xx code and closes your connection.
Also see this question:
What is the best epoll/kqueue/select equvalient on Windows?