Securing a self hosted WordPress site with SSL for Free.

As of this week, Chrome has started to display Not Secure for any website that doesn’t provide an encrypted connection (https).

If you run a WordPress site that’s hosted on WordPress servers (like this one), your site has been served via SSL for quite some time now. However, if you host your own site, you will likely need to do something to not have your visitors see this warning. It’s also the right thing to do. The entire web is moving to encrypted connections and it’s time for even small websites and blogs to make the move as well.

Wait, wait… you say. If I’m not collecting user information, why do I need encryption? Security researcher & blogger Troy Hunt has an excellent overview as to why it’s important even for static sites in his post Here’s Why Your Static Website Needs HTTPS. I’d recommend watching both the long video (24 min) embedded in the post and his short HTTPS is Easy video clips. TL;DR It’s because traffic from your website can be intercepted and modified without your user knowing. Governments, ISPs, Hots pot providers (cafe’s hotels, airports etc). Important: don’t follow the steps in the first video just yet. There’s some things we need to do in WordPress Admin to make sure things go smoothly.

Convinced? Ok. Good. So what to do.

If you are actually running your own physical or vitrualized server, you can buy an SSL certificate and install it. The cost of this ranges quite widely so shop around. If you can’t justify or afford the cost, you can check out my post on Setting Up Let’s Encrypt or read on.

If you have a site from your host that runs cPanel or something similar that gives you some admin functions but is a shared environment that doesn’t let you manage SSL certificates directly on the server, you need a different approach.

Most cPanel hosts do allow certificates, but because of the way Let’s Encrypt works, you will be unable to install services needed for it to work correctly. This means you’ll need to purchase a certificate (usually from your host) to fully secure your site end to end. If you store visitor’s personal information, this is your best bet.

However, there is another option for sites that serve static pages and don’t collect user data. Let’s call it Pretty Good SSL. What it does is encrypt the connection between the user and a service called Cloudflare which sits between your site and your users. The connection from your site to Cloudflare will -not- be encrypted but in most cases this is…Pretty Good SSL. It’s not perfect but for most static sites not collecting user data, it’s just fine. Again Tory Hunt has a good explanation as to why.

OK so how do we make this happen.

Let’s load up your site in Chrome. If you’re still on Chrome 67 go into incognito mode (ctrl-shift-n) you’ll see

If you have Chrome 68, you’ll see it even when not in incognito mode. (which is the reason we’re doing this ;p)

Log in to your WordPress Admin. From the PlugIns – Add New > Search For Cloudflare. You need to install the Flexible SSL fix and it’s not a bad idea to install the full Cloudflare plugin…but it’s not necessary. The Fix is. Without it, you will get stuck in an infinite loop after enabling SSL.

Now head to www.cloudflare.com

Follow along the steps in this 5 minute video from Troy Hunt

 

Basic steps from the video.

  • Set up a Cloudflare account and log in
  • Add your site
  • Change your DNS nameservers to those provided by Cloudflare (wait for a bit…usually about an hour but could be up to 24 hrs)
  • IMPORTANT: The default setup in the Crypto page setup on Cloudflare is FULL but we need to change that to Flexible.

While you wait for the DNS to update, you can update some more settings on the Crypto page.

Note: these settings update when you change them. There’s no Save button on the page.

Now you can check back on the home page until you see. You might need to click the Recheck Nameservers button (limited to once a hour)

If you see that, then you’re all done on Cloudflare.

You might have to wait a couple of hours, or even a full day before the Cloudflare certificate is active. You can check for an active certificate on the Crypto page. 

Finally, head back to your browser and reload the site (might have to hold the shift key to get an uncached version) and viola.

Your site is now Secure!

In fact, it’s more secure (at least in terms of the connection) than many banks. (via https://www.ssllabs.com/ssltest)

Welcome to the future.

PS: Despite the title and all the mentions of SSL in this post, the truth is that the actual SSL protocol has been deprecated due to security problems. For several years, when people say SSL, they really mean TLS which is the protocol that all non-obsolete browsers use. But since most people (even SSLLabs.com) still use the term SSL, I have as well.

Advertisements

Setting up LetsEncrypt on Windows Server2012/IIS8 with HSTS

It’s been forever since I posted here but as usual, I post when I’ve struggled through something, not found clear solutions and resolved it. Hope this helps.

Situation.

We have a public website http://www.example.com, an Exchange gateway email.example.com and an RDS (terminal services) gateway rds.example.com.

UPDATE: March 6, 2018
The steps outlined here do work for RDS & Exchange but there are problems. Both Exchange and RDS require additional steps to renew certificates, specifically, manually assigning certificates to various services with built in tools (Exchange Admin Console and RDS Connection Broker) so a 90 day LetEncrypt certificate is a huge pain and I’ve paid the big bucks for two year certs from a CA.But as I said, these steps -do- work fine if you run a simple web server, so the post is still valid and I hope it helps some of you.

 

Our public website is set up to use Long Duration HSTS (HTTP Strict Transport Security) and is in fact part of HSTS Preload. I encourage you to read up on HSTS and preloading but basically, this means that browsers know that all pages served must be over HTTPS. Long duration HSTS means that browsers set a flag for the site the first time it is visited that it will only allow pages from that site over HTTPS for the duration set up in the response header

FYI, 31,536,000 seconds is one year. Notice also that the includeSubDomains flag is set. This is important to know for setting up LetsEncrypt in my scenario with the 2 subdomains (email & rds). I’ll get to that in a bit.

Our public website has an EV certificate which allows the pages to be loaded from http://www.example.com and example.com. I can’t use this particular certificate for email and rds. My CA does offer multi-domain EV certs but they are quite expensive.  There’s no real benefit to having an EV cert on those subdomains. (some may argue there’s no benefit to an EV cert at all except for Security Theatre but that’s another post 😉 ) Because of this we’ve had the 2 subdomains on certs from a cheap SSL provider as we are only looking at securing the gateways.

These subdomain certs are up for renewal and I though I’d give LetsEncrypt a try. I looked at it a few years ago, but it was basically built for *nix servers and windows implementations were few, generally terrible and documentation was almost non-existent. And still sort of is…hence this post.

There are now some tools for windows you can use to help get a LetsEncrypt cert installed on Windows, in my case Server 2012 R2 running IIS 8.

My first attempt to get this to work was using Win-Acme. I never got it to work, but I’ll outline what I did for keywords so if others have the same problem maybe they’ll find what I was able to get working (or someone can point out what I did wrong) You can skip this bit and head down to Certify App walkthrough if you want.

Unzip the package to  permanent location on the server (needed for renewal) run Letsencrypt.exe from an admin console.

Select N for Create new Certificate

Select 1 for Single Binding of an IIS site

Quick aside here. You need to make sure that your site bindings in IIS are set up correctly. In our case, we just have a single site per server (and subdomain) so the binding for the Default Website is like this. This may vary depending on your set up. Note that the SSL cert listed here is the expiring one.

Back to Win-Acme. You will be presented with a list of all registered IIS sites. In this case, there’s just the single one, but select the number of the site you want to install the cert on.

The first time you run a request for a site, you will be asked to enter an email address for renewal notifications. Since I’d tried this a couple of times, already, I don’t have a screen shot of that.

Once you’ve done that, Win-Acme will try to install the cert. And, in my case, fail.

There are a couple of things I tried. There apparently needs to be a folder in wwwroot of your site called

.well-known/acme-challenge

for the certification process to work properly. I believe the process just checks to see that a file can be served from the server that you are trying to certify.

First challenge is to create a folder called .well-known because on a windows system, it is impossible to create a folder that starts with a dot using File Explorer. Hang over from the old days I guess. You can do one of 2 things. Create a folder (called LetsEncrypt or anything really) in File Explorer and then create a .well-known Virtual Directory in IIS or simply fire up PowerShell cd to your site root and use

md .well-known

Then you can create your acme challenge folder as a sub of that any way you want.

You also may need to set up IIS to accept requests for extension-less files. Some guides suggest setting accepted Mime Types to * application/octet-stream but that is not a great idea as it basically opens a potential security hole as it allows -any- file to be run on your server.

The more secure method is to add a web.config file to the acme-challenge folder

<?xml version=”1.0″ encoding=”UTF-8″?>

<configuration>
<system.webServer>
<validation validateIntegratedModeConfiguration=”false” />
<staticContent>
<mimeMap fileExtension=”.” mimeType=”text/json” />
</staticContent>
<handlers>
<clear />
<add name=”StaticFile” path=”*” verb=”*” type=”” modules=”StaticFileModule,DefaultDocumentModule,DirectoryListingModule” scriptProcessor=”” resourceType=”Either” requireAccess=”Read” allowPathInfo=”false” preCondition=”” responseBufferLimit=”4194304″ />
</handlers>
</system.webServer>
<system.web>
<authorization>
<allow users=”*” />
</authorization>
</system.web>
</configuration>

Which basically limits the serving of extension-less files from just that folder.

After trying all of that and more, I still was unable to get win-acme to work. Also, know that LetsEncrypt rate limits failures to 5 per hour so you may have to wait if you try and fail several times.

So I moved on to Certify. (which as you’ll see worked so I never did test the PowerShell tool.)

Install the Certify app on your server  and then run it.

Click New Certificate.

Just like win-acme, you’ll be asked to enter an email address for renewal notifications.

Select the IIS site from the drop down, in this case, its Default Website.

Take note of the message

The LetsEncrypt service must be able to access all of these domains via port 80 (for HTTP challenges) or port 443 (for TLS-SNI challenges) for the certification proess to work.

So because my site is HSTS, SSL is always on, I figured I had to use the TLS-SNI challenge type. The advanced tab allows us to select which to use.  And a handy Test button.

Run that and you should get an OK

Click save changes and you will be ready to request a LetsEncrypt certificate.

 

Click on the site in the sidebar and the click request certificate and you’ll get an error?

Specifically Default Web Site: Request failed – no challenge found matching requested type.  What’s that mean?

Well it turns that in January of 2018, LetsEncrypt stopped allowing TLS-SNI requests due to a vulnerability which could allow getting certificates for domains you don’t own. Which is like, really bad.

I assume the TLS-SNI challenge type will eventually be removed (and may already be by the time you read this) from Certify as LetsEncrypt has no plans to reinstate support.

So back to the advanced tab, select http-01 challenge and run a test.

Now you’ll see that the error message that the config failed to verify that the site is publicly accessible and can serve extension-less files. Well, the nice thing about Certify is that it actually creates the .well-known/acme-challenge folder and creates the web.config file as mentioned in the win-acme section above.

So we know we should be able to serve extension-less files and since the folder is in the webroot, it should be publicly accessible. So what’s the problem?

This is where we circle back to HSTS and always on SSL. When the LetEncrypt process uses http-01, it’s expecting a result on port 80 (standard http) but since our site is HTTPS Only, the service can’t get the file.

Now if you read this before you try the first time, you may be able to turn HSTS off to install the certificate (but I can’t verify that) however -don’t- do this unless you want to manually do this every time your certificate needs updating. And that’s a lot because, unlike commercial certs with a 2 year max expiry LetsEncrypt certs expire every 90 -days-.

So we need HTTP to get the cert, but can only use HTTPS. What do we do?

Turns out it’s pretty simple. We use URL Rewrite in IIS.

IMPORTANT: For a standard webserver the following steps work fine. They do -not- work on an Exchange server. Well they do, but setting a URL Rewrite to HTTPS breaks Exchange Management Shell and Exchange Toolbox (Exchange 2013). To set up redirection on an Exchange 2013 server follow the steps HERE .

URL Rewrite is not installed by default in IIS, so either download it from Microsoft  or use the Web Platform installer.

You might have to restart IIS Manager to get it to show up after install.

Head to the root node of your website in IIS Manager and fire up URL Rewrite

Then click Add Rule > Blank Rule

Give it a name (ie: toHTTPS), Select Matches the Pattern & Regular Expressions from the drop downs. Then add the pattern (.*)

Under Conditions, click Add and then add Condition input {HTTPS} Matches the Pattern and ^OFF$

Click OK.

Finally, set your action to Redirect, Redirect URL to https://{HTTP_HOST}/{R:1} and Redirect Type to Permanent (301)

Click apply and you now redirect all HTTP traffic to HTTPS.

How does this help with the Certify issue? Well thankfully, LetsEncrypt only needs to hit port 80. It does not care about what happens after that. The server handles the conversion to HTTPS and everyone is happy. Run the http-01 challenge again and you should see

Now all we need to do is click Save and then Request Certificate again.

And after a few minutes….

Now Certify should automatically set up the binding to the new cert but you’ll want to double check just to make sure.

And yup it’s there and assigned.

And we can view the certificate details and woohoo. We’re good to go.

Now this should automatically renew on May 30, 2018, 89 days from now. If it doesn’t, I’ll be doing another post I expect 🙂

Hope this helps.

 

Using Self Signed SSL Certificates on an IIS8 Intranet without Chrome Errors

I’ve just been trying to add a certificate to our intranet site and the standard way of creating and using a self signed in IIS

no longer works in newer versions of Chrome (and probably other browsers*, soon if not now).

UPDATE: March 8, 2018
The certificate works fine in Chrome 64 and Edge 41
It still requires an added exemption in Firefox 58 :\

The old steps were to create the certificate, assign it to the 443 bind in IISAdmin, browse to the site with Chrome, which would throw up an untrusted error which you could bypass in the Advanced tab. Once you had the site loaded, you could add the certificate to your local store. Of course, you had to repeat on every browser on the intranet…which was a huge pain, but worked.

However, with Chrome 64 (and possibly earlier) this is no longer possible. Even when you add the certificate, you will still get a Not Trusted warning.The last thing you want to do is to train users to ignore certificate warnings so it would probably be better to not switch to SSL for intranet except….

It is possible, and actually even easier than the old way since you don’t need to make individual company wide exceptions. The key is that Chrome wants a SAN certificate

Unfortunately, IIS can’t automatically create a self signed SAN certificate, but that doesn’t mean it’s not possible. You just need to use the Certificates MMC Snap in. Robert McMillen has provided an excellent walk through on how to do this on Server 2012 R2.

Once you’ve created the SAN certifcate, just pop back into IISAdmin, go to your site bindings for 443 (or add one) , choose the new certificate and save. Fire up Chrome and browse to the site and you should see this without any warnings.

Don’t forget, you may need to update your intranet website code to ensure all content is served over HTTPS so you avoid a mixed content warning. I use Eclipse so I just did a project wide Search & Replace. You also might want to set up a URL Redirect from HTTP to HTTPS to ensure your users are always using the HTTPS site.

How to override the new plain white background in Twitter

As many of you know, Twitter just removed the ability to customize backgrounds on the web client. It’s bad-ish that they removed the ability to add custom graphics as a back ground, but far worse, they removed the ability to change the background colour, leaving users with an eye-bleeding, headache inducing bluish white. new-9

Well, “the Man” might be wanting us to just shut up and deal with it but we don’t have to take it. StyleBot allows us to edit the CSS (stylesheet) of any page. It is originally intended as an accessibility tool as it allows users to change colours (to make them high contrast), font sizes  etc, however we can use is to stick it to the Twitter man, The great thing about this is that we can save the styles and the plugin changes the colours pretty much permanently.

The following works for Chrome and there’s probably similar things you can do in Firefox & maybe IE.

Install the free StyleBot from the Chrome Store

You will now have a CSS button in the upper right. Right click on it and select Options.

new-2

Select the Styles tab

new-7

Click Add a New Style

Then add the URL twitter.com and the 3 lines of CSS code. (Important: everything is Case Sensitive)

body {
    background-color: #4a7383;
}

I like a dark-ish blue but you can pick what ever value you want. There’s a good colour picker tool here at Mozilla

new-6

Now click the save buttton, reload your Twitter tab and say ahhhh.

new-11

You’ve got a background that you control. And there’s nothing the Man can do about it. You can go crazy and change fonts, layouts and a lot more or use one of the pre-built style for Twitter & many other sites from StyleBot Social but for me, I just wanted the background colour changed.

Note: this only affects what -you- see. If you wanted to customize your Twitter page for others, you’re out of luck. At least until Twitter starts charging you to customize it. Which is my guess as to why they have done this miserable thing in the first place.

Update: Noticed that Twitter cards are changed by this as well.

new-12

I don’t like that but it’s easy to change. All we need is to do is add an entry for Twitter Cards.

body {
   background-color: #4a7383;
}
div.TwitterCardsGrid {
    background-color: #ffffff;
}

Another little tweak.

if you use analytics.twitter.com and don’t want that page altered (it’s quite hard to read with a dark background.)

Add an entry with just a white (#ffffff) background.

Capture

Then modify the original URL to ^https://twitter.com/

Capture

This applies the fix to the main twitter page but not to analytics.

Update #3

Firefox users can install Stylish

Load Twitter.com

Click the S icon and then Write new style > for twitter.com

new-14

new-15

Place your cursor between the { } on line 4 and paste the CSS code from above. Give it a name and click save.

new-16

Coldfusion Directory Monitoring with Event Gateways

This just came up on Twitter today and I realized I hadn’t posted about it so here you are.

Many hacks of ColdFusion over the years have been through people manipulating the CFIDE directory. (the most famous being the FCKeditor Hack) There are many ways to combat this but here’s a simple one.

Using the DirectoryWatcher Event Gateway built into CF versions 8 & up, you can in just a few minutes set up some code to monitor & alert you of changes to the CFIDE (or any other) directory.

You need 2 piece of code.

The Config File

CFIDE_Alert.cfg

# The directory you want to watch. If you are entering a Windows path
# either use forward slashes (C:/mydir) or escape the back slashes (C:\\mydir). 
directory=C:/Inetpub/wwwroot/cfide
# Should we watch the directory and all subdirectories too
# Default is no. Set to 'yes' to do the recursion. 
recurse=yes
# The interval between checks, in milliseconds
# Default is 10 seconds
interval=10000
# The comma separated list of extensions to match.
# Default is * - all files
extensions=*
# CFC Function for file Change events
# Default is onChange, set to nothing if you don't want to see these events
changeFunction=onChange
# CFC Function for file Add events
# Default is onAdd, set to nothing if you don't want to see these events
addFunction=onAdd
# CFC Function for file Delete events
# Default is onDelete, set to nothing if you don't want to see these events
#deleteFunction=

and a CFC to use for the Gateway. (note: I don’t have Delete events turned on as I delete CFIDE/Admin files when not in use…for another post)

CFIDE_Alert.cfc

<cfcomponent>
<cffunction name="onAdd" returntype="any">
<cfargument name="CFEvent" type="struct" required="yes">
<cfset data = CFEvent.data>


 <cfmail to="webmaster@example.com" 
		server="yoursmtp.server"
		username="youruname"
		password="yourpwd"
		from="alert@example.com"
		subject="CFIDE CHANGE DETECTED!"
		type="html">
<cfdump var="#data#">
</cfmail>
</cffunction>

<cffunction name="onCHANGE" returntype="any">
<cfargument name="CFEvent" type="struct" required="yes">
<cfset data = CFEvent.data>


 <cfmail to="webmaster@example.com" 
		server="yoursmtp.server"
		username="youruname"
		password="yourpwd"
		from="alert@example.com"
		subject="CFIDE CHANGE DETECTED!"
		type="html">
			
<cfdump var="#data#">
</cfmail>
</cffunction>

</cfcomponent>

Then all you need to do is create the Event Gateway

Capture

Now, if any files are changed or there are files added, you are sent an email. You could also use Event Gateways to send a an SMS message so you can be notified anywhere, anytime.

Capture

Security Basics: Email Survey Requests are Dangerous

Quick post this afternoon based on a semi regular security email I send out to all users at work.

Both at home and at work, we often see companies sending out email surveys, often with enticements like coupons, entries in draws etc.

It is often extremely hard to tell if these are legitimate.

Here are 2 I’ve recently received

 

b1b2

Now we know that the very first thing to do when we are trying to find out if an email is from a legitimate source is check the FROM address.

(Of course we always keep in mind that FROM addresses can be spoofed, right?)

Here are the 2 FROM addresses for the above emails

b3

b4

Can you tell which is legitimate? Knowing that emails from Walmart or Telus should have a @ walmart.com or @ telus.com (same origin emails) doesn’t help in the case of many legitimate surveys. As stated in the Telus email, companies often contract survey work out to companies who specialize in this kind of thing.

Neither of the above is from same origin but there are some clues in the emails themselves that hint which is legitimate and which is not.

 

  • One says you’ve WON!* something, the other says you’ll be entered for a chance to win. Guess which is more likely to be legitimate.
  • One only offers links to click, the other offers a copy and paste option. Copy and paste allows you to see where the link actually goes. (of course we all hover over links to see where they point always in any case right?)
  • We actually -are- a client of Telus. We/I don’t have any Walmart association (ask yourself “how did they get my email”)

 

So yes, the Telus email is legitimate. The Walmart one points to a malware exploit.

My advice is to ignore and delete survey requests from all senders.

*See Rule Of Exclamation Points In Email

 

Rule Of Exclamation Points In Email

The chances of a email being legitimate is inversely proportional to the number of exclamation marks it contains!!!

 

 

http:BL_CFML – A Project Honeypot Blacklist Implementation for ColdFusion.

At the urging of Charlie Arehart, I’ve cleaned up my http:BL_CFML implementation and added a bit more in the way of comments. I’m putting this here so it’s easy to link to from the http:BL implementations site. For more in depth information about the code, please check out the links to my previous posts listed below.

Stopping Comment Spammers & Email Harvesters with Coldfusion & Project Honeypot

Project Honeypot & Coldfusion Part 2

<cfcomponent displayname="http:BL_CFML v1.01">

<!--- Some original code from mximize.com (which no longer exists) with modifications by JayB sidfishes.wordpress.com
More detailed explanation available here:
https://sidfishes.wordpress.com/2011/06/09/stopping-comment-spammers-email-harvesters-with-coldfusion-project-honeypot/
https://sidfishes.wordpress.com/2011/12/06/project-honeypot-coldfusion-part-2/
https://sidfishes.wordpress.com/2014/07/31/httpbl_cfml-a-project-honeypot-blacklist-implementation-for-coldfusion/

You are free to use or modify this code for any purpose provided links to original posts are maintained.
--->
<!---
This CFC contains the following functions

honeypotCheck: Main framework
newVisitorCheck:  Check with our white list table to see if this ip has visited in the last 3 months.
addToWhiteList: IP's that check as clean against http:BL are added to our white list table to increase page load performance.
getHostAddress: does a reverse lookup of the client IP address against the blacklist at http:BL.
reverseIP: return IP in reverse format as required by http:BL api

You need to create a new table to track white listed IP's

MySQL
/************************************/
CREATE TABLE `visitor_ip_addys` (
`ip_id` int(10) unsigned NOT NULL auto_increment,
`ipaddy` varchar(15) NOT NULL,
`visitdate` datetime NOT NULL,
PRIMARY KEY  (`ip_id`)
) ENGINE=InnoDB AUTO_INCREMENT=510495 DEFAULT CHARSET=utf8$$
/************************************/

MSSQL
/************************************/
CREATE TABLE [dbo].[visitor_ip_addys](
[ip_id] [int] IDENTITY(1,1) NOT NULL,
[ipaddy] [varchar](15) NOT NULL,
[visitdate] [datetime] NOT NULL,
CONSTRAINT [PK_deleteme] PRIMARY KEY CLUSTERED
(
[ip_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
/************************************/

The table is cleared daily of IP's older than 3 months to revalidate visitors in case they may have been
compromised in the time and to keep table size reasonable
--->

<cffunction name="honeypotCheck" returntype="struct" hint="Check Project HoneyPot http:BL">
<cfargument name="ip" required="yes" type="string">
<cfset var aVal = "">
<!---  Make sure to replace {your_API_key} with the API key you receive from the http:BL project --->
<cfset var hpkey = "{your_API_key}">
<cfset var stRet = structNew()>
<cfset var result="">
<cfinvoke method="newVisitorCheck" returnvariable="result">
<cfinvokeargument name="ip" value="#arguments.ip#" />
</cfinvoke>
<cfif result eq "new">
<!--- do the blacklist lookup IP values --->
<cfset aVal = listToArray(gethostaddress("#hpkey#.#reverseip(arguments.ip)#.dnsbl.httpbl.org"),".")>
<cfif aVal[1] eq "IP-Address not known">
<!--- then no match on the Black list --->
<!--- set a value indicating ok address --->
<cfset stRet = {type=99}>
<!--- insert into visitor_ip_addys table --->
<cfinvoke method="addToWhiteList" returnvariable="result">
<cfinvokeargument name="ip" value="#arguments.ip#" />
</cfinvoke>
<cfelse>
<!--- there was a match so set the return values --->
<cfset stRet.days = aVal[2]>
<cfset stRet.threat = aVal[3]>
<cfset stRet.type = aVal[4]>
<!--- Get the HP info message ie: threat level --->
<cfswitch expression="#aVal[4]#">
<cfcase value="0">
<cfset stRet.message = "Search Engine (0)">
</cfcase>
<cfcase value="1">
<cfset stRet.message = "Suspicious (1)">
</cfcase>
<cfcase value="2">
<cfset stRet.message = "Harvester (2)">
</cfcase>
<cfcase value="3">
<cfset stRet.message = "Suspicious & Harvester (1+2)">
</cfcase>
<cfcase value="4">
<cfset stRet.message = "Comment Spammer (4)">
</cfcase>
<cfcase value="5">
<cfset stRet.message = "Suspicious & Comment Spammer (1+4)">
</cfcase>
<cfcase value="6">
<cfset stRet.message = "Harvester & Comment Spammer (2+4)">
</cfcase>
<cfcase value="7">
<cfset stRet.message = "Suspicious & Harvester & Comment Spammer (1+2+4)">
</cfcase>
</cfswitch>
</cfif>
<cfelse>
<!--- good address  --->
<cfset stRet = {type=99}>
</cfif>
<cfreturn stRet>
</cffunction>

<cffunction name="newVisitorCheck" returntype="string">
<cfargument name="ip" required="yes" type="string">
<cfset var vQry = "">
<cfset var result="">
<cfquery name="vQry" datasource="#local.dsn#">
select ipaddy from visitor_ip_addys where ipaddy = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.ip#">
</cfquery>
<cfif vQry.recordcount eq 0>
<!--- then it's a new visitor  --->
<cfset result = "new">
<cfelse>
<cfset result ="existing">
</cfif>
<cfreturn result>
</cffunction>

<cffunction name="addToWhiteList" hint="I add client IP's that don't match with http:BL entries (ie: not comment spammer)">
<cfargument name="ip" type="string" required="true">
<cfset var iQry = "">
<cfquery name="iQry" datasource="#local.dsn#">
insert into visitor_ip_addys (ipaddy, visitdate) values
(<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.ip#">,
<cfqueryparam cfsqltype="cf_sql_timestamp" value="#now()#"> )
</cfquery>
</cffunction>

<cffunction name="ipTableCleanup" hint="I run from a daily scheduled task">
<cfset var deleteIP = "">
<cfquery name="deleteIP" datasource="#local.dsn#">
delete from visitor_ip_addys where visitdate <= DATE_ADD(CURRENT_TIMESTAMP, INTERVAL -90 day)
</cfquery>
</cffunction>

<cffunction name="getHostAddress" returntype="string" hint="I do the dns lookup against the http:bl servers">
<cfargument name="host" required="Yes" type="string">
<cfset var obj = "">
<cfset var result="">
<cftry>
<!--- error handling as error is thrown if host lookup has no match in http:BL ie: it's not been reported as a problem --->
<!--- Init class --->
<cfset obj = CreateObject("java", "java.net.InetAddress")>
<cfset result =  obj.getByName(host).getHostAddress() >
<cfcatch type="any">
<!--- an "error" in this case is an unknown address, which means it is not reported to http:BL --->
<cfset result="IP-Address not known">
</cfcatch>
</cftry>
<!--- Return result --->
<cfreturn result>
</cffunction>

<cffunction name="reverseIP" returntype="string" hint=" I return IP in reverse format as required by http:BL api">
<cfargument name="ip" required="Yes" type="string">
<cfset var aIp = listToArray(arguments.ip,".")>
<!--- Return IP reversed --->
<cfreturn aIp[4] & "." & aIp[3] & "." & aIp[2] & "." & aIp[1]>
</cffunction>

</cfcomponent>

To use this CFC, simply add the following code to a page on your site where a comment spammer or email harvester would visit. If they are on the Blacklist, they will get a 404 error when they try to visit that page.

You can also add this on a site wide include if you like (but this could have performance implications)

</pre>
<!--- Check Project HoneyPot --->
<cfinvoke method="honeypotcheck" component="com.HoneyPotdns" returnvariable="stCheck">
<cfinvokeargument name="ip" value="#cgi.remote_addr#" />
</cfinvoke>

<cfif isDefined("stCheck") AND (stCheck.type GTE 4 AND stCheck.type LTE 7)>
<!--- Send a simple 404 message rather than a hey spammer get lost message. No use in poking a hornets nest --->
<cfheader statuscode="404" statustext="Not Found">
404 Not Found
<cfabort>
</cfif>