How to get client IP behind an AWS ELB? - amazon-web-services

With a webserver (apache or nginx) I am able to find the x-forwarded-for header and find the client IP rather than the ELB's IP.
Can I do the same thing using IPTables so that I am able to block certain IP addresses?
I can do this at the webserver level. However, I think this is a bit inefficient and I am hoping I can achieve this with IP Tables or something similar?

Since July 30th ELB supports Proxy Protocol. As stated in the end of this thread in the AWS forum:
Elastic Load Balancing (ELB) now supports Proxy Protocol version 1.
This feature allows you to identify the client’s connection
information when using TCP load balancing, providing additional
insight into visitors to your applications. Having this information
can be useful for analyzing traffic logs, gathering connection
statistics, troubleshooting, or managing whitelists of IP addresses.
You must enable Proxy Protocol in the ELB.
The developers guide has more information about Proxy Protocol.

You can't do this with iptables, because iptables will only ever see the IP address of the elastic load balancer, since the ELB is what is establishing the connections to your instance.
Using the web server to block certain x-forwarded-for values isn't particularly inefficient, but if you want to control who can access your ELB by IP address, that can also be accomplished with the Security Group attached to the ELB.
Update: Your comment is partially correct, because, at least as of now, ELB on EC2 "classic" does not support an inbound security group or network access control list, but ELB on VPC does.
Q: Can I configure a security group for the front-end of the Elastic Load Balancer?
If you are using Amazon Virtual Private Cloud, you can configure security groups for the front-end of your Elastic Load Balancer. — http://aws.amazon.com/ec2/faqs/#ELB6
Security groups are easiest to use when you need to allow a relatively small set of specific IP address ranges. If you want to allow most but block a few, then a VPC Network Access Control List is the easier approach.

Related

How can I use AWS load balancer to check IP changes?

I have an instance running on premise and its IP address is changed regularly. My other services are running on AWS and they are using IP to connect to the premise's services. I have to update the IP address saved on AWS services whenever the IP is changed on premise network. I have a thought about using DNS but it is still a need to update A record.
I am looking for a way to do some auto-detect instead of manual updating. I wonder whether I can use load balancer to do the check. I know there will be a range of IP addresses on premise network. Can load balancer do a health check on these IP within the range? So my AWS service can send request to the load balancer. Is there any side-effect on this approach?
You need to use hostname instead of IP address as you mentoned the IP addresses keeps changing. AWS VPC can use a DNS forwarder like Unbound, which can forward the requests to your on premise DNS server when VPC resolution is unable to resolve the hostnames. This appraoch is quite effective as you send only those DN resolution to on-premise DNS that are missed by AWS VPC DNS.
Unbound allows resolution of requests originating from AWS by
forwarding them to your on-premises environment—and vice versa. For
the purposes of this post, I will focus on a basic installation of
Amazon Linux with the configuration necessary to direct traffic to
on-premises environments or to the Amazon VPC–provided DNS, as
appropriate. Review the Unbound documentation for details and other
configuration options.
Further reading : How to setup DNS resolution from AWS to on premise servers

Testing classic internal ELB

I have configured and passed the health check for my AWS ELB(load balancer), but I was trying to do a ping or send a packet to the tcp port 9300 there is no ip address for the ELB.
I have an EC2 instance at the end of the ELB which has Elasticsearch running on it.
The ELB that I configured is an internal ELB so it doesn't have a public IP address for it.
I was wondering if there is a way I can ssh? or do something to ping the ELB?
I am pretty new to AWS and read all the trouble shooting from AWS official website, but couldn't find a solution.
The goal that I am trying to achieve is to test whether my internal Amazon EC2 load Balancer is working properly.
I got the internal ELB ip address with the ping command, however, I am not able to ping or crul to that IP address.
I what to know what I am doing wrong.
Is it the way that I want to access a private network is in correct?
An Elastic Load Balancer is presented as a single service, but actually consists of several Load Balancing servers spread across the subnets and Availability Zones you nominate.
When connecting to an Elastic Load Balancer, you should always use the DNS Name of the Elastic Load Balancer. This will then resolve into one of the several servers that are providing the load balancing service.
Load Balancers are designed to pass requests and return responses. The next time a user sends a request, it might be sent to a different back-end service. Thus, it is good for web-type traffic but not suitable for situations requiring a permanent connection, such as SSH. You can configure sticky sessions for HTTP connections that will use cookies to send the user to the same back-end server if required.
The classic Elastic Load Balancer also supports TCP protocol, but these requests are distributed in a round-robin fashion to the back-end servers so they are also not suitable for long-lasting sessions.
Bottom line: They are great for request/response traffic that needs to be distributed across multiple back-end servers. They are not suitable for SSH.
Site-note: Using PING to test services often isn't a good idea. Ping is turned off in Security Groups by default since it can expose services and isn't good from a security perspective. You should test connectivity by connecting via the expected protocols (eg HTTP requests) rather than using Ping. This applies to testing EC2 connectivity, too.

Assigning Static IP Address to AWS Load Balancer

How can I assign a static IP address to a ELB. Seems like I cannot.
Some articles online asks to create a Route 53 record but this requires changing CNAME of domain which also redirect email traffic. I just want to change A record not CNAME.
Some articles also mention that I can use a EC2 instance as a reverse proxy. But will a single proxy be able to handle a lot of traffic?
Any solution for this?
AWS' Elastic Load Balancer is actually elastic on two levels as described here:
http://shlomoswidler.com/2009/07/elastic-in-elastic-load-balancing-elb.html
The first level is the load balancer itself. In order to make sure that ELB can scale to whatever volume you have and burst to whatever volume you suddenly encounter, AWS assigns a 'static' DNS hostname (e.g. MyDomainELB-918273645.us-east-1.elb.amazonaws.com). That hostname points to multiple IP addresses. You can see that (from a command line) by running
$ host MyDomainELB-918273645.us-east-1.elb.amazonaws.com
MyDomainELB-918273645.us-east-1.elb.amazonaws.com 172.31.7.2
MyDomainELB-918273645.us-east-1.elb.amazonaws.com 172.31.11.33
The second form of elasticity within the ELB is obviously then ELB directing the query to one of your EC2 instances in the pool.
So, you can see that trying to assign a static IP address to the load balancer would be self-defeating.
Using an EC2 instance as a reverse proxy would also seem self-defeating as you would then create a bottleneck before even getting to the ELB. Might as well just create your own load balancer.
The recommended solution (which you've pointed out) is to create a CNAME that points to the ELB hostname (which won't change).
i.e. my-app.mycompany.com ->
MyDomainELB-918273645.us-east-1.elb.amazonaws.com
This would allow you to integrate your scalable application, behind the ELB within your domain.
I'm not sure I fully understand why you cannot create a CNAME in your DNS or what that has to do with directing email traffic, can you explain?
A new feature in AWS (I believe it was announced at Re:Invent 2017) allows for static IPs with Network Load Balancers (NLB). NLB can only handle layer 4 (TCP) and not HTTP specifics (layer 7).
You can assign one Elastic IP address per availability zone.
For details see the AWS blog post or the NLB documentation.
The "Classic Load Balancer" and "Application Load Balancer" do not support static IPs. If you need a feature only provided by those, you have to fall back to the CNAME solution described above.
A blog was recently published by AWS support on this topic leveraging NLB to provide static IP to Classic and Application load balancer - https://aws.amazon.com/blogs/networking-and-content-delivery/using-static-ip-addresses-for-application-load-balancers/
Summary of solution as described by the post
We end up with a TCP listener on a NLB that accepts traffic and forwards it to an internal ALB. The ALB terminates TLS, examines HTTP headers, and routes requests based on your configured rules to target groups with your instances, servers, or containers. The AWS Lambda function keeps everything in sync by watching the ALB for IP address changes and updating the NLB target group. In the end we’ll have a few static IP addresses that are easy for whitelisting, and we won’t lose any of the benefits of ALB. Note that we will be sending all of the traffic through two load balancers
I found setting up AWS Global Accelerator very straight forward and simple. It created 2 static IP Addresses and a static DNS pointing to my Application load balancer.
Configuring Global Accelerator
Set listeners as TCP port 80, 443
Select your load balancer endpoint (AWS Global Accelerator Configuration)
Add cname record for your dns pointing to the static dns it created
(mywebsite.com > globalacceleratorDNS.com). If any client needs to
whitelist, give them the 2 static IP it created
Pricing is $18 per month + a few pennies per GB of data transfer.
I'm pretty sure its cheaper than the NLB, Nat Gateway, Elastic IP setup.
https://docs.aws.amazon.com/global-accelerator/latest/dg/about-accelerators.html
For little traffic, it might be a solution to set up an EC2 Instance running Nginx as a forwarding proxy.
So you can use the EC2's static IP Address to forward your traffic resolving the ALB's DNS name.
However, it's a kind of a hack, but using a Global Accelerator or an NLB seems to me also like a hack :-)
Unlike the Network Load Balancer, the Application Load Balancer (ALB) does not support Elastic IPs, but that's not the worst part. If you use Route 53 together with the ALB, the DNS automatically sets the TTL to 60 seconds. This appears to be causing problems for our institutional - mainly government - customers running older Windows DNS servers. They just can't keep up with the ALB's Listener changing its public-facing IP on such a short notice. Older DNS infrastructure is either not respecting or is not capable of handling such aggressive TTL.
While I don't like it, AWS recommends to put a Network Load Balancer in front of the Application Load Balancer, per here: https://aws.amazon.com/blogs/networking-and-content-delivery/using-static-ip-addresses-for-application-load-balancers/

SMTP through HAProxy / Elastic Beanstalk

kind of an unusual setting here:
We have an SMTP service running on Tomcat / Elastic Beanstalk on AWS in an auto-scaling group behind an ELB load-balancer.
Now, for one of our clients we need to have a static IP for the SMTP service. Since this is not possible with the out-of-the-box load-balancer on AWS, we have a separate HAProxy instance transparently routing the :25 traffic trough the AWS load-balancer.
For some reason, the HAProxy chokes after exactly 3 SMTP calls. After that connections either time out or take minutes to go through.
The interesting part is that the following configurations work perfectly fine:
Calling the SMTP service on the AWS load-balancer directly
Load-balancing the Elastic Beanstalk's nodes through HAProxy directly.
Target setting with HTTP calls on port 80, instead SMTP on port 25
Help is really appreciated
That sounds like EC2 rate limiting what appears -- to the system -- to be "outbound" SMTP from your HAProxy instance.
You're accessing the ELB from the HAProxy by one of this outside addresses, and this is causing your traffic to be treated as Internet-bound.
In order to maintain the quality of Amazon EC2 addresses for sending email, we enforce default limits on the amount of email that can be sent from EC2 accounts. If you wish to send larger amounts of email from EC2, you can apply to have these limits removed from your account by filling out this form.
https://portal.aws.amazon.com/gp/aws/html-forms-controller/contactus/ec2-email-limit-rdns-request
One solution is to had those limits removed, but consider your next step carefully -- you'd be better served by load-balancing the EB nodes through the HAProxy directly, using the nodes' private IP addresses -- because there is a charge for traffic to your ELB from within EC2 on the public IP.
Data Transfer OUT From Amazon EC2 To ... Amazon Elastic Load Balancing ... in the same Availability Zone ... Using a public or Elastic IP address ... $0.01/GB.
http://aws.amazon.com/ec2/pricing/
Not a massive charge, perhaps, but it should be an avoidable charge nonetheless.
Additionally, there's no way to configure HAProxy to look up the IP address behind the hostname you've configured for the ELB with each request. HAProxy resolves hostnames on startup and if the ELB's IP address changes, HAProxy will not detect this change.
On the flip side, you can't reliability configure HAProxy to directly connect to the EB instances, since they're dynamically-addressed as well.
The simplest way to prove that my diagnosis is correct is to set the ELB's TCP listener on another port, such as 587 (or 2025, or whatever), mapped to port 25 on the EB instances. Then have the HAProxy target the traffic to port 587. That should eliminate the EC2 rate limiting on SMTP, although you do still have an issue to deal with if the ELB's external IP changes.

AWS Load Balancer with a static IP address

I have a set-up running on Amazon cloud with a couple of EC2 Instances running through a load balancer.
It is important that the site has a unique(static) IP or set of IPs as I'm plugging in 3rd party APIs which only accept requests made from IPs which have been added to their whitelist.
So basically unless we can give these 3rd parties a static IP or range of IPs that the requests from the site will always come from then we would be unable to make any calls to them.
Anyone knows how to achieve this as I know that Elastic IPs are not compatible with load balancers?
If I were to look up the IP of the load balancer DNS name (e.g. dualstack.awseb-BAMobile-ENV-xxxxxxxxx.eu-west-1.elb.amazonaws.com resolves to 200.200.200.200) would that IP be Static?
Any help/advise is greatly appreciated guys.
The ip addresses of your load balancer is not static. In any event, your incoming load balancer IP wouldn't be used for outgoing connections.
You could assign elastic IPs to the actual instances behind the load balancer, which would then be used for outgoing requests. You get 5 free elastic ips, and I believe you can apply for more if you need them.
Additionally if using a VPC and if your instances are in a private subnet then they will only be able to access the internet via the NAT instance(s) you setup, and you can of course assign an elastic IP to the NAT instances
This is an old question, but things have changed now.
Now you can create a Network ELB to get a LB with a static IP.
from https://docs.aws.amazon.com/elasticloadbalancing/latest/network/introduction.html
Support for static IP addresses for the load balancer. You can also
assign one Elastic IP address per subnet enabled for the load
balancer.
https://aws.amazon.com/blogs/aws/new-network-load-balancer-effortless-scaling-to-millions-of-requests-per-second/
You can attache an additional ENI (Elastic Network Interface) to an instance in your VPC. This way the ELB (Elastic Load Balancer) routes the incoming Internet requests to the web server, and the additional ENI will be used to connect to your 3rd party (or internal) requests (Management network)
You can see more details about it in the VPC documentations
Really the only way I am aware of doing this is by setting up your instances within a VPC and having dedicated NAT instances by which all outbound traffic is routed.
Here is a link to the AWS documentation on how to set up NAT instances:
http://docs.amazonwebservices.com/AmazonVPC/latest/UserGuide/VPC_NAT_Instance.html
You CAN attach an elastic IP to the instances BUT NOT to the ELB (which is what the client sees).
You could use a full reverse proxy layer 7 load balancer like HAProxy:
Or a commercial implementation like Loadbalancer.org or Riverbed (Zeus)
They both are in the AWS Marketplace:
Your outbound requests to your 3rd party APIs will NOT go out via the ELB/ALB. That's for incoming connections. If you need an inbound static IP you'll probably need to forego the loadbalancer (or figure out how to implement Anshu's suggestion to attach an elastic IP to the loadbalancers, the doc is light on details). Update: I found some documentation that ALB use static addresses (and I just tried binding an elastic IP to one to be sure and that failed).
If you're talking about outbound connections see below:
If your server is deployed in a public subnet you can attach an
elastic IP to that host. Outbound communications will go out over
that address.
If your server is deployed in a private subnet there's
a NAT gateway attached to it. All outbound traffic from your private
subnet will go out over that interface.
You could use as already mentioned loadbalancer.org appliance in AWS. It would replace the AWS NAT instance and give greater functionality and include both Layer4 and Layer7, along with SSL termination and a WAF.
Best of all you get free support in your 30 day trial in AWS to help you get up and running.
Yes I am biased as I work for loadbalancer.org however I would say nothing ventured nothing gained.
You can use a DNS service like DNSMadeeasy that allows "ANAME" records. These act like an A Record but can be pointed at a FQDN or IP. So in this case you can point it to the ELB DNS.
Dave