≡ Menu

lighttpd

Now, mod_fastcgi is configured and running. FastCGI supports connection via UNIX sockets or TCP/IP networking. This is useful to spread load among various backends. For example, php will be severed from 192.168.1.10 and python / ruby on rails will be severed from 192.168.1.11. This is only possible with mod_fastcgi.
[click to continue…]

Debian PHP 5 Security Issues

Debian 5 php5 package has serious security issues as follows:

To prevent Denial of Service attacks by exhausting the number of available temporary file names, the max_file_uploads option introduced in PHP 5.3.1 has been backported.
[click to continue…]

Recently, I had noticed lots of 404 error generated by my wordpress software. My old wordpress tag structure changed from:
/tips/tag/linux_software
/tips/tag/one_two_foo

To:
/tips/tag/linux-software
/tips/tag/one-two-foo

As a result lots of error 404 was dumped into my log file. I wrote a small php code to get rid of the problem:
[click to continue…]

Lighttpd: Enable IPv6 Support

Lighttpd supports both IPv6 and IPv4 protocol out of box. You need to compile lighttpd with IPv6 support. The server.use-ipv6 option bind to the IPv6 socket. You need to bind to both IPv6 and IPv4 using the following syntax.

First, see compile-time features (find out if IPv6 is enabled or not), enter:
# lighttpd -V
Sample output:

Build-Date: Sep 30 2008 06:18:08
Event Handlers:
	+ select (generic)
	+ poll (Unix)
	+ rt-signals (Linux 2.4+)
	+ epoll (Linux 2.6)
	- /dev/poll (Solaris)
	- kqueue (FreeBSD)
Network handler:
	+ sendfile
Features:
	+ IPv6 support
	+ zlib support
	+ bzip2 support
	+ crypt support
	+ SSL Support
	+ PCRE support
	- mySQL support
	- LDAP support
	- memcached support
	- FAM support
	- LUA support
	- xml support
	- SQLite support
	- GDBM support

You must see + IPv6 support enabled. If not recompile lighttpd with IPv6 support. Once compiled open lighttpd.conf file:
# vi lighttpd.conf
To enable IPV6 and IPV4 together, enter:

server.use-ipv6 = "enable"
server.port = 80
$SERVER["socket"] == "0.0.0.0:80" {
# add your stuff
#
}

Save and close the file. Restart lighttpd:
# service lighttpd restart

Above config is only useful if you want to use all available IPv4 and IPv6 address. Following configuration will bind IPv4 to 202.54.1.10 and IPv6 to address:
Open lighttpd.conf setup main server IP address as follows:

server.port = 80 
server.bind = "202.54.1.10"

Below that add IPv6 config as follows:

$SERVER["socket"] == "[2001:470:1f04:55a::2]:80" {
   # ...
   # your rest of config for ipv6 host
   # ...
}

Here is my sample config file with IPv4 and IPv6 dual stack enabled:

server.modules              = (
                               "mod_redirect",
                               "mod_alias",
                               "mod_rewrite",
                               "mod_expire",
                               "mod_access",
                               "mod_auth",
                               "mod_status",
                               "mod_fastcgi",
                               "mod_accesslog",
                               "mod_compress"
)
 
server.errorlog            = "/var/log/lighttpd/error.log"
accesslog.filename         = "/var/log/lighttpd/access.log"
index-file.names            = ( "index.php", "index.html", "index.htm", "default.htm" )
server.tag                 = "lighttpd"
 
# FastCGI php5
fastcgi.map-extensions = ( ".html" => ".php" )
fastcgi.server    = ( ".php" =>
        ((
                "bin-path" => "/usr/bin/php-cgi",
                "socket" => "/tmp/php-cgi.socket",
                "max-procs" => 4,
                "idle-timeout" => 30,
                "bin-environment" => (
                        "PHP_FCGI_CHILDREN" => "10",
                        "PHP_FCGI_MAX_REQUESTS" => "20000"
                ),
                "bin-copy-environment" => (
                        "PATH", "SHELL", "USER"
                ),
                "broken-scriptfilename" => "enable"
        ))
)
 
include "mimetype.conf"
 
server.document-root = "/home/lighttpd/example.com/http"
server.pid-file = "/var/run/lighttpd.pid"
server.username = "lighttpd"
server.groupname = "lighttpd"
 
# Turn on IPv4 config
server.port = 80 
server.bind = "202.54.1.10"
 
server.error-handler-404 = "/index.php?error=404"
 
### IPv6 Config ###
# Note only log file name changed
$SERVER["socket"] == "[2607:f0d0:1002:11::5]:80" {
	accesslog.filename         = "/var/log/lighttpd/ipv6.access.log"
	server.document-root = "/home/lighttpd/example.com/http"
	server.error-handler-404 = "/index.php?error=404"
}

It appears that latest php version 5.1.6-20.el5_2.1 under RHEL / CentOS Linux v5.2 has made some major changes. As a result choort jail setup using previous instructions no longer works.

PHP is crashing with segmentation fault errors. So I had to trace php errors using strace command. After spending couple of hours I found solution for following errors:

Sep 15 03:26:59 lightyproxy kernel: php-cgi[19106]: segfault at 0000003151c1b4b8 rip 0000003151e98477 rsp 00007fff9ecdde20 error 6
Sep 15 03:26:59 lightyproxy kernel: php-cgi[19107]: segfault at 0000003151c1b4b8 rip 0000003151e98477 rsp 00007fff9ecdde20 error 6
Sep 15 03:26:59 lightyproxy kernel: php-cgi[19108]: segfault at 0000003151c1b4b8 rip 0000003151e98477 rsp 00007fff9ecdde20 error 6
Sep 15 03:26:59 lightyproxy kernel: php-cgi[19110]: segfault at 0000003151c1b4b8 rip 0000003151e98477 rsp 00007fff9ecdde20 error 6
WARNING! These examples / workaround is only for RHEL / CentOS 5.2 and not for Debian / Ubuntu / FreeBSD lighttpd chroot instructions.

You need to copy entire /etc/ and /usr/share/zoneinfo/ to jail. If your jail is located at /jail directory enter following commands:
# service lighttpd stop
# D=/path/to/chroot/jail
# mkdir /root/jail.etc
# /bin/cp -avr $D/etc/* /root/jail.etc
# /bin/cp -avr /etc/* $D/etc/

Copy back original customized files such as passwd, group, php.ini :
# cp -avr /root/jail.etc/* $D/etc/
Now copy /usr/share/zoneinfo/:
# cd $D/usr/share
# cp -avr /usr/share/zoneinfo/ .

Copy all latest php-cgi and all extensions to $D
# cd $D/usr/bin
# cp /usr/bin/php-cgi .
# l2chroot php-cgi

Copy php modules (for 64 bit use $D/usr/lib64):
# cd $D/usr/lib/
# cp -avr /usr/lib/php/ .
# cd php/modules
# for l in *.so; do l2chroot $l; done

Start lighttpd:
# service lighttpd start
This should fix all errors. Watch /var/log/messages for php errors:
# tail -f /var/log/messages

This is 3rd and the final installment for Urchin 6 web analytics software series. Once Urchin is installed, you need to configure tracking on your website. You need to install Urchin sensors - a small piece of javascript tracking
code on each of your website's pages. Usually all large site uses some sort of templating (themes) system.

Step # 1: Copy UTM files to webroot

You need to copy or softlink urchin.js and __utm.gif file to webroot from /usr/local/urchin/util/utm directory. If your webroot set at /home/lighttpd/cyberciti.biz/, enter:
# cp -v /usr/local/urchin/util/utm/* /home/lighttpd/cyberciti.biz/
Set appropriate file permissions:
# chown apache:apache /home/lighttpd/cyberciti.biz/urchin.js
# chown apache:apache /home/lighttpd/cyberciti.biz/__utm.gif

Step # 2: Add tracking HTML JS code in the HEAD section

On each page of your website, place the following tracking code right after the any META tags in the HEAD section:

<script src="/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
  _userv=0;
  urchinTracker();
</script>

Also make sure each website or profiles set to Urchin Traffic Monitor (UTM) as the visitor tracking method.

Step # 3: Make sure Apache logs data with cookies

You need to enable cookies in your Apache logging, add following code your httpd.conf file:

LogFormat "%h %v %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{Cookie}i\"" urchin

Find your domain <VirtualHost> entry for which you wish to enable this new logging format. Deactivate any existing TransferLog or CustomLog entries within a . Then insert the following new CustomLog entry, replacing the string path_to_log with the appropriate path to your log location:
CustomLog /var/log/httpd/cyberciti.biz/access.log urchin

A note about lighttpd web server

If you are using Lighttpd add following code to you lighttpd.conf file:

accesslog.format = "%h %v %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{Cookie}i\""

Save and close web server configuration file. Restart the server:
# service httpd restart
OR
# service lighttpd restart

How do I view reports?

Login to your account by visiting urchin admin url:
https://your.server.com:9999/
Click the Go To Report button to the right of each Profile Name to launch the reporting window for that Profile. The reporting window will allow you to view all available reports for the Profile i.e. website. Here is a sample report:

Fig.01: Urchin 6 Sample Report

Fig.01: Urchin 6 Sample Report (click to enlarge)

Conclusion

This series has shown you how to install and configure Google Urchin 6 under Red Hat Enterprise Linux 5.x. I suggest reading following section for more information.

Further readings:

There is a way to protect different directories with different username/password under Lighttpd server.

If you use different userfile files for authenticating in different directories, you can attach each to the correct directory by using conditionals.

Let us see how to protect two different directories using conditionals directives:
/docs/ with username tom
/sales/ with username jerry

Open lighttpd configuration file:
# vi lighttpd.conf
Make sure mod_auth is loaded:
server.modules += ( "mod_auth" )
Now add first conditionals directive to protect /docs/:

$HTTP["url"] =~ "^/docs/" {
auth.backend = "plain"
auth.backend.plain.userfile = "/home/lighttpd/.lighttpdpassword-DOCS"
auth.require = ( "/docs/" =>
 	(
	"method" => "basic",
	"realm" => "Password protected area",
	"require" => "user=tom"
	)
   )
}

Add second conditionals directive to protect /sales/:

$HTTP["url"] =~ "^/sales/" {
auth.backend = "plain"
auth.backend.plain.userfile = "/home/lighttpd/.lighttpdpassword-SALES"
auth.require = ( "/sales/" =>
 	(
	"method" => "basic",
	"realm" => "Password protected area",
	"require" => "user=jerry"
	)
   )
}

Save and close the file. Now create a password for tom user:
# vi /home/lighttpd/.lighttpdpassword-DOCS
Append username:password for tom:
tom:TomsPassword
Save and close the file. Also, create a password for jerry user:
vi /home/lighttpd/.lighttpdpassword-SALES
Append username:password for jerry:
jerry:JerrysPassword
Save and close the file. Restart lighttpd:
# /etc/init.d/lighttpd restart