PHP

PHP Security, Round 2

As I've noticed from watching hits on my site here, many of you have read my page on PHP security using mod_fastcgi and suexec. The logic on that page still holds, but Gentoo decided to make the switch from mod_fastcgi to mod_fcgid and it broke all sorts of things for me. I got things scratched back together without any security on my old server, and with the installation of my new server a few weeks ago, I set things up more securely again. I still think this way is the way to go for a server where many of the virtual hosts will seldomly see traffic, but if you're running lots of high traffic sites and have a little bit of RAM overhead, you might want to check out this article on mpm-peruser.

For this setup, I decided to stick to some standards. This means no more changing the suxec directory, using /data/, or anything like that. Other than that, the key differences from last time:

  • All configuration is now done with with a setup script instead of using a mysql database. There was not really any point for the host names to be in a database, and it makes setup/teardown scripts easier to write as just a bash script.
  • Some hosts have PHP, some don't, so no point in setting up all the overhead if a host isn't going to use PHP.
  • Most hosts won't have any interest in having their own logs. Statistics can be done using client side things such as Google Analytics, and Apache is happier writing all the logs to 1 place instead of hundreds. I also have split-logs running when logs are rotated, so logs can easily be gathered per-site as needed, just not real time by one of my hosting customers. I've never known of one of my customers using live access to their logs.
  • php.ini files are now stored with the wrapper script in the site's cgi-bin directory and file system extended attributes are used to protect it. This means no separate home for php.ini files, and it's easier for users to see what their PHP confguration is.

The script isn't quite ready for sharing yet, but here's what you can do to get a setup like this:

  1. on Gentoo, make sure your USE contains: suexec, apache2, cgi, fastcgi, session.
  2. on Gentoo, "emerge apache php mod_fcgid". On other platforms, consult your docs (or just download mod_fcgid and use apxs to install it. it should be pretty seamless)
  3. Set up your global configuration. On Gentoo, this is done for you, but make sure this gets loaded into your global apache configuration:
    LoadModule fcgid_module modules/mod_fcgid.so
    SocketPath /var/run/fcgidsock
    SharememPath /var/run/fcgid_shm
    
    <Location /fcgid>
    SetHandler fcgid-script
    Options ExecCGI
    allow from all
    </Location>
    
  4. Add a user and group for your first virtual host, test.example.com. call em "example" if you like
  5. Set up the directory tree for the virtual host:
    /var/www/test.example.com/
    /var/www/test.example.com/tmp
    /var/www/test.example.com/htdocs
    /var/www/test.example.com/htdocs/cgi-bin
    
  6. Make some files:
    <!-- /var/www/test.example.com/test.html -->
    hello HTML world!
    
    <? 
    /* /var/www/test.example.com/test.php  */
    print("hello PHP world!");
    ?>
    
    #!/bin/sh
    # /var/www/test.example.com/htdocs/fcgi
    PHPRC=/var/www/test.example.com/htdocs/cgi-bin/
    export PHPRC
    PHP_FCGI_CHILDREN=2
    export PHP_FCGI_CHILDREN
    PHP_FCGI_MAX_REQUESTS=25000
    export PHP_FCGI_MAX_REQUESTS
    exec /usr/bin/php-cgi
    
  7. Copy your php.ini to /var/www/test.example.com/htdocs/fcgi and edit it so that directories are right. All you'll likely need to change is upload.tmp_dir and session.save_path, but you may want to change others.
  8. Set fcgi to be executable, and make sure permissions are set on it so that it is owned by your test user/group and other users can't mess with it. If things don't work later, this is a frequent culprit
  9. Set the immutable bit on php.ini and fcgi (you'll need to be using extended file system attributes on your filesystem to do this, check your OS documentation for details) by running 'chattr +i /var/www/test.example.com/htdocs/*'. You'll need to undo this with chattr -i if you want to change these files in the future.
  10. Set up this host's configuration:
    <VirtualHost *:80>
            DocumentRoot /var/www/test.example.com/htdocs/
            ServerName test.example.com
            SuexecUserGroup example example
            <Directory /var/www/test.example.com/htdocs/>
                    Options +SymLinksIfOwnerMatch
                    AllowOverride All
                    Order allow,deny
                    Allow from all
                    DirectoryIndex index.html index.php
                    AddType application/x-httpd-fastphp .php
                    Action application/x-httpd-fastphp /cgi-bin/fphp
            </Directory>
    
            <Directory /var/www/test.example.com/htdocs/cgi-bin/>
                    SetHandler fcgid-script
                    FCGIWrapper /var/www/test.example.com/htdocs/cgi-bin/fphp .php
                    Options +ExecCGI -Includes
                    allow from all
            </Directory>
    
    </VirtualHost>
    
    <VirtualHost *:80>
            ServerName aerospace.com
            Redirect Permanent / http://test.example.com/
    </VirtualHost>
    
  11. Give apache a restart and that should be it!

Check out the processes running on your server, and after you hit test.php you should see a php-cgi process running as the example user. If you have problems, error_log and suexec_log in /var/log/apache2/ (or /var/log/httpd/) tend to tell you everything you need to know.

An oh yeah, want to use APC to speed up your PHP applications significantly under this setup? Just install APC, then add the configuration for it to the bottom of the php.ini for any hosts that you want to enable this on. Given that APC isn't 100% perfect and crashes sometimes, the beauty of the fcgid setup is that it will take out the php-cgi process and the fcgid manager will just start a new one like nothing happened.

APC

No, not American Power Conversion, but the Alternative PHP Cache. It's not real obvious as to what it does from the website, but if you're doing any serious PHP application stuff, you should take a look at them (and Zend and eAccelerator). I was helping benchmark some things for work and it's amazing the difference in performance that these make compared to a standard PHP installation.

Each of them is or has a PHP OpCode cache. This means that instead of compiling the PHP from the source code on every page request, things get cached and the web server doesn't need to talk to disk as much. Just installing APC on my two larger web servers has made an amazing difference. CPU utilization is down, memory usage is down, and average response times are up. On Pudge which hosts a lot of sites running a lot of applications (including this site), there is over 150Mb of things in the cache. Aurora just hosts Faster Mustache which is only running Gallery and Drupal, and it's cache is around 45Mb.

Supposedly Gallery doesn't work quite right with APC, but I haven't had any problems with it, and the web server process on Aurora crashed once over the last few weeks after APC was installed, but I don't know if APC was the culprit or not. I'm looking forward to setting up fastcgi with suexec and APC to see how well it does with lots of virtual hosts running, and hopefully there will be a new server in the mail in the next month or two for me to do that on..

PHP on IIS -> fast and supported

Jesse and I went to the Microsoft Web Developer Summit a few weeks ago representing Gallery. Microsoft promised us that they were trying to be better citizens in the PHP community and make PHP work better on Windows. For those of you not in the know, the common way to run PHP on IIS was through CGI, which means that every single visit to a PHP page requires loading the entire PHP stack. Think starting up your web browser from scratch every time you open a new URL, and multiply that slowness by a few thousand users... it's baaaad. To get around this for PHP (and other CGI scripts) FastCGI came along and made everyones servers perform better. It daemonizes PHP (or anything else supported) so that it doesn't need to start up for every request, but it's never worked quiiiite right on IIS and has never been supported. Until now.

So today, after working with Zend for a while, Microsoft has released FastCGI today for the current version of IIS, with full Microsoft Support. Have a PHP app that you are trying to get to work in IIS? They'll help you. Cool! You can download FastCGI for free from www.iis.net/php. (And from what I understand, it really is FastCGI so you can use it for any CGI based application server in IIS.)

Have a Windows server running IIS? Want to use Gallery? Check out the howto that Microsoft wrote on Installing Gallery 2 on IIS. In addition to writing some docs, over the next few months Microsoft will supposedly be getting us resources like virtual machines, licenses, hosted test environments, etc so that we can make Gallery work on a wider range of Microsoft products.

A little Kool-Aid is definitely good every now and then.

Microsoft Web Developer Summit 07

Sunday to Tuesday of this week, Jesse and I represented Gallery at Microsoft's invite only 3rd annual Web Developer Summit. This year their focus was on PHP, and 24 "important" people from the PHP community were invited. The two authors of the book "Pro Drupal Development" that are also Drupal core developers, several people form the PHP (and PEAR) core team, an engineer from SugarCRM, and the guy at Facebook that wrote their developer platform were among the other attendees. On the Microsoft side were the important "higher ups" that work with Open Source technologies (see microsoft.com/opensource).

Sunday was my flight out and a few hours of catching up with an old friend I haven't seen since middle school, followed by meeting up with Jesse for some beer samplers at a local brewery, followed by some snacks and drinks with the rest of the summit attendees.

Monday was a day full of sessions followed by dinner, and Tuesday was more sessions. You can read someone else's presentation notes here so I'll keep this to highlights:

  • Pictures! Jesse's blog where he talks a lot more about some details
  • Microsoft is seriously interested in Open Source now. They've realized that their value is as a platform, and PHP applications need to work well on Windows for people to be willing to use Windows in may server environments. Sure, it's just business because thats what their customers demand, but they're ready to work with us to do what needs to be done.
  • Monday after dinner (and after Jesse ordered a round of tequila shots for the entire conference on Microsoft's tab), I spoke with Sam Ramji, Microsoft's Director of Platform Strategy, for an hour or so. He runs the Open Source Software Lab at Microsoft and was very interested in any ideas that I and the other attendees have for Microsoft.
  • Surprisingly, many of the ideas we had were news to them. It seems that there are a lot of things in the community that we all think Microsoft should do, but nobody ever goes to the trouble of telling them! Things like experienced Linux admins wish their BASH and Apache configuration skills could transfer more directly to PowerShell and IIS, etc. I don't remember all of these because they seemed so obvious, but they took notes and hopefully will get around to doing some of these.
  • Jesse and I were convinced at the last minute to do a talk on Gallery. We quickly put together a presentation and some people at least seemed pretty interested. We got a healthy number of questions and I looked at some number I haven't looked at in a while (Gallery gets ~150k downloads a month!). As a result of this, we may have 2 people contributing some code and one person starting on some more documentation for us. Hoorah.
  • While some of the presentations were pretty useful, much of it wasn't really targeted to the audience. Sure, learning about Silverlight and Expression were neat, but were they really the best use of our time? Probably not. However, internet worked well and it was easy to get other things done during the less interesting parts. (And most people in the room were on IRC so we could discuss things at the event as they happened.)
  • We were not given suitcases full of cash to use ASP.net, but each of us walked out with a full MSDN Subscription and Microsoft is going to be working with us to provide whatever products and licenses we need to be able to effectively develop for and test on Microsoft platforms including IIS7, Windows Server 2003 and 2008, Microsoft SQL Server, etc. No complaints there. (One attendee just hasn't gotten around to publishing something she's been working on yet, and it sounded like Microsoft will be shipping her an XBox 360 to encourage her to get around to it :) )

All in all, it was a pretty useful couple of days. I think the most important part was networking with other PHP developers and the Open Source people at Microsoft, as this should encourage future email conversations with everyone to be timelier and more effective. Hopefully, everything will come through and Microsoft will be able to provide Gallery with what we need to be able to test and develop on Windows, and hopefully Microsoft will be able to implement some of our suggestions for the way they work with Open Source. They do seem very interested in making this happen! If you want to read more from them (which you should, especially if you think I've just been drinking their KoolAid all week), check out: port25.technet.com and microsoft.com/opensource.

Transparent TCP Stream Encryption

School this semester has been very busy, but things are getting done and I'll post the neat things here as I get finished. The first project I completed this semester was my group project for CS6250: Advanced Computer Networks aka Router Architectures and Algorithms.

My group, consisting of Me, Zack A, and Chris L (a usual in my CS groups) designed and implemented ZCC: a set of very easy to use and manage tools for encrypting TCP traffic. The end result didn't turn out quite as we originally planned, but the key functionality is there and we were all very excited about it. (For example, it only works with IPv4 currently) Chris L and I are actually hoping to build on this next semester as a project in CS 7260: Internet Architecture & Protocols.

The neatest part of this project for me was becoming very familar with the ip_queue kernel module and libipq which seems to be something that almost noone is familar with. It's manual page here hasn't been updated in a while, and the successor to it: "libnetfilter_queue," (which we found out too late to use) is only available in very new Linux kernels (2.6.14 or newer). If you Google around for libipq, you'll see that we didn't have a lot to work with or examples to go by. (We were trying to modify the packet data before pushing it back into the queue while most examples just show how to accept or drop packets)

Read on for the details..

CollegeMedium.com

It's finally here. That top secret website project I've been working on. We at College Medium, LLC are proud to announcehttp://www.collegemedium.com/ CollegeMedium.com provides a network for college students to sell items, rent apartments, find local jobs and student roommates, in their school or other surrounding schools.
Employers and property managers can also target specific college campuses for their housing and employment needs. This service is FREE to EVERYONE. Basically, It's really cool. Stop by, check it out, sign up for an account, and let us know what you think! I'm the CTO of College Medium, LLC which means I've spent the last few months doing all the infrastructure work and putting together the site. I've learned a bit doing it and here are some of the cool things that are happening behind the scenes:

  • CSS for all visuals. That includes the nifty semi-transparent dropdown menus. Tables are only used for tabular data, where they should be
  • AJAX for loading state/city/school names and ids, as well for for dynamically loading contextual help and displaying it inline with the content when a user requests it
  • Secure one way hashing of passwords for storage, and one way generation of keys that are used to verify email addresses, cell phone numbers, referals, etc
  • mod_rewrite rules for pretty URLs and hiding things on the file system
  • InnoDB tables in MySQL for strict enforcement of foreign keys including properly deleting entitys that refrence a deleted parent entity
  • PHP running with suexec in mod_fastcgi for secure high performance PHP execution
  • On site messaging for completely anonymous communication between users. Absolutley no information is shared about users, not even their member id number on the site (unless they choose to share it)
  • Users can choose to receive text messages on their cell phone whenever they receive a new message on the site
  • Database of (hopefully) every single college in the united states
  • Logging of all system errors and hiding them from the user
  • Dynamic menu and page generation relying on group permissions in access control lists
  • Lots of other things I probably forgot!