Apache : simple authentication and LDAP authentication examples

January 26, 2010 - No comment

Simple authentication :

Users credentials are stored in a file created with htpasswd command

<Location /dir/>
AuthType Basic
AuthName "Authentication"
AuthUserFile /etc/apache2/passwd-file
Require user username1 username2
</Location>

If we want to allow all users in passwd-file, use :
Require valid-user

LDAP user authentication :

We allow user1 and user2 found in the branch ou=People,dc=domain,dc=tld

<Location /dir/>
AuthName "Authentication"
AuthType Basic
AuthBasicProvider ldap
AuthzLDAPAuthoritative on
AuthLDAPURL ldap://127.0.0.1/ou=People,dc=domain,dc=tld
Require ldap-user user1 user2
</Location>

LDAP group authentication :

We allow all users in the group “support”, users are defined in that group under the memberUid field

<Location /dir/>
AuthName "Authentication"
AuthType Basic
AuthBasicProvider ldap
AuthzLDAPAuthoritative on
AuthLDAPURL ldap://127.0.0.1/ou=People,dc=domain,dc=tld
AuthLDAPGroupAttribute memberUid
AuthLDAPGroupAttributeIsDN off
Require ldap-group cn=support,ou=Groups,dc=domain,dc=tld
</Location>

Combination of users and group :

<Location /dir/>
AuthName "Authentication"
AuthType Basic
AuthBasicProvider ldap
AuthzLDAPAuthoritative on
AuthLDAPURL ldap://127.0.0.1/ou=People,dc=domain,dc=tld
AuthLDAPGroupAttribute memberUid
AuthLDAPGroupAttributeIsDN off
Require ldap-group cn=support,ou=Groups,dc=domain,dc=tld
Require ldap-attribute gidNumber=10000
Require ldap-user user1 user3 user5
</Location>

See also :

- Conditional web authentication : http://www.wains.be/index.php/2007/01/27/apache-conditional-http-authentication/

- Source for this post : http://www.linux.com/archive/feature/120050?theme=print

Keith in his post is wrong about the “Satisfy Any” option, as explained in Apache documentation : http://httpd.apache.org/docs/2.0/mod/core.html#satisfy :

This directive is only useful if access to a particular area is being restricted by both username/password and client host address. In this case the default behavior (All) is to require that the client passes the address access restriction and enters a valid username and password. With the Any option the client will be granted access if they either pass the host restriction or enter a valid username and password.

He seems to explain that the “Satisfy Any” option is necessary when using several “Require” arguments. That’s incorrect, all Require arguments are evaluated by default and must pass checks to give access to the resource.

Installing TRAC with Apache2 and mod-python on Debian Lenny

January 20, 2010 - 1 comment

This is based on a fresh install.

Install the necessary stuff :

# apt-get install apache2 subversion trac
# apt-get install libapache2-svn

libapache2-svn will enable dav and dav_fs modules.

More stuff :

# apt-get install libapache2-mod-python

Create your directories for TRAC environments (/home/trac/), projects source files (/home/dev/) and SVN repositories (/home/svn/) :

# mkdir /home/{trac,dev,svn}

Create your first project :

# mkdir /home/dev/project1
# echo "<?php phpinfo() ?>" > /home/dev/project1/index.php

Create the SVN repository for the project :

# svnadmin create /home/svn/project1

Import the project into the SVN repository :

# svn import -m "Initial import" /home/dev/project1/ file:///home/svn/project1/
Adding         /home/dev/project1/index.php

Committed revision 1.

Move your sources to a safe place, while we checkout the project :

# mv /home/dev/project1 /home/dev/project1-orig

Checkout the project :

# svn checkout file:///home/svn/project1 /home/dev/project1
A /home/dev/project1/index.php
Checked out revision 1.

Make sure the project is now under revision, you should see a “.svn” directory :

# ls -lah /home/dev/project1
total 16K
drwxr-xr-x 3 root root 4.0K Jan 20 12:42 .
drwxr-xr-x 4 root root 4.0K Jan 20 12:42 ..
drwxr-xr-x 6 root root 4.0K Jan 20 12:42 .svn
-rw-r--r-- 1 root root 19 Jan 20 12:42 index.php

It’s now safe to delete the copy not under revision :

# rm -fr /home/dev/project1-orig/

Set up TRAC for your first project, in bold what you need to specify :

# trac-admin /home/trac/project1 initenv
Creating a new Trac environment at /home/trac/project1

Trac will first ask a few questions about your environment
in order to initialize and prepare the project database.

 Please enter the name of your project.
 This name will be used in page titles and descriptions.

Project Name [My Project]> Project1

 Please specify the connection string for the database to use.
 By default, a local SQLite database is created in the environment
 directory. It is also possible to use an already existing
 PostgreSQL database (check the Trac documentation for the exact
 connection string syntax).

Database connection string [sqlite:db/trac.db]> PRESS ENTER

 Please specify the type of version control system,
 By default, it will be svn.

 If you don't want to use Trac with version control integration,
 choose the default here and don't specify a repository directory.
 in the next question.

Repository type [svn]> svn

 Please specify the absolute path to the version control
 repository, or leave it blank to use Trac without a repository.
 You can also set the repository location later.

Path to repository [/path/to/repos]> /home/svn/project1

Creating and Initializing Project
 Installing default wiki pages
 TracSyntaxColoring imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracSyntaxColoring
 TracChangeset imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracChangeset
 TracWiki imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracWiki
 WikiHtml imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/WikiHtml
 TracRevisionLog imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracRevisionLog
 TracFastCgi imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracFastCgi
 TracTicketsCustomFields imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracTicketsCustomFields
 SandBox imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/SandBox
 WikiMacros imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/WikiMacros
 TracUpgrade imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracUpgrade
 TracBackup imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracBackup
 TracAccessibility imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracAccessibility
 RecentChanges imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/RecentChanges
 WikiDeletePage imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/WikiDeletePage
 TracNavigation imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracNavigation
 TracImport imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracImport
 TracModPython imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracModPython
 TracEnvironment imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracEnvironment
 TracBrowser imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracBrowser
 WikiFormatting imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/WikiFormatting
 TracPlugins imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracPlugins
 WikiPageNames imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/WikiPageNames
 TracNotification imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracNotification
 TracInstall imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracInstall
 TracIni imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracIni
 TracAdmin imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracAdmin
 TracRss imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracRss
 TracLogging imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracLogging
 TracGuide imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracGuide
 WikiStart imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/WikiStart
 TracQuery imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracQuery
 WikiNewPage imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/WikiNewPage
 CamelCase imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/CamelCase
 TracRoadmap imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracRoadmap
 TracLinks imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracLinks
 TracStandalone imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracStandalone
 TracInterfaceCustomization imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracInterfaceCustomization
 TracUnicode imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracUnicode
 InterMapTxt imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/InterMapTxt
 TracPermissions imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracPermissions
 TitleIndex imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TitleIndex
 WikiProcessors imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/WikiProcessors
 InterWiki imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/InterWiki
 TracCgi imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracCgi
 TracTimeline imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracTimeline
 InterTrac imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/InterTrac
 PageTemplates imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/PageTemplates
 TracTickets imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracTickets
 TracSupport imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracSupport
 TracWorkflow imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracWorkflow
 TracSearch imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracSearch
 TracFineGrainedPermissions imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracFineGrainedPermissions
 WikiRestructuredTextLinks imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/WikiRestructuredTextLinks
 TracReports imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/TracReports
 WikiRestructuredText imported from /usr/lib/python2.5/site-packages/trac/wiki/default-pages/WikiRestructuredText
 Indexing repository
 [1]
---------------------------------------------------------------------
Project environment for 'Project1' created.

You may now configure the environment by editing the file:

  /home/trac/project1/conf/trac.ini

If you'd like to take this new project environment for a test drive,
try running the Trac standalone web server `tracd`:

  tracd --port 8000 /home/trac/project1

Then point your browser to http://localhost:8000/project1.
There you can also browse the documentation for your installed
version of Trac, including information on further setup (such as
deploying Trac to a real web server).

The latest documentation can also always be found on the project
website:

http://trac.edgewall.org/

Congratulations

The configuration is stored under /home/trac/project1/conf/trac.ini.

Create the password files for web authentication :

# htpasswd -c /etc/apache2/passwd-trac yourusername

Set up Apache :

# cp /etc/apache2/sites-available/default /etc/apache2/sites-available/projects

# vim /etc/apache2/sites-available/projects
<VirtualHost *:80>
    DocumentRoot /var/www/

    <Directory /var/www/>
        Order allow,deny
        Allow from all
    </Directory>

    ### TRAC Root : http://server/trac or http://server/trac/

        # Rewrite ./trac to ./trac/
        RewriteEngine on
        RewriteRule ^(.*)\/trac$ $1/ [NC]

    <Location /trac/>
        SetHandler mod_python
        PythonHandler trac.web.modpython_frontend
        PythonInterpreter main
        PythonOption TracEnvParentDir /home/trac
        PythonOption TracUriRoot /trac/
        SetEnv PYTHON_EGG_CACHE /tmp
    </Location>

    ### TRAC Login : http://server/trac/*/login
    <LocationMatch ^(/trac/[^/]+)?/login>
        AuthType Basic
        AuthName "TRAC Login"
        AuthUserFile /etc/apache2/passwd-trac
        Require valid-user
    </LocationMatch>

    ### SVN repository : http://server/svn
    <Location /svn>
        DAV svn
        SVNParentPath /home/svn
        SVNListParentPath on

        AuthType Basic
        AuthName "SVN Repository"
        AuthUserFile /etc/apache2/passwd-trac
        Require valid-user
    </Location>
</VirtualHost>

Enable rewrite module :

# a2enmod rewrite
Enabling module rewrite.
Run '/etc/init.d/apache2 restart' to activate new configuration!

Disable the default website :

# a2dissite default
Site default disabled.
Run '/etc/init.d/apache2 reload' to activate new configuration!

Enable the newly configured website :

# a2ensite projects
Enabling site projects.
Run '/etc/init.d/apache2 reload' to activate new configuration!

Restart Apache :

# /etc/init.d/apache2 restart

Make sure Apache can read and write TRAC configuration files.
This is a basic working example but you may want to do something more elaborate involving Set-GID or POSIX ACL.

# chown -R www-data. /home/trac

Now go to http://server/trac, it should rewrite the URL to http://server/trac/ and display a list of available projects.

WALLA ;)

Please let me know if it works for you. Thanks.

Partially based on http://www.willamaze.eu/?p=732

apache2 + webdav + SSL (self signed) on Debian Lenny

July 17, 2009 - 3 comments

Install

Install Apache2 and SSL

apt-get install apache2 openssl ssl-cert

Enable the Apache modules we’ll be using :

a2enmod ssl
a2enmod dav_fs
a2enmod dav

Make sure you find the line “listen 443″ somewhere in /etc/apache2/ports.conf

Create the SSL certificate

mkdir /etc/apache2/ssl
openssl req $@ -new -x509 -days 365 -nodes -out /etc/apache2/ssl/apache.pem -keyout /etc/apache2/ssl/apache.pem
chmod 600 /etc/apache2/ssl/apache.pem

Apache config

mkdir -p /var/www/ssl/webdav/
chown www-data. /var/www/ssl/webdav/
htpasswd -c /var/www/passwd.dav user

Edit /etc/apache2/sites-enabled/000-default like this :

<VirtualHost *:443>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/ssl/

        SSLEngine on
        SSLCertificateFile /etc/apache2/ssl/apache.pem

        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>
        <Directory /var/www/ssl/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>

    # WEBDAV DIRECTORY
        <Directory /var/www/ssl/webdav/>
           DAV On
           AuthType Basic
           AuthName "webdav"
           AuthUserFile /var/www/passwd.dav
           Require valid-user
       </Directory>

        ErrorLog /var/log/apache2/error.log
        LogLevel warn
        CustomLog /var/log/apache2/access.log combined
</VirtualHost>

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/non-ssl/
        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>
        <Directory /var/www/non-ssl/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>

        ErrorLog /var/log/apache2/error.log
        LogLevel warn
        CustomLog /var/log/apache2/access.log combined
</VirtualHost>

Restart Apache :

/etc/init.d/apache2 restart

Access the webdav share :

The webdav share can be accessed by Windows, Linux or Mac machines out of the box.
Under Windows, you may need to have to change a key in the registry though.

Sources :
http://www.howtoforge.com/setting-up-webdav-with-apache2-on-debian-etch
http://longspine.com/node/10

OpenVPN : routing all traffic through the VPN tunnel

July 18, 2008 - 19 comments

I’m really into OpenVPN these days, see my two previous posts about it :

Setting up OpenVPN for your road warriors :
http://www.wains.be/index.php/2008/07/15/a-vpn-for-remote-users-with-openvpn/

Setting up a VPN between two sites :
http://www.wains.be/index.php/2008/06/07/routed-openvpn-between-two-subnets-behind-nat-gateways/

Today : how to route all traffic through the OpenVPN tunnel

On the server side :

First of all, if you want to route all your traffic through the VPN tunnel, you need to turn on IP forwarding (also called routing) and add a masquerading rule on the server (where eth0 is the device connecting you to the internet) :

echo "1" > /proc/sys/net/ipv4/ip_forward

iptables -t nat -A POSTROUTING -s 10.30.0.0/24 -o eth0 -j MASQUERADE

To make routing persistent, see http://www.wains.be/index.php/2006/06/06/enable-ip-forward-under-rhelcentos/

Then, here’s the OpenVPN configuration :

port 10000
proto udp
dev tun
comp-lzo
ca ca.crt
cert server.crt
key server.key
dh dh1024.pem
duplicate-cn
server 10.30.0.0 255.255.255.0
client-to-client
push "dhcp-option DOMAIN local.example.org"
push "dhcp-option DNS 172.16.7.253"
push "redirect-gateway def1"
keepalive 10 120
persist-key
persist-tun
user nobody
group nogroup
log vpn.log
verb 1
chroot /tmp

You can see the option redirect-gateway that is responsible for creating all the routes on the client computer when the connection is set up.

The two other push options are only taken into account by Windows clients (to my knowledge).
If you want to change the DNS resolution of your linux clients, you need to use the up and down options on the client (see below).

Client configuration :

vpn.conf :

client
dev tun
proto udp
remote vpn.example.org
port 10000
nobind
persist-key
persist-tun
ca ./ca.crt
cert ./user.crt
key ./user.key
verb 5
up ./up.sh
down ./down.sh
ping 60
ping-restart 120

up.sh :

#!/bin/sh
mv /etc/resolv.conf /etc/resolv.conf.bak
echo "search local.example.org" > /etc/resolv.conf
echo "nameserver 172.16.7.253" >> /etc/resolv.conf

down.sh :

#!/bin/sh
mv /etc/resolv.conf.bak /etc/resolv.conf

When connecting to the server (with verbose option set to 5), we can see the server pushing the route settings to the client.

Fri Jul 18 23:22:19 2008 us=838005 ifconfig tun0 10.30.0.6 pointopoint 10.30.0.5 mtu 1500
Fri Jul 18 23:22:19 2008 us=843211 route add -net 72.x.x.x netmask 255.255.255.255 gw 172.16.7.253
Fri Jul 18 23:22:19 2008 us=845178 route add -net 0.0.0.0 netmask 128.0.0.0 gw 10.30.0.5
Fri Jul 18 23:22:19 2008 us=848568 route add -net 128.0.0.0 netmask 128.0.0.0 gw 10.30.0.5
Fri Jul 18 23:22:19 2008 us=850460 route add -net 10.30.0.0 netmask 255.255.255.0 gw 10.30.0.5

On the client, the routes :

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
72.x.x.x  172.16.7.253   255.255.255.255 UGH   0      0        0 wlan0
10.30.0.5       0.0.0.0         255.255.255.255 UH    0      0        0 tun0
172.16.7.0     0.0.0.0         255.255.255.0   U     0      0        0 wlan0
10.30.0.0       10.30.0.5       255.255.255.0   UG    0      0        0 tun0
0.0.0.0         10.30.0.5       128.0.0.0       UG    0      0        0 tun0
128.0.0.0       10.30.0.5       128.0.0.0       UG    0      0        0 tun0
0.0.0.0         172.16.7.253   0.0.0.0         UG    0      0        0 wlan0

Apache : disable the HTTP TRACE method

October 25, 2007 - No comment

Marius Ducea is sharing an interesting tip about Apache.
Later versions of Apache now have a variable controlling if the trace request method is enabled.

TRACE is a HTTP request method used for debugging which echoes input back to the user.

http://www.ducea.com/2007/10/22/apache-tips-disable-the-http-trace-method/

Howto : installing TRAC on Debian Etch

October 5, 2007 - 4 comments

Howto available here : http://www.wains.be/pub/howto/trac-debian.txt

This howto explains the steps from creating the SVN project to publishing it with TRAC.

Along with this howto, you can download a script that automates the process of creating the SVN repository and TRAC environment.
This script was made according to this howto and works under Debian. YOU SHOULD FIRST GO THROUGH THE HOWTO BEFORE USING THIS SCRIPT.

http://www.wains.be/pub/create_svntrac_project

Usage :

# create_svntrac_project.sh project_name (0|1)
project_name = NO space or special char
0 = SVN repository creation
1 = TRAC environment creation, SVN repository must exist and project must ALREADY BE imported

I like TRAC because it provides a nice diff viewer (among other things).

I tried ViewCVS from the stable repo but I had several issues (broken images, no color in the diff viewer, etc.)
I noticed in the code it was calling images from incorrect paths, etc.
Maybe I did something wrong, I don’t know..

Anyway, TRAC is far better !

Apache : custom 404 error page returns a 302 error code

July 21, 2007 - 1 comment

First let’s look what the docs says about setting up a custom error page :
http://httpd.apache.org/docs/2.0/en/custom-error.html

If you set up your custom 404 error page pointing to a full URL like :

ErrorDocument 404 http://www.wains.be/404/index.html

You would get an error 302 code.

.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable

July 19, 2007 - 18 comments

I got this error message in apache error logs :

/some/path/to/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable

I was trying to access an image to something like http://www.domain.be/image/picture.jpg

The error message is very misleading because the real issue was just inappropriate rights on the folder “image”. (I did not have anything involving htaccess around there).

I had the folder chmod’ed 644 for some reason.

A “chmod 755 image” fixed the problem..

Allowing Apache/mod_dosevasive to use iptables through sudoers

March 29, 2007 - 2 comments

What is mod_dosevasive ?

mod_dosevasive is an evasive maneuvers module for Apache to provide evasive
action in the event of an HTTP DoS or DDoS attack or brute force attack. It
is also designed to be a detection tool, and can be easily configured to talk
to ipchains, firewalls, routers, and etcetera.

Detection is performed by creating an internal dynamic hash table of IP
Addresses and URIs, and denying any single IP address from any of the following:

- Requesting the same page more than a few times per second
- Making more than 50 concurrent requests on the same child per second
- Making any requests while temporarily blacklisted (on a blocking list)

The issue

Apache by default runs as an unprivileged user.
When using the module dosevasive, you can set it up to trigger a command when a DoS/DDoS/Brute force attack is detected.

This is my config :

mod_dosevasive config :

LoadModule dosevasive20_module modules/mod_dosevasive20.so
<ifmodule mod_dosevasive20.c>
    DOSHashTableSize    3097
    DOSPageCount        2
    DOSSiteCount        50
    DOSPageInterval     1
    DOSSiteInterval     1
    DOSBlockingPeriod   10
# Optional Directives - /usr/share/doc/mod_dosevasive/README for more info
    DOSEmailNotify      admin@domain.be
    DOSWhitelist        192.168.1.*
    DOSSystemCommand    "sudo /sbin/iptables -A INPUT -s %s -j DROP"
</ifmodule>

You can see I set up dosevasive to drop the offending IP’s when the system is triggered.

As we are running apache as an unprivileged user, when need to allow apache to use sudo in order to drop the IP’s with iptables.

Edit the sudoers file :
visudo

Add this :
apache ALL=(ALL) NOPASSWD: /sbin/iptables -A INPUT -s [0-9.]* -j DROP

This would allow apache/mod_dosevasive to drop an offending IP in the firewall.

As I’m not a sudoers regular user, this may not be the best recipe.. If you have a better solution, drop me a line ! :)

Hide PHP version in the header (X-Powered-By)

March 3, 2007 - No comment

Edit /etc/php.ini (under RHEL/CentOS) and set :
expose_php = Off

Next Page »