Archive for the ‘Geek Cred’ Category

Reduce Attacks on Apache+PHP

Sunday, April 20th, 2008

A couple of days ago I thought that one of my servers got compromised. I thought someone cracked my password by brute force and kept shutting down Apache at 4AM. As it turned out, I made a mistake with the log rotation configuration that the post-rotation restart fails to start Apache.

I immediately installed DenyHosts, disabled keyboard-interactive login and hardened the firewall. It made me feel more insecure which resulted into today’s post.

With a fresh install of FreeBSD 7 on another server yesterday, I wanted to make sure that I do it properly from the start this time.

Apache adds the Server header that reveals the OS, version and some modules. PHP also adds an X-Powered-By header that shows the version of PHP. With those information publicly available, someone can write a script that could exploit vulnerabilities on specific versions of Apache and/or PHP.

For Apache, you can use mod_security. It’s available as a port and at Karanbir Singh’s yum repository for CentOS users. See the directive below.

<IfModule security_module>
  SecServerSignature "Apache"
</IfModule>

Also, just to be a happy camper, I used a new configuration file to be included. Consult your configuration for the path. On CentOS, the default configuration directory is at /etc/httpd/conf.d. On FreeBSD, it’s at /usr/local/etc/apache[n]/Includes, where n may be your Apache version.

For PHP, simply set expose_php to off in your php.ini

Disclaimer: This works for me but I’m not sure if this is the best way to do it. I tried mod_headers first but it didn’t work.

Insert to Asterisk’s Queue Log When a Member Is Called

Friday, April 4th, 2008

Asterisk’s queue_log can come in handy in many cases (queues in Asterisk can be called ACD). There are systems that go as far as depending solely on the queue_log to operate (including mine).

Every now and then requests requirements for a feature to tell if a call in the queue is being transferred to a queue member (an agent) comes up. I had a workaround that used an AGI script but it didn’t work all the time. I’ve been digging around the source code so that it’s inserted into queue_log instead. After three attempts of hacking one friggin’ line of C code, I finally did it. My sincerest apologies to my COMPRO1 and COMPRO2 professors.

You may get the patch for asterisk-1.4.19 over here.

P.S. I know that watching the queue_log isn’t much of a good idea. I only stole the concept and I wasn’t aware of AMI at that time. Migration plans are on the way.

SSH Profiles with myssh

Thursday, November 15th, 2007

I have a hard time remembering IP addresses of the servers I maintain. Some of them are connected to a specific network only (meaning it’s possible to have two machines have the same IP address). To make it easier for me, I wrote some scripts to do all almost all the memorizing for me.

Download the files, extract and copy myssh* to /usr/bin and you’re good to go. To add a host, use myssh_write:

myssh_write yourlabel somehost someuser 22

The user and port are optional. They default to your username and port 22 respectively.

To connect to somehost, use myssh:

myssh yourlabel

You can make it even easier by adding an alias to your bashrc, alias ssh='myssh', and using SSH keys.

Download: myssh.tar.gz

P.S. I wrote the two scripts in PHP. I have a hundred reasons to do this in Python but I just got too lazy to experiment. I’ll have it ported next week.

Migrating to Python

Saturday, November 10th, 2007

I’m thinking of moving a part of my pet project to Python. I was hoping to learn Python before the year ends. Maybe I could speed it up by going directly to application and browsing through manuals. I’ll use Tkinter instead of wxPython. Here’s what I’m planning to do:

  • A desktop client app
  • Should work with my current XHR pages
  • Safely authenticate
  • Release binary versions for Windows
  • Handle distribution (maybe some sort of automatic update notification thing?)

Yes, I’ll be leaving AJAX/XHR mainly because I’m having a hard time debugging several parts. Specially that Firefox (or my extensions) becomes sluggish and unresponsive. Also, I find Javascript a bit limiting.

In short, I’m chickening out on Javascript. By the way, is it just me that accidentally pronounces Tkinter like it was Tay-kinter?

Walis: Some sort of batch script thing

Saturday, September 15th, 2007

Ever tried deleting a bazillion of files in one directory and got an “Argument list too long” error?1 Find too slow?2

A long time ago, I wrote a short script that solved these kind of problems. I call it Walis (broom or sweep in Filipino). This script will recursively scan a directory and output the files with your command (and even add output redirection).

To use this script to delete the files, type walis /some/path "rm -f" | sh. To move files in separate directories into one, type walis /some/path "mv " /another/path/ | sh.

The script is very simple. You can modify it to check a file’s timestamp or do some string manipulation (useful for renaming).

I’m too lazy to take a look at bash so this is written in PHP. You just need the command line version of PHP to get this to work.

[Download]

1 We found log files that averaged in 4KB in size. They were dumped in several subdirectories and rm -rf couldn’t do it.
2 Tried find to delete old log files but it was so slow that it would’ve taken 3 months to complete the task. But an application was spitting out logs at a rate so fast, it would fill up the partition in a month.

Load Balancing Two MySQL Servers for PHP Applications

Monday, June 18th, 2007

My “research” on clustering and replication was just timely. I had to find a fix for an overloaded server. I could’ve just rewritten the code but I wanted to try something new first. I found out that a MySQL cluster needs to have at least three servers to get full redundancy. Replication was my only choice because I only have two servers for this application and the queries that are producing the most load are select queries.

MySQL replication works by having a master server where all the inserts, updates and deletes (basically any writing done) and one or more slave servers that polls the master server to replicate the database. You can only issue select queries to the slave server. You can also have multiple master servers but it won’t be covered here. You can follow this article to setup replication.

I’ll be using Round Robin to balance the load since I’ll be load balancing for a separate portion only where the same queries are used. This will equally split the load to each server (…almost). To do this in PHP, I wrote a very simple script that opens a socket. Once a host connects, it tells which database server to connect to and immediately terminates the connection.

#!/usr/bin/php -q
<?php
// Bind and listen
socket_bind($stream, "127.0.0.1",3307);
socket_listen($stream, 100);

// Define DB login credentials in an array
// host|user|passwd
$hosts = array(
0 => array('db1.dbservers.net','someuser','somepass'),
1 => array('db2.dbservers.net','anotheruser','anotherpass'),
/***** if you add another host (just follow the drift) *****/ 
// 2 => array('db3.dbservers.net','yetanotheruser','yetanotherpass') 
);

// Loop forever
while(true)
{
	// Accept anyone
	$client = socket_accept($stream);
	$key = key($hosts);
	$reply = implode($hosts[$key], "|");

	// Move internal pointer to next host
	if(next($hosts) === FALSE)
		reset($hosts);

	// Push response then kill the connection
	socket_write($client, $reply);
	socket_close($client);
}
?>

This script should be called from the command line and run like a daemon. Then we modify how we connect to the database. We connect to the “daemon” and catch the login information.

<?php
// Connect to load balancer daemon
$fp = fsockopen("localhost", 3307);

// Fallback and use some host in case of failure
if(!$fp)
{
	$host = "localhost";
	$user = "someuser";
	$pass = "somepasswd";
}
else
{
	// Get DB login information
	$packet = fgets($fp);
	$account_details = explode("|", $packet);
	$host = $account_details[0];
	$user = $account_details[1];
	$pass = $account_details[2];
}

// Connect
$link = mysql_connect($host,$user,$pass);
if(!$link)
{
	die("Fatal Error: Can't connnect to database\n");
}
mysql_select_db("somedb",$link);
?>

The code above can be improved further to check if a host is still up, give weights on the server depending on its hardware and other bells and whistles.

The beauty of this is you can safely change to another algorithm like Weighted Round Robin or Job Informed and all of the code that has to be changed is in the daemon. You may learn more on other algorithms from the paper by Dennis Haney and Klaus S. Madsen.

I’m looking into venturing to a Job Informed algorithm once the whole application uses load balancing. Queries will have weights then some form of load estimation can be achieved. Query analysis is also a possibility (based on subqueries, query type, constraints ,etc).

Changed Goals

Saturday, May 26th, 2007

I’m lowering the bar from the last time I posted my latest goal.

I couldn’t sleep last night so I got up and started playing around with XUL. It was fun. I’m moving GTK and wxWidgets a couple of notches down and shifting to Python then XUL+XHR. I went to bed around 6AM.

I was thinking about how much I accomplished for this month. I did two huge things. I started moving parts of my code and new parts to object oriented PHP. Also, I’m now playing with Asterisk’s manager (I know. I’m ancient. I have to catch up with AJAM).

Back to XUL. It’s pronounced as zool (rhymes with cool). It’s short for XML User Interface Language. It’s like Microsoft’s XAML (rhymes with camel) but almost limited to forms.

Its advantage over XAML is it’s cross-platform with XULRunner (Windows, OSX and Linux). It can also run on any Gecko-based browser [as of this post's writing]. XAML, on the other hand, runs only on Windows and that would suck because not all of my users don’t use Windows.

I figured that I wouldn’t really need the fancy graphics and 3D effects that XAML offers. Maybe someday when we get holographic displays.

I was going to end this post but I got tempted to make fun of Microsoft’s branding. In my honest opinion, XMLHttpRequest and XAML are one of the best things that MSFT came up with. But man, do they suck at branding! XHR is way cooler. XUL almost sounds like zune (that brand generated a lot of buzz)! They’re lucky enough I didn’t rearrange XAML to LAMX (rhymes with lame-ksssss).

Just like sex, a three-letter abbreviation is the cool thing to have nowadays. Oh well. Can’t blame them for trying to be different.

Another Note to Self

Friday, April 20th, 2007

To have a link that does nothing, use javascript:void(0);. javascript: works but it causes the error console in Firefox to pop up.

Why use a link that does nothing? If you don’t want the status bar to show long javascript lines and use the onClick event attribute. Yes, that’s just it (aesthetic purposes).

It’s funny how I solved this before and completely forgot about it the other night. I was hitting refresh and clicking the link for 4 hours, hoping that it would work as expected.

Raising My Geek Cred

Monday, March 19th, 2007

Just to make sure that you don’t get the impression that all I do is play games, I’m starting a new category with geekier stuff. I was hesitant to do this because I’ll be reposting stuff from other sources.

Let me start with something simple. I’ve been playing around with Javascript for more than 5 years already. Okay, maybe not 5 years, I stopped caring about Javascript when I got into college (circa 2003) and moved most of the processing to the server when I learned PHP. AJAX became popular and I’m back to distributing that load.

For those who were used to the pre-DOM/AJAX era, you’ll notice that window.onload or the onLoad event attribute doesn’t work as it used to. This is how it is done for browsers that use Gecko (Firefox et al):

if(document.addEventListener)
document.addEventListener(”DOMContentLoaded”, myFunc, false);

This will call the function myFunc() after the page has loaded.

I wouldn’t want to bore you with more code (in other words, too lazy to type further). For the rest of the browsers and more explanation, you can learn more from here.