I'm trying to implement a system using multiple servers which communicate with the clients via TCP. As there are going to be multiple backend servers to process clients' requests, I'm wondering if there exists a load balancing mechanism which after the load balancer receives a client request, it connects the client directly to a backend server so that they establish a two-way TCP connection and all future communication between the two is done directly between them and not through the load balancer.
In general terms, no, IP doesn't allow this, individual connections cannot be handed off to other machines. The protocol does not permit it. You can, in the case of high-availability, hand off all connections from one machine to another, but even that is kind of a hack and is done using MAC address shifting.
What you want is probably something like HAProxy which is a TCP/IP load balancer. It's fast enough that being in the middle isn't really a problem, you won't feel a performance hit.
The alternative is to do something in the application layer where your "load balancer" tells clients which server to connect to, but doesn't actually do the connecting. That's done by the client in a secondary request. Sometimes this is done via DNS, sometimes via time-limited tokens to ensure clients respect the routing.
Related
I couldn't find anything in the documentation but still writing to make sure I did not miss it. I want all connections from different clients with the same value for a certain request parameter to end up on the same upstream host. With ELB sticky session, you can have the same client connect to the same host but no guarantees across different clients.
This is possible with Envoy proxy, see: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/load_balancers#ring-hash
We already use ELB so if the above is possible with ELB then we can avoid introducing another layer in between with envoy.
UPDATE:
Use-case - in a multi-tenant cloud solution, we want all clients from a given customer account to connect to the same upstream host.
Unfortunately this is not possible to be performed in an ALB.
An application load balancer controls all the logic over which host receives the traffic with features such as ELB sticky sessions and pattern based routing.
If there is no work around then you could look at a Classic Loadbalancer which has support for the application setting the sticky session cookie name and value.
From best practice ideally your application should be stateless, is it possible to look at rearchitecting your app instead of trying work around. Some suggestions I would have are:
Using DynamoDB to store any session based data, moving from a disk based session (if that's what your application does).
Any disk based files that need to persist could be shared between all hosts either using EFS for your Linux based hosts, or FSX on Windows.
Medium/Long term persisting files could be migrated to S3, any assets that rarely change could be stored here and then your application could use S3 rather than disk.
It's important to remember that as I stated above, you should keep your application as stateless as you can. Assume that your EC2 instances could fail, by preparing for this it will make it easier to recover.
I'm trying to get TCP timestamp from the packets for clock skewing purposes on my application which is hosted on EC2. In my network I have an ALB.
So my question is how do I get TCP level packet information in my app ? Since ALB filters out all the OSI Layers except application level (HTTP)
If the only reason to get access to TCP packet is to detect timestamp and correct clock drift, I would suggest to configure your EC2 instance to use NTP time server instead.
https://aws.amazon.com/blogs/aws/keeping-time-with-amazon-time-sync-service/
That being said, the ALB is not "removing" TCP information from network packets. HTTP connections made to your application are still transported over IP and TCP. If you need low level access to network packets from an app, I would suggest to look at the pCAP library which is used by TCPDUMP and many other tool to capture network traffic on an interface.
https://www.tcpdump.org/
[UPDATED to include comments]
It is important to understand the TCP connection between your client and the ALB is terminated at the ALB level. The ALB creates a second TCP connection to forward HTTP requests to your EC2 instance. The ALB does not remove information from TCP/IP, it just creates a second, independent and new connection. Usually the only information you want to propagate from the initial TCP connection is the source IP address. The ALB, like most load balancers and proxies, captures this information from the original connection (the one received from the client) and embed the information in an HTTP header called X-Forwarded-For.
This is documented at https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html
If you want to capture other information from the original connection, I am afraid it will not be possible using ALB. (but I also would be very curious about the use case, i.e. WHAT you're trying to achieve)
Good Day,
I have been using AWS quite a bit for my cloud based system for a hardware project. Using SimpleDB and the notification service provided is great.
However, I need a backend on AWS that basically listens to requests coming in, processes it and sends it back to a particular address. Some kind of UDP service.
I could easily write a c#/c++ app for it, but i am not sure if I can host it on AWS. Does anyone know how this works?
Short answer: yes.
EC2 instances are just like any other virtual machine, obviously you can put in a server that listens to UDP. Configuring the network for this is, of course, slightly more complicated, but possible. The one thing making it more complicated is that with UDP you will not be able to enjoy the load balancer service that Amazon offers, as it (currently) only supports TCP-based protocols.
So, if you have one server you wish to put on the internet, the procedure is probably same as what you'd do with a TCP server: set up a server and an elastic IP pointing to it, and then have your clients connect to it (by knowing the elastic IP you've been allocated, or by referring to that IP via a DNS resolution). If you have multiple servers you wish to set up, answering the same address, life is a bit more complicated. With TCP, you could have set up an Amazon load balancer and assign your elastic IP to the load balancer. If you'd want a load balancer for UDP, the Amazon stock load balancer can't do that, but you can still find a software load balancer (there are hundreds of them on Amazon's public images library) to set up.
Nginix has an Amazon image that will load balance UDP for $2,500/yr or you can launch your own EC2 instance and use open source Nginx.
My specific use case was for a UDP logging service, if you can use hostnames Route 53 could be a scalable managed solution as well.
I am trying to turn the server/client model into a server/server model, so as to have the my 2 computers running the program find each other by perhaps a url or something else like ip address.I was wondering if it was possible for 2 servers to connect via url's. or is ip the only way? examples would be appreciated since this is my second day writing c++.
For HTTP, the server only talks to clients. So, I am not sure what you mean by server to server.
URLs are fine to use to access an HTTP server, but the host name will need to be resolved into an IP address before a network connection can actually be established. You should be able to find libraries that will do those details for you, but it is not hard to manually establish a socket connection to an HTTP server.
There are configurations where there are multiple servers, acting as a single server. These are sometimes referred to as web farms or a HTTP cluster. Typically, there is some sort of load balancer in front of the cluster. Many HTTP load balancers support a server affinity feature to make sure a client is sent to the same server in the cluster for subsequent operations.
In a cluster configuration, servers may need to synchronize shared state, such as file system data or configuration data. This is typically handled by some mechanism that is external to the HTTP server process itself. The HTTP server process may need to cooperate with the synchronization, but this can be as simple as restarting the process.
There is another mode of HTTP server configuration called a reverse proxy configuration. A cluster of HTTP proxy servers sit in front of a single HTTP server. The proxy servers are thought to be cheap and expendable entities that off load work from the HTTP server itself, providing a scalable means to increase HTTP server capacity.
There are many open source HTTP server and proxy projects available as examples of how they are implemented. If you are trying to build your own custom server application, you can have a look at the HTTP examples in Boost asio.
I looking for add support to a VPN for my software,
I known PPTP and OpenVPN , the two makes a system-wide binding, installing a TAP driver so all applications route their traffic to then.
How could i implement a VPN support for just my application ? ThereĀ“s any library, example, hint or way to do it ?
My software is actually made in C++ /MFC. Using the standard CAsyncSocket.
Forwading incoming connections to your application is relatively easy:
stunnel allows you to forward traffic to specific ports through an an SSL tunnel. It requires that you run it on both ends, though.
Most decent SSH clients, such as OpenSSH or PuTTY also support port forwarding, with the added advantage that any remote SSH server can usually act as the other end of the tunnel without any modifications.
You can also use OpenVPN and other VPN solutions, but this requires specific forwarding rules to be added to the remote server.
Forwarding outgoing connections, though, is trickier without modifying your application. The proper way to do it is to implement the SOCKS protocol, preferrably SOCKS5. Alternatively, you can use an external application, such as FreeCap, to redirect any connections from your application.
After you do that, you can forward your connections to any SOCKS server. Most SSH clients, for example, allow you to use the SOCKS protocol to route outgoing connections through the remote server.
As a sidenote, OpenVPN servers do not necessarily become the default gateway for all your traffic. Some do push such a route table entry to the clients, but it can be changed. In my own OpenVPN setup I only use the VPN to access the private network and do not route everything through it.
If you can force your application to bind all outgoing sockets to one or more specific ports, you could use IP filtering rules on your system to route any connections from those ports through the VPN.
EDIT:
Tunneling UDP packets is somewhat more difficult. Typically you need a proxy process on both the remote server and the local client that will tunnel incoming and outgoing connections through a persistent TCP connection.
Your best bet would be a full SOCKS5 client implementation in your application, including the UDP-ASSOCIATE command for UDP packets. Then you will have to find a SOCKS5 proxy that supports tunnelling.
I have occasionally used Delegate which seems to be the Swiss pocket-knife of proxies. As far as I know, it supports the UDP-ASSOCIATE command in its SOCKS5 implementation and it also supports connecting two Delegate processes through a TCP connection. It is also available for both Linux and Windows. I don't remember if it can also encrypt that TCP connection, but you could always tunnel that one through stunnel or SSH if you need to.
If you have system administrator rights on a remote VPN server, however, you could probably have a simpler set-up:
Have your P2P application bind it's outgoing UDP sockets to the client VPN interface. You many need to setup a secondary default route for that interface. This way your application's outgoing packets will go through the remote server.
Have the remote server forward incoming UDP packets to specific ports through the VPN connection back to you.
This should be a simpler set-up, although if you really care about anonymity you might be interested in ensuring your P2P application does not leak DNS or other requests that can be tracked.
Put SSH connectivity in your app or use SSL. You'll have to use a protocol/service instead of VPN technology. Good luck!
I think you simply need SSL: http://www.openssl.org/
OpenVPN is based on SSL - but it is a full vpn.
The question is what do you need? If you need encryption (application private connection) - and not a vpn (virtual private network) go for ssl.
Hints can be found here:
Adding SSL support to existing TCP & UDP code?
http://sctp.fh-muenster.de/dtls-samples.html
http://fixunix.com/openssl/152877-ssl-udp-traffic.html