MX Validation in PHP

Posted by Nessa | Posted in Uncategorized | Posted on 01-12-2007


Hosting companies have all kinds of tactics to keep spam away from their customers, but one very common complaint I get is the amount of spam coming in through contact forms. Even though we don’t allow ‘nobody’ mail through the php mail() function and we provide the best server-side spam filters available, local mail cannot be filtered or limited. In other words, no spam filter in the world is going to save you from your shitty contact form.

I started recommending to our customers to implement MX checks in their forms as spam bots nowadays can easily get past things like captcha and textual confirmations. Spammers rarely send email from valid mail hosts so it’s very easy to filter these out with just a few lines of code:

list($user, $domain) = split(“@”, $email);
if (checkdnsrr($domain, “MX”)) {
} else {


To explain the code a little bit, you’re basically taking your stored email address variable ($email) and using the split() function to single out the domain name into one variable, $domain. When you pass the domain through the checkdnsrr() function, PHP will return either a ‘1’ or ‘0’ result, which is interpreted as either true or false. The above is just the basic code, but you can have it spit out errors as well:

if (checkdnsrr($domain, “MX”)) {
} else {
echo "Invalid email";

The checkdnsrr() function can also be used to check for other records as well, like A, CNAME, NS, etc.

Securing the TMP Partition and Tracking Hacks

Posted by Nessa | Posted in Uncategorized | Posted on 16-11-2007


Are your temp partitions putting out behind your back? Anyone who’s ever administered a Linux server would know the risk of leaving the /tmp directory unsecured, moreso on a webserver that is shared among multiple websites.

The tmp directory is world-writeable and used by a majority of services on a machine — including the storage of PHP and MySQL session files. One issue that I’ve seen on older servers is that one customer’s poorly-coded website would get exploited and end up downloading a file into the /tmp directory, then have that hack file executed on the server as a nobody-owned process. Hack processes are the easiest to find, as they always have a little something extra.

This should go without saying, but hack processes can run from almost anywhere, not just /tmp. I’m mainly bringing up the tmp directory because it’s the most targeted location for hack files if it isn’t secured properly.

Identifying Hack Processes

To start out, log into your server as root as issue the following command to see all the nobody-owned processes running on the machine. This is assuming that Apache on your webserver runs as ‘nobody':

root@localhost[~] ps -efw |grep nobody |more

A majority of the output will reflect legitimate Apache processes:

nobody 8748 25841 0 21:35 ? 00:00:00 /usr/local/apache/bin/httpd -DSSL
nobody 8785 25841 0 21:35 ? 00:00:01 /usr/local/apache/bin/httpd -DSSL
nobody 8988 25841 0 21:36 ? 00:00:00 /usr/local/apache/bin/httpd -DSSL

You’ll see that they all have the same parent process ID of ‘25841’ and all of the commands look about the same. However, you may see something that looks like this:

nobody 15707 26407 0 11:18 ? 00:00:00 [sh <defunct>]
nobody 15717 1 0 11:18 ? 00:00:04 /usr/bin/perl
nobody 13016 1 0 14:14 ? 00:00:00 /usr/bin/perl

nobody 8988 1 0 21:36 ? 00:00:00 /usr/local/apache/bin/httpd -DSSL -d3

All of these are hack processes. A few things to look for:

– Perl and shell (sh) processes on most systems run as the user that is executing them, not ‘nobody’. If this is true on your system, a nobody-owned perl process is probably a hack

– The parent ID of the process is different than all the others of the same service — these can be easily faked

– For Apache, an extra little switch on the end of the command (../httpd -DSSL -d3) – ‘d3′ is usually the name of the hack file that is being executed through Apache (not always).

Now I know you probably have the urge to kill -9 it, but don’t. Killing a hack process before determining what it is or where it came from is only going to let it happen again.

Tracking the process:

Once you know which processes should not be running, you need to know where they came from. The *easiest* way to track a process is through the lsof command. If you take the process ID (not the parent) and run an lsof it will tell you everything you want to know:

lsof -p 8748

From here I can see that this process is running from a folder in a user’s account. All I need to do now is kill it off, then remove the hack files from that user’s directory and let them know to update their shit.

TMP Directory Hacks

I’ve seen my fair share, but many hack processes will be spawned from the temp partitions of the server (like /tmp, /tmpDIR, /dev/shm), as these are usually set to 777 to allow programs to store their temporary files. When you first look in your TMP directory you’re going to see a lot of stuff — this is normal, but you’ll want to look for nobody-owned files that stand out. Just a hint, some hacks will try to trick you with their names. I have seen many that are named “…” or “httpd” to make them look legitimate, but I know that httpd (the service that runs Apache) should not be in the tmp directory…and that’s what makes it stand out.

Securing the tmp Partition

I’m not going to go too far into this here, because there’s already a very sexy website with this information available.

If you are on a cPanel server, you should run /scripts/securetmp in addition to following the instructions above.

How to Make Your System Admin Mad by Creating Huge-Ass Files

Posted by Nessa | Posted in Uncategorized | Posted on 31-10-2007


So If you’ve ever woke up in the morning and asked yourself…”Hmm, how can I make my system admin’s job harder to the point where they get mad and shut down my server?” Well, lucky for you I can answer that question. All you have to do is use the ‘dd‘ command to write a 120gb file to an 80gb hard drive. That’s a winner.

By ‘dd’ I’m not talking about my bra size, people. It’s sad, but we recently had an over-curious customer try to see what would happen if the hard drive filled up on his dedicated server. You know what happens when you flush a clogged toilet? Yea….

So here’s the command:

dd if=/dev/zero of=test bs=1024 count=125829120

This command will write a 120gb file directly to the disk. ‘of’ specifies the name of the output file, while ‘bs’ represents the size of a block and ‘count’ is how many blocks to create. Really, it’s a dangerous thing to do if you don’t know what you’re doing. Generally the only time I do this is when I’m testing large file support for servers and PHP.  Nevertheless, the sheer curiosity of ignorant users is enough for me to pull the power plug on a server.

Using PHP to Display Version Info – Part II

Posted by Nessa | Posted in Uncategorized | Posted on 17-10-2007


Earlier I showed some examples of commands you can use to pull software versions into a simple PHP script. In the next example I’ll show how to do the distro and kernel versions. I’m sure that there’s a much simpler way to do this (i.e. a simple cat command on the /proc/version file), but I figured I’d use a more advanced example in the form of a function. I did the distro as a variable to show how easy this is:

function kernelinfo () {
$buf = exec( 'cat /proc/version');
if ( $buf == "ERROR" ) {
$result = "N.A.";
} else {
if (preg_match('/version (.*?) /', $buf, $ar_buf)) {
$result = $ar_buf[1];

if (preg_match('/SMP/', $buf)) {
$result .= ' (SMP)';
return $result;

$distro = exec('cat /etc/redhat-release');

$kernel = kernelinfo();

echo $distro;

echo "<html><br></html>";

echo $kernel;


This will show a result of the following, obviously various depending on your platform:

CentOS release 4.5 (Final)
2.6.9-023stab033.9-enterprise (SMP)

Keep in mind that this script (as the last) requires the ability to pass shell commands through PHP. So, you would need to be able to the exec function, or replace it with system, passthru, escapeshellcmd, or shell_exec if those are allowed in your php.ini configuration. Also, if you run PHP as an Apache module, this will not work if you have open_basedir protection enabled.

cPanel Backup Cron Support for x3 ?

Posted by Nessa | Posted in uncategorized | Posted on 22-07-2007


Since cPanel 11 came out I’ve been getting a ton of emails from people who are currently using my cPanel Automated Backup script asking if it’s compatible with the x3 theme. If your host is using cPanel 10 or 11 running on monsoon, x, x2, or x3, the script will work. You just have to make sure you have the theme set right in the config:

$skin = “x3″;

Installing Sphinx for MySQL 5.1

Posted by Nessa | Posted in Uncategorized | Posted on 21-07-2007


This is probably one of the two things that drove me crazy over the last two weeks. The first was trying to get cPanel to stop being such a MySQL nazi, the second was getting Sphinx installed into MySQL 5.1 for one of the clients. I’ve installed it with 5.0 on Ubuntu before, but 5.1 with cPanel can be pretty torturous. After talking to the developer who was able to fill in the blanks, I’ve decided to write my own documentation on how to install Sphinx as a dynamic MySQL plugin for an existing MySQL 5.1 installation.

Before we start...

You need MySQL 5.1 installed to use the plugin feature. If you’re running on cPanel or other version-dependent software it’s a really really bad idea to install MySQL from source, so you’ll probably want to read this as a guide to upgrading via RPM. Also, this walkthrough is specific to MySQL 5.1.20 (beta), since that’s the latest release out at the time of this writing.

You also need to have root access, and a decent knowledge of Linux and MySQL.

Download the Sphinx binaries and MySQL 5.1.20 patch:

tar -xvzf sphinx-0.9.7.tar.gz
cd sphinx-0.9.7/mysqlse/

patch -p1 < sphinxse097-mysql5120.patch

I should point out that Andrew Aksyonoff (the developer) provided that patch to make Sphinx compatible with MySQL 5.1.20, but you’d probably have to check back on his site for version ugprades and such, esp. for newer versions of MySQL.

Now download the MySQL 5.1 sources — these are only going to be used to compile the Sphinx module:

cd /usr/src
tar -xvzf mysql-5.1.20-beta.tar.gz
cd mysql-5.1.20-beta
cp -Rf /usr/src/sphinx-0.9.7/mysqlse/ storage/sphinx

Compile the Sphinx module against the MySQL 5.1 sources, but don’t install:


If you look in storage/sphinx/.libs you’ll see the loadable .so files that can plug in to MySQL easily. I suggest you copy them into a more permanent location:

mkdir /var/lib/mysql/plugins
cp storage/sphinx/.libs/ha_sphinx.* /var/lib/mysql/plugins

Now add this line to /etc/my.cnf and restart mysql:


To install, log into the MySQL root and issue the ‘INSTALL PLUGIN’ command:

mysql -u root
mysql> INSTALL PLUGIN sphinx SONAME '';

To verify its installation, just run the ‘SHOW ENGINES’ command:

mysql> show engines;
| CSV | YES | CSV storage engine
| SPHINX | YES | Sphinx storage engine 0.9.7

If you need further info, check out the doc-u-men-ta-tion.

Creating your Own “Access Groups” In Linux

Posted by Nessa | Posted in Uncategorized | Posted on 22-05-2007


We started cracking down a bit on system binaries being executeable by end users on our shared hosting servers, which consisted of chmod-ing things like ‘wget’ to 700 so only root users have access. If you’re on shared host, it’s likely that you’ve encountered this kind of restriction before, and if you’re a server admin you probably know why this is necessary.

A typical scenario I’ve seen in many cases is some user’s crappity software gets exploited and executes the ‘wget’ command to download hacks and warez onto the server. I’ve also seen typical Linux functions be abused by hack processes because the access was not being controlled — it’s only safe to say that certain system binaries should be restricted to only trusted users….programs that I find particularly pervious to hacks are those like wget, lynx, scp, sh, and exec.

The issue with this (and the point of this article) is that if you suddenly disable these functions you’ll probably find yourself with a dozen complaints from your users who were using them. I’m all about fairness, so I’m not about to tell someone to rewrite their scripts because of a server-side change. Instead, I created a group on the server and added those users to be able to have access to what they needed, and chgroup-ed the binaries to that group.

I’ll use the wget example first. Say you have ‘user1‘ and ‘user2‘ that both need to be able to use wget, which is currently set to root:root 700. You’ll need to first create a file called ‘’ and insert this script:

if [ $# -ge 2 ]; then
if [ $UID == 0 ]; then
egrep ^$1 /etc/group > /dev/null
if [ $? == 0 ]; then
while [ $# -gt 0 ]; do
echo $GROUPNAME `groups $CURRENT` |sed 's/.*: //g' | sed 's/ /,/g' | usermod -G `cat -`,$GROUPNAME $CUR$
echo "the group $1 does not exist."
echo "you must be ROOT to run this script."
echo "usage: $0 grp usr1 [usr2 ... usrN]"

I know, I know, you’re probably asking why I dont use useradd +G or something like that. I tried, but in this case those commands are not appropriate. Anyways, go ahead and create your group:

root@vps [~]# groupadd wgetters

Now, simply run the script and add your users to that group:

root@vps[~]# sh wgetters user1 user2

Run id user1 to make sure that user was added to the group — you should see something like this:

uid=32010(user1) gid=32012(user1) groups=32012(user1),32014(wgetters)

Now if you chown the wget binary to root:wgetters / 750 , then only the users in that group can use wget, and their actual group identity would be unaffected.

It wouldn’t hurt mentioning that wget is often unnecessary, as many scripts can be run other ways:

php -q scriptname.php

perl scriptname.cgi


lynx (assuming that you have lynx enabled)

Make Apache Faster

Posted by Nessa | Posted in Uncategorized | Posted on 09-05-2007


Apparently someone thinks that my website is too slow in its load time. I never really thought it was that bad, but his little handy danty Firefox plugin claims that it takes my site approximately 6-7 seconds to load initially, which kinda sucks. I know that I’ve written some stuff on optimizing php performance and I tell customers on a daily basis how to keep their sites from bogging down our servers, but I never really cared to optimize my own site because I have a v-dedicated server. So anyways, I’ve made a few modifications to both my site and the server environment to help speed things up a bit.

You might want to read my article on Optimizing PHP as well.

Enable Compression with Apache

If you are running on Apache 2, mod_deflate should already be installed on your system — all you have to do is enable it. I recently downgraded my server back to Apache 1.3.37 (mainly because of cPanel) so I’m using the mod_gzip alternative. Basically, mod_gzip compresses the contents of your site server-side and then passes the file onto your compression-enabled browser to decompress the file. The overhead on the server may be slightly higher during heavier traffic times, but you’ll find yourself saving bandwidth and load time since the server is passing less data between it and your clients.

To install mod_gzip on Apache:

tar -zxvf mod_gzip-
cd mod_gzip-

If you’re on a cPanel system, you’ll need to modify the path to apxs:

pico Makefile

Change APXS?=/usr/local/sbin/apxs to APXS?=/usr/local/apache/bin/apxs

Then just do the normal make && make install

Now enable the dynamic modules in the Apache config:

pico /usr/local/apache/conf/httpd.conf

Uncomment out these lines:

#LoadModule gzip_module libexec/
#AddModule mod_gzip.c

Now all you need to do is restart Apache as normal. To see if compression is working on your site, just hop on over to this page and run the test.

Change The KeepAliveTimeout

By default your Apache configuration will probably have keep connections alive for up to 15 seconds before they die off. For busier sites this can be a little too long. I suggest setting this to 3 or 5 seconds in your httpd.conf.

Adjust the PHP Output Handler

Your PHP scripts are constantly recompiiling themselves every time a page is loaded. If your site is heavily reliant on PHP, you may find it beneficial to have PHP send its output to a compression function in your php.ini

output_handler = ob_gzhandler

Check Your resolv.conf

It’s obvious that your settings are fine if your site and email are working, but your resolver may not be set to do the fastest lookups. If you have a caching or local nameserver, you will want that listed first in /etc/resolve.conf . I’ve seen a drastic decrease in performance on some customer VPS’s because the servers were doing DNS lookups through external nameservers. I have dedicated nameservers, so my resolve.conf looks like this:



One of the major changes I made on my site was to the image and page sizes… I did a lot of code and image compression to decrease the amount of time it takes to load my site. A majority of this consisted of simply saving my images in .gif or .png formats and removing plugins and includes that were not needed.

Suhosin Will Make your PHP Hard

Posted by Nessa | Posted in Uncategorized | Posted on 20-04-2007


SuhosinI noticed a vague mention of Sohosin on a PHP blog that I read on occasion and I decided to give it a whirl to see if it’s as sexy as is sounds. So far my server hasn’t crashed, so I’m willing to recommend it to anyone who’s interested in hardening their PHP. Ok, sorry. I really can’t say that without chuckling. Yes, welcome back to third grade.

If you check out the developer’s site you should pretty much get the idea of what it does, but basically closes some of the security holes that we see with PHP all the time. Not to say that it will make your php 4.3/MySQL3/globals on/port 22 open server any more secure, but if you’re running any of the latest stable security releases you might be somewhat interested.

I’m currently running PHP 5.2.1, which is the latest release of PHP5 at the time of this writing. You can essentially install this on any PHP4+ server that you have root SSH access to. I opted to install the DSO, as I absolutely hate recompiling PHP. Installing Suhosin as a dynamic shared module will not require you do recompile anything, and is therefore the preferred method for lazy people.

Note: I’m using the latest (and only) release at the time of my writing, but head over to the download page to see if there is anything newer:

cd /usr/src
tar -xvzf suhosin-0.9.20.tgz
cd suhosin-0.9.20

Now to install:

make install

It should return a line something like this:

Installing shared extensions: /usr/local/lib/php/extensions/no-debug-non-zts-20060613/

Now, all you have to do is add this line to your php.ini and restart Apache. Of course, the path should be what the installation output gave you:


**If you are running eAccelerator, this should be above the eAccerelator configuration

When you load up your phpinfo file you should see the module loaded near the Zend section. Everything should be fine as-is, but it you’re one of those people who has to reconfigure everything, knock yourself out.

Keep People from Jacking your Images

Posted by Nessa | Posted in Uncategorized | Posted on 19-03-2007


I get this question a lot, so I figured I’d post it here. For those of you who don’t have the convenience of a cPanel-based system, you can block image hotlinking in your .htaccess. Image hotlinking is basically when someone uses an image from your website on their site, but has your site in the <img src..> tags (instead of their own site) so the image loads remotely, and therefore sucks up your bandwidth and resources.

Load up the .htaccess file in your website root (public_html or www folder, usually) and add these lines anywhere in the file:

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^*$ [NC]
RewriteCond %{HTTP_REFERER} !^$ [NC]
RewriteCond %{HTTP_REFERER} !^*$ [NC]
RewriteCond %{HTTP_REFERER} !^$ [NC]
RewriteCond %{HTTP_REFERER} !^*$ [NC]
RewriteCond %{HTTP_REFERER} !^$ [NC]
RewriteCond %{HTTP_REFERER} !^*$ [NC]
RewriteCond %{HTTP_REFERER} !^$ [NC]
RewriteRule .*\.(jpg|jpeg|gif|png|bmp)$ [R,NC]

I’m using my two sites, and it’s parked domain, These are sites that I want to allow to display my images. Please note that with Apache, w’s and https matter. So if you have hotlink protection set for and someone accesses your site via or www., they will not be able to see the images unless your allow them as a referrer. Same goes with your subdomains.