Problem/Motivation

We run Varnish in front of Drupal, and have Drupal configured (via the reverse_proxy_addresses array in settings.php) to record the actual user IP address, so that we can gain the benefit of Drupal's IP-based flood and block features.

Due to bad behavior, I manually added some IPs to the "blocked_ips" list in Drupal. Later, I was pinged for a site outage and found that every one of my site visitors was seeing the ban message for a single IP. I guessed that perhaps a banned IP had been the first to request the homepage after the Varnish cache hit the timeout. Thus, Varnish stored the ban message for the homepage URL and served it to everyone.

I confirmed my guess by visiting interior pages (typing the URLs from memory), which all loaded properly. The problem was only on the homepage--and manually purging the Varnish cache resolved that.

Proposed resolution

The IP ban message is served by the function drupal_block_denied in bootstrap.inc. I propose that this function should mark the page uncacheable when serving the ban message. That way reverse proxies will not accidentally store and widely serve the ban message.

I don't see a way to solve with Varnish VCL, because the ban message could appear at any URL on the site. It's just a matter of bad timing by a banned IP.

Comments

jsneeringer created an issue. See original summary.

cilefen’s picture

But isn't the opposite true? Varnish will cache pages accessed by non-banned IPs then serve them to banned IPs because subsequent requests never "hit" drupal_block_denied().

I am not sure what you are proposing is possible.

See the releated issues and this Acquia doc about the complications of IP restrictions when using forward proxies.

cilefen’s picture

Issue tags: +SprintWeekend2017

I keep forgetting the weekend tag...

jsneeringer’s picture

"But isn't the opposite true? Varnish will cache pages accessed by non-banned IPs then serve them to banned IPs because subsequent requests never "hit" drupal_block_denied()."

Yes, but passive site browsing is not a security concern. The value of IP blocking at the application level is that POST operations like user registration and login are not permitted. This how the flood systems protects Drupal from brute force attempts.

But serving the "banned IP" message to non-banned users (what happened to my site) is effectively a site outage, because visitors cannot access site content.

The fix should be simple: drupal_block_denied just needs to set a no-cache header. I just haven't had time to roll and submit a patch yet. Maybe tonight.