cft

Using CloudFront to secure your web applications

Cyberattack is more common than you think


user

Richard Fan

3 years ago | 7 min read

Cybersecurity is a hot topic now. If you search on Google about how to protect your website, you may find many buzzwords, IDS, IPS, WAF, DDoS, Proxy, you name it. You may think protecting your website is difficult and expensive and it is worthless to invest in security if your website is not critical.

Cyberattack is more common than you think

A human hacker may not bother sneaking into your website and change the headline of your homepage. But in most cases, your website would be hacked by a bot which constantly guessing your login password.

They can even inject code redirecting your customers to some malicious websites. The frequency of these hacks and the impact on your business are much higher than you think.

Using Amazon CloudFront to protect your website

Amazon CloudFront is a CDN service which allows us to delivers web content through the AWS network. By doing so, we can lower the traffic to the server as CloudFront will cache the content. We can also hide the webserver and prevent it from direct attack.

We don’t have to place the server in AWS to use CloudFront. In this article, I am going to walk you through on how to set up CloudFront as a reverse proxy to your existing website.

Using CloudFront to serve your website, integrated with SSL certificate and Application Firewall
Using CloudFront to serve your website, integrated with SSL certificate and Application Firewall

In my architecture, I made several changes to force web traffic go through CloudFront:

  1. Create a new DNS record (Origin sub-domain) pointing to my server IP
  2. Create a CloudFront distribution pointing to the origin sub-domain
  3. Change the existing DNS record (Public sub-domain) to the CloudFront distribution
  4. Block all traffic through the origin sub-domain or the server IP, except those from CloudFront

By using CloudFront, we can enable many security features:

  1. CloudFront protects the website from DDoS attacks.
  2. AWS Certificate Manager provision SSL certificate for HTTPS connections.
  3. AWS WAF block traffic from malicious IP or common OWASP attacks.
  4. S3 can store the access log, allow us to analyse web traffic or root-cause incidents.

Most of the setup is so common that there are many tutorials we can find elsewhere. My focus will be on how to do the DNS routing.

Traffic routing

DNS record sets

Because CloudFront doesn’t allow IP address as origin, we have to create a new DNS record to direct CloudFront traffic towards the IP address of the server. It can be anything we want, even in a different domain name, but it should be different from the one that normal visitors use (I use origin.example.com in this example).

We then use the origin sub-domain to create a CloudFront distribution. After it has been created, we can see the domain name for that distribution xxxxxxxxxxxxxx.cloudfront.net.

Now, we can change the target of the existing public sub-domain to the CloudFront domain name.

Because the CloudFront endpoint is not an IP address, we should use a CNAME record. If you want to use root domain, you may consider moving your nameserver to those support CNAME flattening (e.g. Cloudflare). We may also use Route53 as nameserver and use its alias feature to point the root domain to CloudFront.

CNAME flattening allows pointing root domain to another domain name
CNAME flattening allows pointing root domain to another domain name
Route53 alias feature allows pointing root domain to other AWS services
Route53 alias feature allows pointing root domain to other AWS services

Avoid redirect loop

Now, our web server is receiving traffic through the origin sub-domain. If the web app is host-sensitive, it won’t work. The most common case would be redirections.

If the web app detects hostname of incoming traffic and redirects users to the correct one (e.g. redirecting origin.example.com to www.example.com), the redirection will never end (server receives traffic from origin.example.com> user redirected to www.example.com> CloudFront relay traffic to origin.example.com > back to the beginning)

To avoid these situations, we need to pass the Host header to the server. We can do this by adding Host into header whitelist of the CloudFront distribution.

Another common situation is that your web app redirects HTTP traffic to HTTPS. Because CloudFront can change the protocol between viewer and origin, it may end up in a redirect loop like the previous case.

To tackle this issue, we have 2 choices:

1. Provision HTTPS on the webserver

If you have a 3rd party signed SSL certificate for the origin sub-domain, you can provision it on the server and accept HTTPS traffic from CloudFront. We also need to choose Match Viewer for Origin Protocol Policy option in the CloudFront distribution.

Choose Match Viewer to preserve visitors’ protocol
Choose Match Viewer to preserve visitors’ protocol

2. Disable HTTP to HTTPS redirection

If you don’t have an SSL certificate or if you cannot set up HTTPS on the server, we should choose HTTP Only for Origin Protocol Policy, so that CloudFront will only send traffic to the server using HTTP.

The next step is to disable the HTTPS redirection feature of the web app. This can be difficult as different apps have different approaches.

For WordPress (Yes, many insecure websites on the Internet is using WordPress), we can add the following at the beginning of wp-config.php

$_SERVER['HTTPS']='on';

This code fake WordPress to think that the incoming traffic is using HTTPS, and thus won’t trigger the redirection.

If you are using Apache Server, your web app may do the HTTPS redirection through rewrite rule. The most common methods are usingRewriteCondto detect if the incoming traffic is using HTTPS or using port 443. Find for the following keywords and disable the rewrite rules:

RewriteCond %{SERVER_PORT} 80
RewriteCond %{HTTPS} !=on

If we use this method, the server cannot distinguish whether the user is using HTTP or HTTPS. I would suggest choosing Redirect HTTP to HTTPS for Viewer Protocol Policy in the CloudFront distribution setting. So that we can assume every request from our user is using HTTPS.

Choose Redirect HTTP to HTTPS to ensure visitors are using HTTPS
Choose Redirect HTTP to HTTPS to ensure visitors are using HTTPS

Although using HTTP between CloudFront and the webserver is not secure, it is less likely the hackers can intercept these traffic compare to the traffic between users and the webserver.

Blocking direct access

Now, we have secured the CloudFront endpoint. But hackers can easily circumvent by directly accessing the origin sub-domain or even the server’s IP address. We need to block those traffic but allow traffic from CloudFront only.

IP Whitelist

CloudFront uses a set of IP to send traffic to origins, Amazon publishes those IP ranges in this file: https://ip-ranges.amazonaws.com/ip-ranges.json.

The list contains many different services, but we are interested in CloudFront only. The following bash script helps us filter them out:

curl https://ip-ranges.amazonaws.com/ip-ranges.json 2>/dev/null | jq -r '.prefixes[] | select(.service == "CLOUDFRONT") | .ip_prefix'

We will get a list like this:

144.220.0.0/16
52.124.128.0/17
54.230.0.0/16
54.239.128.0/18
52.82.128.0/19
99.84.0.0/16
.....

The next step is to deny all traffic except those IP prefixes. For Apache Server, we can do this by adding the following block in the site config

<Directory "<webroot_path>">
Order Deny,Allow
Deny from all
Allow from 144.220.0.0/16
Allow from 52.124.128.0/17
Allow from 54.230.0.0/16
Allow from 54.239.128.0/18
Allow from 52.82.128.0/19
Allow from 99.84.0.0/16
...
</Directory>

We need to add the ServerName directive in the existing VirtualHost and add a fallback VirtualHost pointing to an empty page

<VirtualHost *:80>
DocumentRoot "<empty_webroot_path>"
</VirtualHost><VirtualHost *:80>
ServerName www.example.com
DocumentRoot "<real_webroot_path>"
</VirtualHost>

After the setup, our website can be accessed through CloudFront with the correct domain name (www.example.com) only.

If hackers want to access our website directly, they have to know the origin sub-domain or server IP, realising we allow CloudFront traffic only, then provision their CloudFront distribution, access that distribution and fake the Host HTTP header. Although it’s doable, we still significantly raise the bar to attack our website.

Cost

The services we use here are charged by usage, it is difficult to say how much exactly it cost, so just do an estimate

CloudFront

CloudFront charges per GB monthly usage. For endpoints in North America:
Traffic from CloudFront to the internet: $0.085/GB
Traffic from CloudFront to the webserver: $0.02/GB
Every 10,000 HTTP request: $0.0075
Every 10,000 HTTPS request: $0.01

Assume we have a high traffic website with 10GB traffic and 100,000 HTTPS request per month, the cost of CloudFront would be: 10 X 0.085 + 10 X 0.02 + 10 X 0.01 = $1.15/month

The actual price would be lower as most of the static contents are cached in CloudFront, traffic to the webserver should be lower.

S3

In my architecture, we use S3 to store access logs. Although it is optional, I would still count it as logging is one of the best practices of security, I assume most of you will enable it.

CloudFront logs are normally delivered every hour. And depending on the traffic volume, it may be split into several files. Let’s assume there are 200 files per hour and the size of each one is 500 bytes.

Every hour, there would be 200 PUT request (No. of files to be stored), the request cost would be: $0.005 X 200/1000 = $0.001/hour, or $0.72/month

The total file size generated in a month would be 72MB, the cost for that would be: $0.023 X 72/1000 = $0.001656

Assume we keep the logs for 2 years, at the end of the second year, we will have 72MB X 24 = 1.8GB of files. The storage cost for that month would be: $0.023 X 1.8 = $0.0414

AWS WAF

Each Web ACL cost $5 per month, every 1 million requests cost $0.6. If we only use AWS provided ruleset, there will be no extra cost. Let’s assume our traffic doesn’t exceed 1 million per month, the cost would be: $5.6/month

Total cost

The total cost per month would be: $1.15 (CloudFront) + $0.72 (S3 request) + $0.0414 (S3 storage) + $5.6 (WAF) = $7.5114

It’s just $7.5114, we can have content caching, DDoS protection, web access log storage and web application firewall. The most expensive service is WAF, if we opt-out this, the cost can be even lowered to just $1.9114/month.

Conclusion

Many companies think securing their website is difficult and worthless. However, public cloud services make it easy and the cost is convenient.

Don’t set the goal too high at first. Don’t think that you are fighting with state-sponsored hackers, it will only scare you away from implementing cybersecurity.

By implementing simple cybersecurity measure like enforcing HTTPS, you have already outperformed almost 40% of websites on the Internet which uses HTTP as default.

If you spend more on coffee than on IT security, you will be hacked. What’s more, you deserve to be hacked.
— Richard Clarke

$1.9114 can’t even buy you a cup of coffee in Starbucks. I find no reason not to take action to secure your website.

Upvote


user
Created by

Richard Fan

AWS DeepRacer League Finalist | AWS Community Builder | Cloud Engineer


people
Post

Upvote

Downvote

Comment

Bookmark

Share


Related Articles