I can't promise you "successfully, permanently" but there are certainly plenty of things you can do to make his life more difficult. Enough of these and he will give up.
You have already tried using his IP address for identification but it's easy to find free proxy servers. It's somewhat harder to find free and anonymous proxy servers. Most proxy servers send the user's IP address along in an
X-Forwarded-For: header. You can use
mod_security to block these.
SecRule REQUEST_HEADERS:X-Forwarded-For "@Contains 192.168.0.1"
Obviously, you should replace
192.168.0.1 with his actual IP address. You can block a larger set of proxied IPs by removing the last octet.
This will limit him now to using anonymous proxies and Tor. You can identify when he's using Tor because every request will come from a different IP address and these will probably all be on a Tor exit node list. Here are two examples of lists. There are proxy lists available too.
echo("<img src=\"http://example.com:25/".session_id().".jpg\" />");
It's also worth noting that Google analytics assign a unique identifier in the second "field" (separated by dots) of their
__utma cookie. If you have Google analytics and he doesn't delete this cookie, you may already have enough to track him.
To log cookies (and all HTTP headers) you can use a forensic log.
Following that, browser fingerprinting is a bit more difficult and prone to both false positives (if you make it a little fuzzy) and false negatives (if you go for exact matches only) but can it be done. It would actually be more effective if he keeps reverting his VM to a known state because that will mean his fingerprint never changes. He would have to change his VM's screen resolution and time zone and the installed plugins each time he got banned.
One more method: Identify the content he posts. Just treat him like a normal spammer. Feed his data through a Bayesian learning engine and teach it to recognise him... and once it's good enough at recognising what he posts, ban anyone who posts that sort of content. This one has the nice advantage that false positives are probably people you would want to ban anyway, even if they're not the same guy.