Securing WordPress on AWS Lightsail

Share on:

AWS Lightsail provides a really easy way to set up a WordPress instance. But, by default, the installation is not completely secure. So, in this post, I will show you how to secure your WordPress installation on AWS Lightsail.

To secure your WordPress site from most of the attacks, you need to do two main things:

  • Restrict access to port 22.
  • Block access to wp-admin or change the location of wp-admin

I will show you even more things that you can do to secure your site.

Prerequisites

For this guide, I am going to assume that you already have a WordPress instance running on AWS Lightsail and a domain is connected to it. Also, make sure that you have an account with Cloudflare. Also, assign a static IP for your own convinience.

Configuring Firewall for Allowing Ports

By default in Lightsail, the following ports are unblocked for the world to access:

  • 443
  • 80
  • 22

From the list, we don’t want port 22 to be accessed by anyone as many attacks are carried out via SSH. So, with the help of the Lightsail firewall, restrict access to port 22 only to your IP.

Securing WordPress

If you haven’t obtained your WordPress credentials for wp-admin, then SSH into the instance and use the following command:

cat bitnami_credentials

Next, we will configure SSL for our site. Before proceeding, make sure that the root domain AND the www CNAME points to the instance IP. Else, certificate issuance will fail.

After doing this, run the following command:

sudo /opt/bitnami/bncert-tool

A wizard will start asking for some information like email, domain name, www to non-www redirect, HTTP to HTTPS redirect, etc. The configuration will be saved at /opt/bitnami/apache2/conf/bitnami/bitnami.conf. Open bitnami.config from the location mentioned and make one small change.

 # BEGIN: Enable HTTP to HTTPS redirection
  RewriteEngine On
  RewriteCond %{HTTPS} !=on
  RewriteCond %{HTTP_HOST} !^localhost
  RewriteCond %{HTTP_HOST} !^[0-9]+.[0-9]+.[0-9]+.[0-9]+(:[0-9]+)?$
  RewriteCond %{REQUEST_URI} !^/\.well-known
  #RewriteRule ^/(.*) https://%{SERVER_NAME}/$1 [R,L]
  RewriteRule ^/(.*) https://example.com/$1 [R=301,L]
  # END: Enable HTTP to HTTPS redirection

I have commented out RewriteRule ^/(.*) https://%{SERVER_NAME}/$1 [R,L] and instead replaced it with RewriteRule ^/(.*) https://example.com/$1 [R=301,L]. This will make www to non-www redirect faster.

Next, we will define the WordPress installation domain in the wp-config file. Enter the following command in the terminal:

nano /opt/bitnami/apps/wordpress/htdocs/wp-config.php

Change the following lines:

define('WP_SITEURL', 'http://' . $_SERVER['HTTP_HOST'] . '/');
define('WP_HOME', 'http://' . $_SERVER['HTTP_HOST'] . '/');

to

define('WP_SITEURL', 'https://example.com');
define('WP_HOME', 'https://example.com');

After saving, restart Apache using the following command:

sudo /opt/bitnami/ctlscript.sh restart apache

At this point, SSL certificates are set up for our domain and SSH access is restricted to our own IP. Now, we will set up Cloudflare for protecting our wp-admin page and also to improve the performance.

Setting Up Cloudflare

The next part of the tutorial assumes that you have set up Cloudflare and the domain is added to your account and the nameservers are pointed to the Cloudflare nameservers.

Strict SSL Cloudflare

Open the SSL/TLS tab in Cloudflare and change the encryption mode from Flexible to Full (Strict).

If the SSL certificate was correctly issued for our site, your site will load fine over Cloudflare after making this change.

Also, make sure to disable the Always Use HTTPS feature. Else, the redirect will be inefficient if someone tries to visit the site via HTTP and non-www subdomain. The visitor will be redirected twice. So, to reduce this hop, its best to let Apache handle the redirects.

Setting Security Headers

With the default configuration, the following security headers are missing:

  • Content-Type-Options
  • Referrer-Policy
  • Feature-Policy
  • HTTP Strict-Transport-Security (HSTS)
  • Content-Security-Policy

To add the first 3 security headers, add the following code to the .htaccess file:

<IfModule mod_headers.c>
    Header set X-XSS-Protection "1; mode=block"
    Header set X-Content-Type-Options nosniff
        Header set Referrer-Policy "same-origin"
        Header set Feature-Policy "geolocation 'self'; vibrate 'none'"
        Header set Content-Security-Policy "default-src 'unsafe-inline' https: 'self' data:; upgrade-insecure-requests; frame-ancestors 'self';"
</IfModule>

As we are using a Bitnami image, the .htaccess file is disabled by default. To enable it, open /opt/bitnami/apps/wordpress/conf/httpd-app.conf and change:

AllowOverride None

to

AllowOverride All

After making the changes, restart Apache with the following command:

sudo /opt/bitnami/ctlscript.sh restart apache

We will enable HTTP Strict Transport Security (HSTS) with via Cloudflare. HSTS header is used to specify and enforce security policies in web browsers. You can find more information about it HERE.

HSTS Headers Cloudflare

We can check HSTS with the help of the following header in Chrome Dev Tools:

HSTS Header

For updating and setting up CSP (Content Security Policy), it varies from website to website. So, it’s best to configure it yourself. Here is a good site for information on CSP headers – https://htaccessbook.com/important-security-headers/#csp

Securing wp-admin With Cloudflare

We will be using the Cloudflare firewall rules to further secure our WordPress site. Use the following firewall rules below to achieve this.

1) Allow own IP to access wp-admin

Use the following code to allow only your IP to access wp-admin (replace 127.0.0.1 with your own IP):

(lower(http.request.uri.path) contains "/wp-admin" and ip.src in {127.0.0.1}) or (lower(http.request.uri.path) contains "/wp-login.php" and ip.src in {127.0.0.1})

2) Block all other IPs from accessing wp-admin

Now, we will block all the other IPs from accessing wp-admin, wp-login.php, admin-ajax.php, theme-editor.php, and xmlrpc.php using the following rule:

((http.request.uri.path contains "/xmlrpc.php") or (lower(http.request.uri.path) contains "/wp-login.php") or (lower(http.request.uri.path) contains "/wp-admin/" and not http.request.uri.path contains "/wp-admin/admin-ajax.php" and not http.request.uri.path contains " /wp-admin/theme-editor.php"))

3) Block bad bots

Now, we will block bad bots from accessing the site with the help of a feature called Bot Fight Mode.

Bot Fight Mode

4) Block access to the plugin directory

It is nearly impossible to test every plugin for vulnerabilities as there are thousands of them all around the internet. So, we will block external access to our plugins directory with the help of the following rule:

(http.request.uri.path contains "/wp-content/plugins/" and not http.referer contains "example.com" and not cf.client.bot)

Verdict

If you have done everything that was mentioned in this tutorial then congratulations! Your WordPress site is safer than ever before. In short, we did the following things:

  • Set up SSL
  • Set up Cloudflare
  • Set up security headers
  • Used Cloudflare for blocking attacks and bad bots

I hope that this tutorial has helped you to further secure your WordPress site. If you have any queries or suggestions, then please don’t hesitate to contact me.

Share on:

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

I am the founder of WPSteam. I am currently doing my B.Tech in Electronics & Telecommunication Engineering from KIIT University, Bhubaneshwar, India

Leave a Reply

%d bloggers like this: