Integrate fail2ban with CloudFlare

Following my previous post about using fail2ban to stop malicious requests to xmlrpc.php, I set up a CloudFlare account. In doing so, I ran into two issues:

First, my access logs were only showing CloudFlare’s IP address, not those of the users making the requests. That’s due to how CloudFlare proxies every request. Fortunately, CloudFlare provides an Apache module to translate the IP addresses for your logs.

Second, even with the correct IP address in the logs, fail2ban was no longer effective in stopping requests (since it handled the requests before the Apache module translated the IP addresses). I needed to stop the requests at CloudFlare, before they ever made it to my server. Fortunately, it’s simple to set up a fail2ban action that utilizes the CloudFlare API to block those requests. Create an action including:

actionban = curl -s "https://www.cloudflare.com/api.html?a=ban&key=<ip>&u=<account>&tkn=<token>"
actionunban = curl -s "https://www.cloudflare.com/api.html?a=nul&key=<ip>&u=<account>&tkn=<token>"

And set your filter(s) to use that action.

Stop Hack Attempts on WordPress xmlrpc.php

I recently noticed a lot of requests to this and other WordPress sites’ xmlrpc.php file. By “a lot”, I mean about 10-20 every second. It wasn’t particularly breaking anything (there aren’t any currently vulnerabilities there that I’m aware of), but it was increasing the load on my server.

My first step was to set an .htaccess rule to give a 403 response. That at least avoided hitting PHP with all those requests. But Apache still had to process them, so I wanted to take it a step further. I’m already using fail2ban, so I wanted to figure out how to stop these requests at that level instead of waiting until they reach Apache.
Continue reading “Stop Hack Attempts on WordPress xmlrpc.php”

WordPress Form API

The short version: I made a Form API for WordPress. Use it in your plugin. Make better forms. Give back and help us all make better forms.

Introduction

If you’ve every written a WordPress plugin, chances are you’ve had to create a form, be it for a settings page, custom post/user meta, widget configuration, front-end user input, or a myriad of other possibilities. If you look at WordPress core or most plugins, you’ll see all of them using pretty much the same method for creating a form field, something very similar to:

 
sprintf( '<input type="text" value="%s" name="%s" />', $current_value, $field_name ');

There are a few special kinds of fields that have pre-existing functions, such as wp_dropdown_pages() or wp_dropdown_categories(). But generally speaking, we’re writing HTML in our PHP (maybe dressed up as a template include).

Lament

I want something better than that. I want a robust API that lets me create forms (or individual form elements), modify them, validate, and process user input. I want themes to have control over the display of forms. I want other plugins to be able to modify and extend my forms.

I tried a variety of existing libraries. Zend_Form from the Zend Framework has a lot to offer, in terms of a robust, object-oriented API. But it’s not very pluggable, and loading the entire Zend Framework just for the Form API is overkill.

I used to spend a lot of time in Drupal, and its Form API is somewhat pleasurable to work with. Forms are amazingly extensible and themeable. But I’m not thrilled with the array-based syntax, and porting it to WordPress would be inappropriate for a multitude of reasons.

Toward a Solution

In the grand hacker tradition, I was dissatisfied with the existing options, so I made my own. I’ve dubbed it WP Forms, and you can download/clone/fork it from its home on GitHub.

What does it do? It’s an API for forms in WordPress. You can use it to create simple form elements. You can use it to create entire forms. You can validate your forms. You can process the submitted information. You can change how elements are rendered. You can wrap elements in themeable markup.

There’s a lot of documentation. It should answer a lot of your questions. And those that I didn’t anticipate, I’d be delighted to answer.

Request for Feedback

WP Forms is surely incomplete. I’m personally not thrilled with the API around adding optgroups to select elements, but I’m not yet sure how to improve it. The API for decorating elements is probably a little complicated for beginning developers, so I’m open to suggestions for a better way to handle that (or at least provide a facade for most common operations). Beyond that, I just don’t know how people would want to use the API. I know how I would use it, but I’m not “people”, and I’m definitely not you; I’m just me.

I can think of several features to add: conditional fields/content, ajax submissions, multipage forms, media uploads, more built-in field types/validators. What features would you want to see?

Request for Contributions

WP Forms will be much more powerful if we can get behind it as a community, extending it, improving it, using it, testing it, documenting it. Do you want an awesome form API in WordPress? I hope you’ll help me make one.

Stable Sorting in PHP with the Schwartzian Transform

You have an array:

$object0 = (object)array('priority' => 5);
$object1 = (object)array('priority' => 10);
$object2 = (object)array('priority' => 5);
$my_array = array(
  0 => $object0,
  1 => $object1,
  2 => $object2,
);

Now let’s say you want to sort that array. You would probably call uasort($my_array $callback) with a callback to sort by the objects’ priority property. And you might end up with:

$my_array == array(
  0 => $object0,
  2 => $object2,
  1 => $object1,
);

Or, you might end up with:

$my_array == array(
  2 => $object2,
  0 => $object0,
  1 => $object1,
);

Keep calling uasort($my_array, $callback), and you might even switch back and forth between the two. What if you want to maintain the order of $object0 and $object2, no matter how many times you sort the array? There’s no native PHP function to accomplish this, but it’s fairly easily done using the Schwartzian Transform.

The Schwartzian Transform is a three step process: decorate, sort, undecorate. We decorate each item in the array by wrapping it in a more-easily sorted container. We then sort those containers, then remove our wrapper, leaving us with our original elements, only sorted.

For our array above, we would transform each item in the array into an array with three items: the priority, the index, and the the object.

array_walk( $my_array, create_function( '&$v, $k' , '$v = array( $v->priority, $k, $v );'));

PHP’s built-in asort() sorts this first by priority (array index 0), and if priorities are the same, then items by index (array index 1). Since every index is distinct, the sorting will never fall back to the third item in the array.

asort($my_array);

Finally, put all the items in the array back where we found them:

array_walk( $my_array, create_function( '&$v, $k', '$v = $v[2];'));

The Schwartzian Transform has the benefits of being both stable (multiple calls will produce the same result) and efficient (you only have to calculate the “priority” of each item once; helpful if it’s a more expensive operation).

WordPress Action Nesting: a cautionary tale

When you save a post in WordPress, the post’s data goes through wp_insert_post(), which in turn triggers the save_post action. So let’s say you have a callback hooking into save_post.

function my_first_callback( $post_id, $post ) {
  // do something...
}
add_action('save_post', 'my_first_callback', 10, 2);

So far, pretty simple. Now let’s put something in our callback function.

function my_first_callback( $post_id, $post ) {
  if ( $post->post_type == 'post' ) {
    wp_insert_post(array(
      'post_title' => 'A Post',
      'post_status' => 'publish',
      'post_type' => 'a_custom_post_type',
    ));
  }
}
add_action('save_post', 'my_first_callback', 10, 2);

Not a horribly complicated function. We’ll leave aside my reasons for creating a post in this callback (there’s a myriad of reasons why one might want to create or update a different post when a given post is saved) and focus on the consequences.

wp_insert_post(), called from my_first_callback() will once again trigger the save_post action, while we’re still in the middle of processing the first save_post action. So long as you avoid an infinite loop, there’s nothing necessarily wrong with that. But look closely inside do_action(), and you’ll find something else to worry about. Continue reading “WordPress Action Nesting: a cautionary tale”