Category Archives: servers

Building a Customized PirateBox, Part 1: Build a PirateBox

I wanted to have something fun and portable that I could use to promote the software literacy effort I’m spinning up here, and I thought it would be great to make a PirateBox that I could “re-brand” and use to share files and a microsite about what I’m doing and why it’s important.

The PirateBox project has spawned a number of customized versions, like LibraryBox, BibleBox, and others. I’m calling the one I’ve put together “nanonet”, and you can see a version of the web site it runs here.

What You’ll Need

  • A TP-Link TL-MR3040
  • A small USB drive — you only need the room for the base PirateBox install, under twenty megabytes, plus whatever space you’ll need for the web site you want to serve plus any files you want to share.
  • A Debian 7 “Wheezy”-like system with an Ethernet port that you can dedicate to this for a little while

I did my build on Linux Mint 17, but this will probably work on any Linux command line.


A “vanilla” PirateBox offers a chat window, a forum board, and the ability to upload and download files, in addition to its single-page HTML site. For my application, I wasn’t really interested in having people upload to the device, I just wanted to make material available for people to download.

The only “administrative” access to the PirateBox is via the Ethernet port, so there aren’t really any security issues to worry about on a device like this.


The TL-MR3040 is, in today’s terms, a tiny device, although in the mid-to-late ’90s, it would have been more or less the equal of a reasonably powerful PC. Its biggest limitation is internal storage: it’s got 16MB of RAM, and only 4MB of flash memory to play around with.

That’s going to limit what we’ll be able to put on the device, and aside from what’s needed to make PirateBox itself run, we’re going to limit ourselves to an index page, the stuff needed to support it (e.g. minified jQuery, etc.) Every thing else can go onto the USB drive, in a “Shared” directory.

We’re going to take things in the following order:

  1. Reflash the TL-MR3040 with the PirateBox version of OpenWrt 12.09 “Attitude Adjustment”.
  2. Do the first-time OpenWrt set-up.
  3. Install PirateBox v1.0

That much is going to be a lengthy posting in and of itself. In part 2, we’ll

  1. Extract an image of the on-board PirateBox web site from the install — this is the only portion where I actually used Linux, everything else was done on OS X
  2. Throw away the index page, and replace it with one of our own
  3. Implement the rest of the web site in the shared directory on the USB drive
  4. Customize things like the SSID of the WiFi network, the favicon, etc., to reflect the new “branding”

Installing OpenWrt “Attitude Adjustment” (PirateBox Edition)

Check which version of the MR3040 you’ve got, there are two different firmware versions, and you can brick your device if you try to reflash it with the wrong one.

To do this, take off the back — you’ll need to do this to install the battery anyway — and look at the barcoded label stuck on the label underneath where the battery goes. This photo shows the label on a v2.2 device, as indicated. For this one, we’d want v2 firmware. Do not guess at this. Be sure to check.


For a version 2 device, you will want

For a version 1 device, you will want

In either case, get a copy of, and expand it. Put the resulting folder, called install, onto your FAT-formatted USB drive. Do not insert the USB drive into the MR3040 at this time.

Again, be sure you’ve gotten the correct bin file for your device!

Start by installing the battery and plugging the MR3040 into a powered USB port via its own mini-USB port to charge it up. Both of mine have arrived with flat batteries. This will take an hour or two.

Configure the Ethernet port on your system. The MR3040’s factory configuration uses the link-local IP address on its Ethernet port, so we want our system to have an address on the same network that won’t collide. is fine.

To set it up on OS X, choose “System Preferences” from the Apple menu, then double-click on “Network”.

In the Network control panel, select your Ethernet port in the sidebar and then choose “Using DHCP with manual address” from the pop-up menu. Enter “” in the box below the pop-up and click “Apply”.

System PreferencesScreenSnapz004

Connect the MR3040 to your computer’s Ethernet port — they include a short cable in the box — slide the 3-way switch on the side to “3G/4G”, and turn it on. It takes a little while to boot, but you can check to see when it’s up with the command


at a Terminal command line. When you start getting responses to the ping, open up a browser window and enter the URL

The browser will ask you for a user name and password. For a new TL-MR3040, these are admin and admin. This will get you to the Administration app for the TP-Link software.

Click on “System Tools” in the sidebar menu, then on “Firmware Upgrade” when the accordion menu opens. That will get you to this screen. Note that the factory firmware version for the device is shown here. In this case, it’s v1, more than likely, yours will be v2.

Be very sure that the version of the firmware that you’ve gotten from the PirateBox site is the same as the version shown here. You can brick your device if you mix them up, and you’re a lot better off bricking your device after you’ve successfully installed OpenWrt than you are before, for reasons we’ll discuss another time.


Click the “Select” (or “Parcourir”) button to the right, and choose the bin file you downloaded earlier.

A scroll bar will appear indicating the progress of the firmware update. DO NOT INTERRUPT POWER ON THE DEVICE WHILE THIS IS GOING ON. While you’re waiting, go back to your Ethernet preferences panel and change the address you’re using from to, since when a new device comes up on OpenWrt, it uses the default address

Bring up a terminal window, and start pinging that address with the command


When you start getting a response to your pings — and it can take a while, maybe ten or fifteen minutes — we can proceed to the next step. (If you’re not getting ping responses after twenty minutes, the most likely problem is that you haven’t reconfigured your own system’s Ethernet port correctly.)

First Login to OpenWrt

Initially, OpenWrt only allows telnet access, has a single user, root, who has no password set, so the very first thing we want to do is telnet in and set that password.


When prompted to log in, enter root and hit return. You should see this:


Once you see this screen, you’re talking to ash, the OpenWrt command shell. Change the root password:


You’ll be prompted to enter your new root password twice. Choose something you won’t forget! Assigning a password to root will “activate” OpenWrt, and once we’ve closed the telnet connection, we’ll only be able to access the system via SSH from that point on, so you’ll need to use the command

ssh root@

When you’re prompted, enter your password, and you should be back at the OpenWrt command prompt shown above.

We’re now ready to complete our PirateBox installation. Get out of the telnet (or ssh) connection by typing


and power off the MR3040.

Install PirateBox

Finally, we’re ready to install PirateBox v1.0 onto our newly-configured TL-MR3040. This part is easy.

With the power still off, insert your prepared USB drive — FAT-formatted, with the install folder you unpacked from the file you downloaded earlier — into the USB port of the MR3040.

Turn the power on. Go do something else for fifteen minutes or so.

What you’ll observe, if you watch it, it a lot of blinking and flashing, occasionally interrupted by short periods when only the power light is lit — that indicates that the MR3040 is rebooting, which is does three or four times before the installation is completed.

After about the third reboot, if you scan your local Wifi networks, you’ll see the network “Piratebox — Share Freely!” appear. You can connect to that network, but it may go away if the install hasn’t actually completed yet.

Once you’ve been able to get onto the Wifi network that the MR3040 is creating, open a new browser page, and navigate to any address you haven’t browsed recently — caching can confuse things — or just go to http://piratebox.lan, the name the Piratebox uses to refer to itself. You should see this.


Congratulations! You’ve just created a PirateBox, a tiny self-contained web server based on a tiny version of Linux.

Explore and have fun — you can upload and download files, put up messages on a forum, or leave brief notes on the home page. It turns out that, when you’re out with a crowd, a PirateBox can be an easier way to share around things like photos rather than having to email them.

In part two, we’ll dig a little deeper into the internals of PirateBox and show how you can put pretty much any sort of a web site onto one.

If you follow this tutorial, please let me know how things worked out for you in the comments. If you run into snags, I’ll do what I can to help out.

Set Up Your WordPress Site to Use Password-Free SFTP For Better Security

This turns out to be a pretty easy trick to do. In order to accomplish this, you will need:

  1. to be able to ssh (or, heaven forbid, telnet) into a command line on your server and operate as root or a “sudoer”;
  2. to be able to edit the wp-config.php file for your WordPress installation;
  3. to be able to stop and restart your web server.

Assumptions: You’re running CentOS or something like it. If you’re running Debian, or something like it, you’ll need to use apt-get instead of yum, and your directory layout will be different.

Enabling SSH for PHP

We’re going to set up WordPress to enable uploads via SFTP; for that, we’ll first need to build and install the ssh2 extension to PHP. At your server’s command line, execute the following to load all of the infrastructure you’ll need:

$ yum install php-devel php-pear gcc gcc-c++ make automake autoconf pcre-devel re2c libssh2 libssh2-devel

Next, have pecl install the ssh2 extension.

$ pecl install ssh2-0.12

Turn on ssh2 by creating an ini file for PHP:

$ echo "extension =" > /etc/php.d/ssh2.ini

Restart your web server:

$ service httpd restart

At this point, the SSH2 PHP extension should be installed and activated; you can use

$ php -i | grep ssh2

to verify this.

Setting Up WordPress for SFTP

First thing to do is to generate a key pair. YOU MUST BE LOGGED IN AS THE USER WHO WOULD BE DOING THE UPLOADING TO WORDPRESS. At the command line, execute

$ keygen-ssh

When prompted to enter a file name, we’ll call the key pair “~/wp_rsa”, so as not to accidentally overwrite any other keys we have around. Once your key pair has been generated, execute the following commands in that user’s home directory:

$ cat >> .ssh/authorized_keys
$ mv wp_rsa* .ssh/

For reasons that aren’t immediately clear to me, WordPress required both the public and private key to be available to it. Set the access protections appropriately:

$ chmod 755 .ssh/
$ chmod 644 .ssh/*

Next, edit wp-config.php, and add the following lines to the end, making the appropriate substitutions for your own site «where indicated»:

define('FTP_HOST', 'localhost');
define('FTP_USER', '«your user name goes here»');
define('FTP_PUBKEY', '«full path to user's home directory»/.ssh/');
define('FTP_PRIKEY', '«full path to user's home directory»/.ssh/wp_rsa');

Finally, set the protections and ownership on the wp-content directory to allow Apache to create things in there (assumption — I have ownership of my wp-content directory set to «site owner»:apache; you may need to adjust this to suit your specific situation:

$ chmod 775 «full path to WordPress directory»/wp-content

You should be good to go.

[This posting is an adapted excerpt from the upcoming book “McFate’s Indispensible and Comprehensive Guide to Building Bullet-Proof Servers”]

The Correct Way to Lock Out an IP Address From Your Server

I’ve been getting something like a one-person DoS attack overnight, it seems — a single IP address hitting port 80 hundreds of times a minute, generating endless 404s, and chewing up noticeable bandwidth — so I had to add a rule to my iptables to block the IP address at fault. Here’s how to do it:

First, list your current iptable rules, with line numbers, for easy reference:

$ sudo iptables -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    fail2ban-SSH  tcp  --             tcp dpt:22 
2    ACCEPT     all  --             
3    REJECT     all  --           reject-with icmp-port-unreachable 
4    ACCEPT     all  --             state RELATED,ESTABLISHED 
5    ACCEPT     tcp  --             tcp dpt:25 
6    ACCEPT     tcp  --             tcp dpt:587 


Add a new rule to block the offending IP address (“xxx.yyy.zzz.www”).

$ sudo iptables -I INPUT 1 -s xxx.yyy.zzz.www -j DROP

This will insert the new rule at position 1, just prior to the rule that accepts TCP incoming traffic on port 22 for SSH and passes it to fail2ban.

Save the updated table and restart the service.

$ sudo service iptables save
$ sudo service iptables restart
$ sudo iptables -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    DROP       all  --           
2    fail2ban-SSH  tcp  --             tcp dpt:22 
3    ACCEPT     all  --             
4    REJECT     all  --           reject-with icmp-port-unreachable 
5    ACCEPT     all  --             state RELATED,ESTABLISHED 
6    ACCEPT     tcp  --             tcp dpt:25 
7    ACCEPT     tcp  --             tcp dpt:587 


Some suggestions for doing this that turn up on Google have used the “-A” (Add) flag rather than the “-I” (Insert) flag. This will not work in most cases, it would add the new rule to the end of the INPUT chain, after the rule that accepts (for instance) HTTP packets. If the banned IP address were attempting to access port 80, if would be ACCEPTed by that rule before it could get DROPped by the new rule.

The position of the rule is important: if it follows a rule which would accept the traffic otherwise, the new rule will have no effect. Placing it before the rules for general public traffic ensures that the annoyance in question can’t consume resources by trying to do things like load non-existent web pages. In fact, by checking first, the IP address is effectively firewalled from the server.

“Shell Shock” Exploit — Probably Not a Worry For OS X Users

We’ve been hearing a lot about a very serious exploit in a universally-deployed piece of software, the “Shell Shock” bug in the bash shell. I got an alert late yesterday evening, and immediately upgraded the software on my publicly-facing servers.

There’s been some discussion of whether or not it’s an issue for OS X, and some debate over whether it’s a significant exposure on that platform. I didn’t think it was, but I haven’t seen an update for OS X Server to patch it, for example.

My own version of bash is managed through Homebrew, so rather than the stock 3.2, I’m running a newly patched and up-to-date v4.3.25(1). However, I got curious, so I decided to check the stock OS X version of bash for this exploit, and here’s what I found:


So, the (rather antiquated) OS X version of bash, which has a “modified” date of May 10, has already been patched to disallow this hack, or so it would appear.

UPDATE: Apple’s given a statement on iMore that OS X users should not be at risk from the “Shell Shock” exploit unless they have “advanced UNIX services configured”. I’m not sure which specific “advanced UNIX services” they’re referring to — at a guess, “Web Sharing”, which I don’t do, seems a likely suspect — but that may be the explanation for the commenters reporting vulnerability and me not seeing it on my system (either in /bin/bash or in /bin/sh)…

The vast majority of OS X users are not at risk to recently reported bash vulnerabilities,” an Apple spokesperson told iMore. “Bash, a UNIX command shell and language included in OS X, has a weakness that could allow unauthorized users to remotely gain control of vulnerable systems. With OS X, systems are safe by default and not exposed to remote exploits of bash unless users configure advanced UNIX services. We are working to quickly provide a software update for our advanced UNIX users.”

UPDATE, 2014-10-01: Apple has put out a patch for OS X systems.