Spam, spam, spam, spam. Spammers have taken over the Internet and made it a horrible place to maintain a web site. Spammers have gone beyond simply spamming your email account -- now they are spamming blogs and guestbooks, spamming trackbacks, and spamming signup forms. Even a child's home page with a guestbook for friends is not safe from links for cialis, porn, or web hosting. Obviously these spammers are getting some return from their criminal activity, because they keep doing it. Unfortunately, you can't reach through the computer screen and grab them by the throat to strangle the life out of them. All you can do is put in place some safeguards and try to minimize the attack. Part 2 in this series shows how you can record the IP address of the spammer and block access to your site to that computer in the future. Once again, I'll assume you have familiarity with PHP or ColdFusion basics (databases, inserting and displaying data) and HTML forms.
In the last part of the series I showed a simple anti-spam technique that requires that a live person enter information into your form fields. If you have contact forms, comment forms, or guestbooks, you know that spammers have been recently attacking these otherwise innocent forms with all kinds of spam to try to drive traffic to their pitiful sites. If they are using actual human interaction to create their spam -- either filling in the fields themselves or hiring others to do it for them -- then you can attempt to block them in the future. I say "attempt" because spammers also use techniques to mask their IP address, and also do not always initiate their attack from the same computer. However, having said that, blocking these IP addresses can have an impact on the number of spams you get through your forms.
The technique involves setting up an include file (in the case of PHP) or putting some code in the Application.cfm file (for ColdFusion.) If you are using PHP and have implemented the technique shown in my article PHP Site Simplification with Application.php, then you can use that file for this functionality. The bottom line is that you want to block the spammer from even seeing your site, once he has been proven to be an attacker. You are in effect treating them like the misbehaving children that they are -- if they can't play nice, they will not be able to play at all.
The trick to this technique is to always store the user's IP address when creating your contact form. Rather than create a form that will not fit your site or situation, I'll describe the process so that you can adapt it to any form.
If your database table looks like this -- id, firstname, contacttime, email -- add an ipaddress field to the end of the table -- id, firstname, contacttime, email, ipaddress. To get the IP address of the user into the table, you will need to modify your insert statements on your forms. A typical insert statement might look like this for ColdFusion:
<cfquery datasource="blah">
INSERT INTO mytable (firstname, contacttime, email)
VALUES
(<cfqueryparam cfsqltype="cf_sql_varchar" value="#FORM.firstname#" />
, <cfqueryparam cfsqltype="cf_sql_varchar" value="#Now()#" />
, <cfqueryparam cfsqltype="cf_sql_varchar" value="#FORM.email#" />)
</cfquery>
or like this for PHP (note the use of GetValueString -- a function that Dreamweaver inserts when creating insert statements):
$insertSQL = sprintf("INSERT INTO mytable (firstname, contacttime, email) VALUES (%s, now(), %s)",
GetSQLValueString($_POST[firstname], "text"),
GetSQLValueString($_POST[email], "text"));
mysql_select_db($database_test, $test);
$Result1 = mysql_query($insertSQL, $test) or die(mysql_error());
What we will do is to grab the user's IP address and modify the SQL code so that the IP address is inserted into the new ipaddress field. To get the IP address and put it into a variable, we'll use some server variables right before the insert statement:
<cfset ipaddress = cgi.remote_addr>
$ipaddress = $_SERVER["REMOTE_ADDR"];
Now, all you need to do is store this IP address in your table. Modify your insert statement to include the IP:
<cfquery datasource="blah">
INSERT INTO mytable (firstname, contacttime, email, ipaddress)
VALUES
(<cfqueryparam cfsqltype="cf_sql_varchar" value="#FORM.firstname#" />
, <cfqueryparam cfsqltype="cf_sql_varchar" value="#Now()#" />
, <cfqueryparam cfsqltype="cf_sql_varchar" value="#FORM.email#" />
, '#ipaddress#')
</cfquery>
$insertSQL = sprintf("INSERT INTO mytable (firstname, contacttime, email, ipaddress) VALUES
(%s, now(), %s, %s)",
GetSQLValueString($_POST[firstname], "text"),
GetSQLValueString($_POST[email], "text"),
GetSQLValueString($ipaddress));
mysql_select_db($database_test, $test);
$Result1 = mysql_query($insertSQL, $test) or die(mysql_error());
At this point, every form submission will now contain an IP address. Now that you know who they are, you can do something to keep them from coming back.
The next step is to create a database table where you will store all the spammer information. Basically, you need a table where you can insert suspect IP addresses that can later be blocked at the page level. Basically, you will create a table named spammers with one field: ipaddress. In this table, you will store the suspect IP addresses of spammers. You could add a primary key to this field, as you only need one entry per spammer. Alternatively, you can create an auto-incrementing field to act as your primary key.
The ipaddress field should be a varchar field that holds at least 15 characters (as in 255.255.255.255). Once created, you can create a form on your site that can be used to insert the IP address of the spammer:
<h1>Spammer</h1>
<p>Insert a spammer IP address to block from this site</p>
<form id="form1" name="form1" method="get" action="">
<input type="text" name="ipaddress" id="ipaddress" />
<input type="submit" name="button" id="button" value="Submit" />
</form>
Then add some server-side code to the top of the page to insert the data into your database:
<cfparam name="url.ipaddress" default="">
<cfif url.ipaddress NEQ "">
<cfquery datasource="#request.datasource#">
INSERT INTO spammers (ipaddress) VALUES (<cfqueryparam cfsqltype="cf_sql_varchar" value="#url.ipaddress#">)
</cfquery>
</cfif>
<?php
require_once('../Connections/test.php'); // assuming you are using a DW connection
$_GET["ipaddress"] = isset($_GET["ipaddress"]) ? $_GET["ipaddress"] : "";
if($_GET["ipaddress"] != "") {
$insertSQL = sprintf("INSERT INTO spammers (ipaddress) VALUES ('%s')",
$_GET['ipaddress']);
mysql_select_db($database_test, $test);
$Result1 = mysql_query($insertSQL, $test) or die(mysql_error());
}
?>
Now, when you find a spam in your database table, you can simply paste the IP address in your "add spammer" form and the ip address will be stored in the table. Notice that I used a GET method on the form -- this gives you additional options to add IP addresses to the table:
The page can be used any way you like. The code to build these is basic, but beyond the scope of the article. With the concept in mind, you should be able to put this together.
Finally, you'll need code to read this database table and deny access to these specific IP addresses. For ColdFusion, the process is easy -- put the code in your application.cfm file, which is executed at the top of each page before the page is executed. For PHP, it involves the extra step of creating a file that is included automatically at the top of either every page, or just the specific pages you want to block. The code involves checking the user's IP address against all IP addresses that should be blocked, and then using a redirect to pass the user off to another location -- like the FTC site or some other scary sounding site.
In Application.cfm (or Application.cfc), you can add the following code:
<cfquery name="rsSpammers" datasource="tommuck">
SELECT ipaddress
FROM spammers
WHERE ipaddress = '#cgi.remote_addr#'
</cfquery>
<cfif rsSpammers.recordCount NEQ 0>
<cflocation url="http://www.ftc.gov">
</cfif>
On a page that will be included at the top of the form/action file or included on all pages (like an application.php file), add the following code:
<?php
require_once('../Connections/test.php');
$query_rsSpammers = sprintf("SELECT DISTINCT ipaddress
FROM spammers WHERE ipaddress = '%s'", $_SERVER['REMOTE_ADDR']);
$rsSpammers = mysql_query($query_rsSpammers, $test) or die(mysql_error());
if(mysql_num_rows($rsSpammers) > 0) {
header("Location: http://www.ftc.gov");
}
?>
Again, these are the basics only. You can set up the functionality to be as elaborate as you like -- adding a date/time stamp to the spammer entry, adding a field to allow/disallow IP addresses, setting a time limit for denying access, etc.
Hopefully this two-part series has gotten you to think about a couple ways to help prevent spammers from taking over your site and your contact forms.