Friday, May 30, 2008

Abusing SMTP Servers for fun and profit with JMeter and the SMTP plug-in

Let’s Be Spam Kings with JMeter! (aka Abusing SMTP Servers for fun and profit)

The other day I came across a SMTP Plug-in for JMeter from http://www.beolink.org/index/jmeter-plug-in.

Two extra .jars are needed that are not shipped with JMeter and those are mail.jar and activation.jar. There were no MD5 sum values so I assume that these two .jars are adequate as the solution appears to work. I am not aware of any possible versioning conflicts as I am no Java guru. I did write “Hello, World!” code once in Java back in 1995.

To install the plug-in I had to copy both mail.jar and activation.jar to the jakarta-jmeter-2.3.1\lib\ sub-dir and copied the SmtpSampler-0.9.jar to the jakarta-jmeter-2.3.1\lib\ext sub-dir.

Let’s create a brand new JMeter project:


Let’s add a thread for our spam chunking:


I’ve setup 5 threads with 200 iterations for a total of 1,000 iterations to be executed in total as this is the number of files that I want to chunk at our poor SMTP server.

Like in my FTP application, I have a CSV file that contains all the information that JMeter will require for chunking spam. It is pretty similar to the FTP data:

8<----------------------------------------------------------------- user1@someserversomeplace.com,10.0.1.4,C:\work\smtpLoadAgent\data\dataFile1.txt.gpg user2@someserversomeplace.com,10.0.1.4,C:\work\smtpLoadAgent\data\dataFile2.txt.gpg user3@someserversomeplace.com,10.0.1.4,C:\work\smtpLoadAgent\data\dataFile3.txt.gpg user4@someserversomeplace.com,10.0.1.4,C:\work\smtpLoadAgent\data\dataFile4.txt.gpg user2@someserversomeplace.com,10.0.1.4,C:\work\smtpLoadAgent\data\dataFile5.txt.gpg user1@someserversomeplace.com,10.0.1.4,C:\work\smtpLoadAgent\data\dataFile6.txt.gpg user5@someserversomeplace.com,10.0.1.4,C:\work\smtpLoadAgent\data\dataFile7.txt.gpg user4@someserversomeplace.com,10.0.1.4,C:\work\smtpLoadAgent\data\dataFile8.txt.gpg user5@someserversomeplace.com,10.0.1.4,C:\work\smtpLoadAgent\data\dataFile9.txt.gpg ------------------------------------------------------------------>8

The columns are pretty easy to figure out: e-mail address, IP address of the SMTP server in question and the path to the file that is going to be chunked. In this case, just like the FTP server example, it’s a GPG’d text file containing random data.

Just like the other example, add a CSV Data Set Config to JMeter defining the variables that will be used:


For some reason, the name of the plug-in comes across as [res_key=smtp_title]. I don’t know if this a config issue on my side or something not set properly in the .jar. I emailed the person that was nice enough to create this plug-in but haven’t heard anything back. It appears to be a cosmetic issue at this point and doesn’t cause any problems that I’ve seen so far.


Now we need to fill out the information for the SMTP sampler so we can abuse the SMTP server:


In this example, I replaced the default [res_key=smtp_title] with “smtpSampler” and set the Server field to the dynamic variable that I defined earlier as ${ipAddress}.

In my particular case, the SMTP server is running on port 35 and not the standard port 25. It’s great that the SMTP plug-in gives us this option as I couldn’t find an option to change the port number in the perl code that I had written with MIME::Lite and Net::SMTP. I had done some testing with a freeware port redirection tool that got the job done but I never got far enough to see how much overhead was consumed by the port redirection. Now I don’t have to worry about it!

I set the Address From field to be a (I think) non-existant e-mail address of joe@blow.com.

Address To is set to the dynamic variable ${emailAddress}

The file that I want to send is set to be ${fileToAttach} which is the full path to the file in question. Since the CSV file has a different file for each line, we won’t be sending the exact same file with each iteration.

For the subject line I used “${fileToAttach} ” and then checked the “Include timestamp in subject” checkbox. The timestamp that will be appended to the filename being sent is actually epoch time and not human readable form. For most people I doubt that this will be a problem. I also checked “Calculate message size” so I can see the number of bytes that were transferred when logging output.

Let’s go ahead and throw some Listeners so that we can see the results of our testing. I’m not going to use the spline graph as I prefer the scatter plot that Graph Results show. Even it isn’t my preferred way of showing data but it is easy enough to dump the output to an XML/CSV file and use some of my perl code to generate “pretty” graphs:


I have found that I prefer to watch the “Average”, “Deviation” and “Throughput” data points in the scatter plot.

In my particular case, I am pointing at an SMTP server running on my local laptop in a Virtual PC 2007 VM hosting a Win2k3 server running hMailServer. For a free e-mail server, hMailServer seems to be a fairly full featured product and includes IMAP support and integration with blacklists and WinClam virus protection and I even saw some entries for tar pitting and even AD support. Pretty darn cool!

Here is a shot of hMailServer waiting to receive our mass spamming of attachments:



Let’s rip loose with JMeter and see what happens:





Well, look at that! 1,000 e-mails chunked at a rate of about 300 per minute or about 5 per second. Not too shabby.

Logging into Thunderbird in the VM we see that the e-mail attachment was sent without issue:



How cool is that?

I found that the JMeter with the SMTP plug-in was faster than my perl code using MIME::Lite and Net::SMTP by about 1.5 e-mails per sec. I also had some issues with the MIME::Lite issuing a die() when a problem was encountered instead of returning a false with $msg->send_by_smtp() which would cause a worker thread to die off which was pretty annoying.

So, with the SMTP plug-in I get access to non-standard ports (as seen above) and better over all performance.

Something that I did find is that if on the SMTP Sampler screen the “Check for Failure” checkbox is checked that each of the e-mail xfers are marked as “warning”. Example is below:



If the log file that I specified is examined you will see the following:

“org.beolink.jmeter.protocol.smtp.UnexpectedSuccessException: Expected failure but got success...”

To checkout the 500 error return I went ahead and did some tests and captured the TCP stream with Wireshark (nee ethereal) and saw that there was no difference between the perl chunking and the JMeter/SMTP plug-in chunking and there were no error codes returned.

My solution? Uncheck the “Check for failure” checkbox and keeping on trucking.

Despite the two issues noted above, the SMTP plug-in for JMeter does a great job and I will be using it instead of my home grown perl solution.

No comments: