How does cloudfront work with Route53 routing policies?
So as I understand it CF is supposed to route requests to the nearest server, which is in effect the Route53 latency policy. So if you have an R53 hosted zone entry for your CF domain name is this done by default if you leave the routing policy as simple or do you neec to explicitly set this yourself? And if you chose another policy type (failover, geo-location etc) would that overwrite it?
You leave it as simple.
You don't have access to the necessary information to actually configure it yourself -- CloudFront returns an appropriate DNS response based on the location of the requester, from a single, simple DNS record. The functionality and configuration is managed transparently by the logic that powers the cloudfront.net domain, you set it and forget it, because there are no user-serviceable parts inside.
This is true whether you use an A-record Alias or a CNAME.
Any other configuration would not really make sense, because talking of failover or geolocation imply that you'd want to send traffic somewhere other than where CloudFront's algorithm would send it.
Now... there are cases when, behind CloudFront, you might want to use some of Route 53's snazzier options. Let's say you had app servers in multiple regions serving exactly the same content. Latency-based routing for the origin hostname (the one where CloudFront sends cache misses) would allow CloudFront to magically send requests to the app server closest to the CloudFront edge that serves each individual request. This would be unrelated to the routing from the browser to the edge, though.
Related
My S3(front-end codes), and EC2(back-end codes) are BOTH linked to 'example.com'
What I like to do here is to direct users to view the pages, stored in S3, unless they input 'example.com/api/'on their browser.
In other words, 'example.com/api/' for the server access, and the other routes for the react app access.
which service should I use in AWS? CloudFront, Route53, Load Balance. I am so confused. thank you.
TLDR; Create a single CloudFront distribution for your domain with separate cache behaviors for each of the paths you need to support. You can easily add additional applications, control caching, or write edge functions (using Lambda#Edge or CloudFront Functions) for any further customization you might need.
Details: CloudFront allows you to configure multiple origins (e.g. S3, EC2, API Gateway, ELB, custom URLs, and so forth) and then create cache behaviors (routes) that direct traffic to the appropriate origin.
In your case, you would create a cache behavior of /api/* to point to your EC2 origin, and the default cache behavior (think of this as your fallback route) would point to your S3 origin for all requests that do not begin with /api/
You can create a subdomain say api.example.com using Route53, here is a document for that https://aws.amazon.com/premiumsupport/knowledge-center/create-subdomain-route-53/
And for routing traffic for the newly created subdomain go through this document https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-routing-traffic-for-subdomains.html
I have a custom origin i.e. a web app on an EC2 instance. How do I decide whether I should go for:
a Cloudfront CDN
or,
deploy multiple instances in different regions and configure a Geolocation/proximity based routing policy
The confusion arises from the fact that both aim at routing the request to the nearest location (edge location in case of Cloudfront and region specific EC2 instance when it comes to multi-region deployments with Geolocation based policy with Route 53) based on where the request originates from.
There is no reason why you can't do both.
CloudFront automatically routes requests to an edge location nearest the viewer, and when a request can't be served from that location or the nearest regional cache, CloudFront does a DNS lookup for the origin domain name and fetches the content from the origin.
So far, I've only really stated the obvious. But up next is a subtle but important detail:
CloudFront does that origin server DNS lookup from a location that is near the viewer -- which means that if the origin domain name is a latency-based record set in Route 53, pointing to deployments in two or more EC2 regions, then the request CloudFront makes to "find" the origin will be routed to the origin deployment nearest the edge, which is also by definition going to be near to the viewer.
So a single, global CloudFront deployment can automatically and transparently select the best origin, using latency-based configuration for the backend's DNS configuration.
If the caching and transport optimizations provided by CloudFront do not give you the global performance you require, then you can deploy in multiple regions, behind CloudFront... being mindful, always, that a multi-region deployment is almost always a more complex environment, depending on the databases that are backing your application and how they are equipped to handle cross-region replication for reads and/or writes.
Including CloudFront as the front-end is also a better solution for fault tolerance among multiple regional deployments, because CloudFront correctly honors the DNS TTL on your origin server's DNS record, and if you have Route 53 health checks configured to take an unhealthy region out of the DNS response on the origin domain name, CloudFront will quickly stop sending further requests to it. Browsers are notoriously untrustworthy in this regard, sometimes caching a DNS answer until all tabs/windows are closed.
And if CloudFront is your front-end, you can offload portions of your logic to Lambda#Edge if desired.
You can use multi region for lot reasons mainly,
Proximity
Failover (incase if first region fails, requests can be sent to another region)
Multi region lambda deployment is clearly documented here. You can apply the same logic to all of the AWS Resources too. (DynamoDB, S3)
https://aws.amazon.com/blogs/compute/building-a-multi-region-serverless-application-with-amazon-api-gateway-and-aws-lambda/
You can also run Lambda#Edge to force all your requests / splits to one region on the edge.
Hope it helps.
So currently we have two ec2 instances (lets say A and B) and a cloudfront.
If the user goes to www.appdomain.com/app the user should get routed to the cloudfront SPA page. However if the user goes www.appdomain.com the user should be routed to the EC2 instance A, and if user goes to www.appdomain.com/api be routed to EC2 instance B.
All of these applications must be on the same domain.
Now we found out how to set path rules using an application load balancer, but would like to know how to set it to cloudfront as well.
Update:
So in summary the question is how do we route /app to cloudfront / and /api to ec2.
All of these applications must be on the same domain.
In this scenario, every request for that domain must pass through CloudFront first.
Your DNS record will need to point to CloudFront (not the ALB) and CloudFront is then responsible for routing the request to the appropriate target -- to an EC2 instance via an ALB, to an S3 bucket, to wherever you need the requests to go -- and each of these things is called a content origin.
Once the origins are specified by their individual domain name (not your site's domain name, but a domain name specifically for the resource in question), you define CloudFront path patterns to select which origin is to receive the request for each pattern (e.g. /api*).
Once your DNS is changed to point to CloudFront, all requests go there first, and are handed off to the next service, unless CloudFront has a cached copy of the requested object -- in which case, CloudFront will serve it from its cache, and nothing will be sent to the origin.
You can't route from ALB to CloudFront, but you can route from CloudFront to ALB.
You can't subdivide a domain into multiple, different path-based content origins without using a reverse proxy that is able to match the paths and fetch the content on behalf of the requester -- HTTP and DNS don't support such functionality. CloudFront, in addition to providing the CDN service, is also a reverse proxy.
ALB, of course, is also a reverse proxy, but does not support as many different types of content origins as CloudFront does -- ALB only supports EC2 instances, servers in your data center (in which case, ALB must have a VPN path in order to reach them), and Lambda functions as content origins. CloudFront can use literally anything as a content origin as long as it speaks HTTP/HTTPS and is accessible via the Internet. (To choose a somewhat random example, CloudFront can even use a service from another vendor -- like a Google Cloud Storage bucket -- as a content origin, if that was something you needed to do, for whatever reason... because these are accessible via HTTP across the public Internet.)
I need to use AWS WAF for my web application hosted on AWS to provide additional rule based security to it. I couldnt find any way to directly use WAF with ELB and WAF needs Cloudfront to add WEB ACL to block actions based on rules.
So, I added my Application ELB CNAME to cloudfront, only the domain name, WebACL with an IP block rule and HTTPS protocol was updated with cloudfront. Rest all has been left default. once both WAF and Cloudfront with ELB CNAME was added, i tried to access the CNAME ELB from one of the ip address that is in the block ip rule in WAF. I am still able to access my web application from that IP address. Also, I tried to check cloudwatch metrics for Web ACL created and I see its not even being hit.
First, is there any good way to achieve what I am doing and second, is there a specific way to add ELB CNAME on cloudfront.
Thanks and Regards,
Jay
Service update: The orignal, extended answer below was correct at the time it was written, but is now primarily applicable to Classic ELB, because -- as of 2016-12-07 -- Application Load Balancers (elbv2) can now be directly integrated with Web Application Firewall (Amazon WAF).
Starting [2016-12-07] AWS WAF (Web Application Firewall) is available on the Application Load Balancer (ALB). You can now use AWS WAF directly on Application Load Balancers (both internal and external) in a VPC, to protect your websites and web services. With this launch customers can now use AWS WAF on both Amazon CloudFront and Application Load Balancer.
https://aws.amazon.com/about-aws/whats-new/2016/12/AWS-WAF-now-available-on-Application-Load-Balancer/
It seems like you do need some clarification on how these pieces fit together.
So let's say your actual site that you want to secure is app.example.com.
It sounds as if you have a CNAME elb.example.com pointing to the assigned hostname of the ELB, which is something like example-123456789.us-west-2.elb.amazonaws.com. If you access either of these hostnames, you're connecting directly to the ELB -- regardless of what's configured in CloudFront or WAF. These machines are still accessible over the Internet.
The trick here is to route the traffic to CloudFront, where it can be firewalled by WAF, which means a couple of additional things have to happen: first, this means an additional hostname is needed, so you configure app.example.com in DNS as a CNAME (or Alias, if you're using Route 53) pointing to the dxxxexample.cloudfront.net hostname assigned to your distribution.
You can also access your sitr using the assigned CloudFront hostname, directly, for testing. Accessing this endpoint from the blocked IP address should indeed result in the request being denied, now.
So, the CloudFront endpoint is where you need to send your traffic -- not directly to the ELB.
Doesn't that leave your ELB still exposed?
Yes, it does... so the next step is to plug that hole.
If you're using a custom origin, you can use custom headers to prevent users from bypassing CloudFront and requesting content directly from your origin.
http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/forward-custom-headers.html
The idea here is that you will establish a secret value known only to your servers and CloudFront. CloudFront will send this in the headers along with every request, and your servers will require that value to be present or else they will play dumb and throw an error -- such as 503 Service Unavailable or 403 Forbidden or even 404 Not Found.
So, you make up a header name, like X-My-CloudFront-Secret-String and a random string, like o+mJeNieamgKKS0Uu0A1Fqk7sOqa6Mlc3 and configure this as a Custom Origin Header in CloudFront. The values shown here are arbitrary examples -- this can be anything.
Then configure your application web server to deny any request where this header and the matching value are not present -- because this is how you know the request came from your specific CloudFront distribution. Anything else (other than ELB health checks, for which you need to make an exception) is not from your CloudFront distribution, and is therefore unauthorized by definition, so your server needs to deny it with an error, but without explaining too much in the error message.
This header and its expected value remains a secret because it will not be sent back to the browser by CloudFront -- it's only sent in the forward direction, in the requests that CloudFront sends to your ELB.
Note that you should get an SSL cert for your ELB (for the elb.example.com hostname) and configure CloudFront to forward all requests to your ELB using HTTPS. The likelihood of interception of traffic between CloudFront and ELB is low, but this is a protection you should consider implenting.
You can optionally also reduce (but not eliminate) most unauthorized access by blocking all requests that don't arrive from CloudFront by only allowing the CloudFront IP address ranges in the ELB security group -- the CloudFront address ranges are documented (search the JSON for blocks designated as CLOUDFRONT, and allow only these in the ELB security group) but note that if you do this, you still need to set up the custom origin header configuration, discussed above, because if you only block at the IP level, you're still technically allowing anybody's CloudFront distribution to access your ELB. Your CloudFront distribution shares IP addresses in a pool with other CloudFront distribution, so the fact that the request arrives from CloudFront is not a sufficient guarantee that it is from your CloudFront distribution. Note also that you need to sign up for change notifications so that if new address ranges are added to CloudFront, then you'll know to add them to your security group.
I am having cname(abc.com) pointed to my elastic IP and need to create three EC2 instances(e.g. Instance1, Instance2, Instance3) for three different applications.
Now I want to achieve following results:
If user hits "abc.com/App1", request should be redirected to Instance1.If user hits "abc.com/App2", request should be redirected to Instance2.If user hits "abc.com/App3", request should be redirected to Instance3.
All these Instances should work independently. And, If any of these goes down, it should not impact others.
We can't use subdomains. I am trying to find out something in ELB.
ELB does not offer path-based routing. All instances connected to an ELB receive a share of incoming requests.
CloudFront, however, does support path-based routing. You can configure each instance as a "custom origin" and configure which path patterns to route to it.
http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesPathPattern
Granted, this is not the "primary purpose" of CloudFront, but it works quite nicely in this application.
CloudFront is actually a caching reverse proxy CDN service, so if you go this route, you can also potentially relieve your back-end machines of some workload, or you can disable caching entirely by forwarding all the request headers to the origin and returning an appropriate Cache-Control: header from your instances.
A CloudFront distribution can be associated with a domain name in Route 53 in exactly the same way that an ELB can -- using Alias records.
Bonus: you can also easily pluck additional paths and route them directly to S3 to serve up static assets from an S3 bucket.