Using Cloudfront and AWS WAF with WordPress

So, for today’s post I decided to beef up my AWS cloud environment for my site I detailed in an earlier post how I turned my site from a one instance LAMP stack hosted site into a distributed, loosely coupled “Enterprise” class environment here

Well, some new services have come out since then and one of the coolest is the Web Application Firewall ( At first I thought I would just place it in front of my ELB but then I learned that you have to use it with Cloudfront, so it looked like my site was going to get beefed up in the form of having Cloudfront in front of my ELB, and an AWS WAF in front of the Cloudfront distribution blocking traffic I deem unnecessary (pretty awesome right?)?

Since my site is a wordpress site, it is often targeted by an annoying attack that occurs where attackers try to hit /xmlrpc.php on the server, ( I wanted my WAF to take care of this by blocking the traffic before it even gets to my ELB. To do this, I first created the WAF by going to the WAF console: and then clicking create web ACL. From here I named it ‘WordPressfilter’ then scrolled down to the ‘String match conditions’ and clicked create condition. Here I gave it a name ‘xmlrpc.php’, and then the interesting part was figuring how I wanted to block the traffic. I settled on using the URI, match type contains, transformation none, and value to match ‘/xmlrpc.php’.

From here I then had to create a rule, where after naming it, you select ‘does’, ‘match at least one of the filters in the string match condition’ and select the condition you created before, then I chose to block traffic with the rule, and below that Allow all requests that don’t match rules. From here you can click create, and now we have to create a Cloudfront distribution to use this with. Here are our docs on creating a WAF (, I also found this helpful (

After creating the WAF, I had to create a Cloudfront Distribution that would use my ELB as an origin.  Doing this was pretty easy, first you click on Cloudfront in the AWS console then click create distribution – web. From here in the “Origin Domain Name” section, click and select your ELB, it should auto load for you in the field. Then I found it necessary to click the third option under ‘Allowed HTTP Methods’ to allow both GET and POST. I also changed forward headers to ALL and YES for forward query string. I used the default for rest of answers.

Under ‘Distribution settings’ I found it necessary to select the AWS WAF Web ACL I just created, then add the CNAMES for my site (,, and and finally I turned on logging and fed it to an S3 bucket I own. Here is our docs on that (

After all this was done, all that was left was to wait for the Cloudfront distribution to spin up (like 15 minutes!!!) and then change my Route 53 settings. Namely, I had to delete the A records of and and that were pointing to my ELB, and instead create new Alias records where I point them to the new Cloudfront Distribution that was span up. This way, when someone now goes to my site, they first hit the WAF, then Cloudfront, then ELB, then autoscaled EC2 web instances, and finally this then talks to my RDS mysql db containing the data. I’ll have to sketch a post of this as it is useful to know how data flows through your environment.

Doing all of the above was great as it makes my site much, much more resilient against DDOS and other attacks as the first thing attackers now hit is Cloudfront, which is a global network of edge locations which can distribute traffic fast and efficiently to all over the world, and also I can cut them off at the knees with my WAF in the sense that I can add new rules on the fly to fight unwanted traffic from even hitting my back end architecture.

Here is a graph showing the WAF in action. This is really cool, because previously this malicious traffic was free to hit and try and disrupt my site, but now it does not even get past Cloudfront, saving load and strain on my back end servers.

Happy blocking! And to the people attacking other people’s sites for no good reason…

Leave a Reply

Your email address will not be published. Required fields are marked *