journal features
movie reviews
photo of the day

using a cache server to secure WordPress

the journal of Michael Werneburg

twenty-seven years and one million words

Toronto, 2015.09.25

Securing a website that runs on WordPress can be a challenge. I don't believe the platform itself is necessarily insecure, but anyone who's ever observed logs of parties in remote jurisdictions sniffing around a WordPress website looking for known vulnerabilities has a right to be nervous.

With great power comes great complexity...

WordPress is an application that allows content management, and performs complex rendering based on numerous calls to various PHP modules; frequently many of these modules are plugins provided by third parties. A quick search around the Internet shows that there's been a long history of plugins leading to WordPress websites being compromised for various purposes.

...and a dash of DDoS

The substantial overhead introduced by complex sites running complex content management and content-rendering systems such as WordPress makes them good targets for distributed denial of service (DDoS) attacks as well. It's simply not that hard to drown such high-complexity systems in enough requests to tie up enough resources to render the website unreachable. There are many websites devoted to the various settings, plugins, and best practices that one must follow to secure the actual WordPress site. These are must-reads.

But if you're running a website that doesn't require constant interaction with visitors, there is an old alternative technology that provides dramatically improved security while simultaneously retaining all of the content management and rendering capabilities of WordPress. As a side benefit, websites so configured can be much, much faster than bare WordPress sites.

The not so big idea

The trick is to build a cache server. In the version I've deployed, the WordPress site is wrapped in a lightweight nginx server.

Securing a WordPress website with an nginx wrapper.Securing a WordPress website with an nginx wrapper.

Three servers

Technically, there are three web servers in this configuration. The core WordPress server runs on Apache as usual, but only "listens" to an IP address internal to the server.

The administrative interface at port 8080, while on the public IP address, is configured to only service requests from authenticated locations – usually a small number of IP addresses associated with the organization. This nginx server forwards all requests to the WordPress server on the internal address.

The public web site is served by nginx on port 80. It does not connect to the WordPress server at all, but simply returns cached copies of the web pages from files on the disk. This is accomplished through a caching job scheduled under 'cron', which reads from WordPress to create those files.

A walk through the database

The caching system walks through the WordPress website, mimicking web requests and writing the rendered pages to files on the drive volume. These files reside in the "document root" of the nginx server, which responds to requests for content with that flat content from the drive.

This walk through WordPress is possible because the job first connects to the WordPress database and gets the list of ID's for pages and posts that are currently active. A system utility is employed to retrieve each page from WordPress by requesting each page in turn by its ID. The last step is to ensure that all referenced assets such as Javascript and cascading style sheet files, images, sitemap files, and documents are likewise written to the drive.

Fast, scalable, and immune

The resulting nginx-driven website is both immune to probes for WordPress vulnerabilities, and fast enough to be harder to take offline with modest DDoS attacks. In fact, because it takes so little work to produce the requested web pages, it's much lighter on the server and can therefor deal with a higher volume of traffic. And in that regard I believe it's worth looking at as a partial solution for large, dynamic websites that can partially offload content delivery to such an engine. This is by no means a new idea – I was involved in such as a scheme for delivering the official website of the Sydney Olympics back in the stone ages of the Internet in 2000. But for security purposes I think this old idea is worth while in the current age.

rand()m quote

Success has a thousand fathers, failure is an orphan.

—-Old proverb