Web sites hosting (discussion)

Discussions, thoughts and details about WebSite.

A (bit more) secure PHP

Apache's mod_php is only able to run PHP scripts as the Apache user (on Debian : www-data). But we want one UID per website, and a quite good isolation.

External information :

Apache2 + mod_php

Good performance, but all sites run under a shared UID and the whole security depends on safe_mode and open_basedir, which we maybe don't want to try... well, actually, why not, inside a VServer.

Apache2 + suexec'ing PHP running as CGI

All these solutions are performance hogs : running in pure CGI mode, a PHP interpreter is loaded every time a PHP script is run :/

suPHP

  • http://www.suphp.org/
  • un module Apache + un binaire setuid root qui s'occupe de changer l'UID de PHP au besoin
  • looks like a suExec clone, with no apparent enhancement
  • 0.6.1 brings the possibility to chroot to a common (whole server-wide) directory such as /var/www ; along with proper permissions (o-rwx) this gives great sites isolation

Information sources :

php-cgi + suExec

  • More or less the same performance and security as suPHP.

Apache2 + mpm-itk

Apache2 + suExec + a CGI dispatch daemon

If chrooting is wanted, a proper chroot must be build with php inside for every website :

If chrooting is not wanted, things are not that hard to setup.

suExec wants the wrapper scripts to be owned by the user running the script, which we don't want : else, a simple PHP script would be allowed to modify the wrapper. Either suExec must be compiled with such checks disabled, or a workaround has to be used : immutable bit and ACLs are the main options, as explained on http://ckdake.com/projects/documentation/php_security/.

These solutions are supposed to be either a bit slower or a bit faster than mod_php.

mod_fastcgi

mod_fcgid

mod_scgi

mod_cgid

  • ???

lighttpd with builtin FastCGI

Nginx

  • chouette doc de config avancée : https://calomel.org/nginx.html

syslog

sans patcher

"suffit" de le faire logguer dans un named pipe, et au choix, soit de faire forwarder le contenu par un cat|machin.sh, soit de faire lire ce pipe à un démon syslog.

l'idée vient de : http://admin-monkey.com/doku.php?id=nginx

en patchant

y’a un patch qui semble maintenu. testé, pas réussi à faire marcher.

Module Fcgi

homepage

  • exemple du wiki
  • directives de cache du backend prises en compte à partir de 0.7.48 (dans lenny-bpo, squeeze)
  • marche bien

PHP

  • http://blog.hbis.fr/2009/03/18/nginx-fastcgi-php/
  • exemple du wiki
  • facile de désactiver PHP dans certains dossiers (IMG, etc.)

Mutualisé

  • http://blog.hbis.fr/2009/06/18/nginx-vhosts/

cache

voir aussi :

  • purger le cache : http://wiki.nginx.org/Nginx3rdPartyModules#Cache_Purge_Module

module fastcgi

http://wiki.nginx.org/NginxHttpFcgiModule

a des paramètres de cache, à creuser.

module proxy

http://wiki.nginx.org/NginxHttpProxyModule

  • idée : mettre son répertoire de cache en ramdisk

modules memcached

  • http://wiki.nginx.org/NginxHttpMemcachedModule
  • http://wiki.nginx.org/NginxHttpMemcModule
  • non: savent seulement lire depuis memcached, ou causer son protocole, mais pas tenir un cache à jour

remove_ip

doit bien y avoir un module pour changer des variables d’état HTTP à la volée

  • fastcgi_param permet-il de mettre REMOTE_IP = 127.0.0.1 ou un truc comme ça ?

content negotiation

apparemment, ne supporte pas Content Negotiation (ikiwiki+po). même avec proxy_pass vers un Apache qui lui le supporte, ça n'a pas l'air de fonctionner, car il cause HTTP/1.0 au backend :/

vrac

  • logguer les requêtes particulièrement longues (lentes) : http://wiki.nginx.org/NginxHttpLogRequestSpeed (3rd party)
  • fournir url pour invalider tel ou tel bout du cache : http://labs.frickle.com/nginx_ngx_cache_purge/

Cherokee

homepage

  • un convaincu
  • supporte TLS, vhosts, fastcgi, syslog, reverse proxy, etc.
  • interface de conf web très complète, mais... si les fichiers de conf sont bien documentés, il est recommandé de ne pas les modifier à la main... sauf pour scripter, etc.
  • reste à traduire les htaccess livrés par les CMS
  • ne supporte pas Content Negotiation: bug report

SSL vs. vhosts

Supporte SNI, mais si le client ne supporte pas ?

FPM

homepage

  • microdoc sur le wiki
  • http://blog.myprod.net/2010/08/14/apache2-suexec-fastcgi-php-5-3-3-fpm-cache-opcode-apc/
  • pas buildé dans le paquet Squeeze, mais se réactive trivialement + recompilation du paquet

Apache

Apache sait faire générer sa conf par un programme Perl, avec les PerlSections.

Nous choisissons cette solution, extrêmement flexible, plutôt qu'une des autres solutions :

DNS

Type du dns_enregistrement parent d'un web_site : A, mais pas forcément chez nous. C'est pourquoi on stocke, dans la table dns_records, les champs A qui pointent vers nous mais dont ne gérons pas le DNS, tout va bien.

Un CNAME peut-il être enregistrement parent d'un site web ? Cas possibles :

  • CNAME externe/interne -> fqdn hébergé chez nous y compris DNS -> A interne
    Alors enregistrement parent = ce A interne
  • CNAME externe/interne -> fqdn hébergé chez nous seulement au niveau web sous forme d'un A externe
    Alors enregistrement parent = ce A externe
  • CNAME externe/interne -> fqdn hébergé chez nous seulement au niveau web sous forme d'un autre CNAME externe
    Retour à la case départ.

Donc non.

Sauf que e raisonnement ci-dessus ne fonctionne que si un CNAME induit une redirection, càd si les requêtes web reçues sont adressées au fqdn destination (content).

Or... c'est faux. Par conséquent, oui, dans la théorie, un CNAME géré ailleurs mais pointant sur nous pourrait être enregistrement parent d'un site web. Sauf que ça complique beaucoup le schéma SQL, et donc, le modèle de franGiPane interdit ça.

NSS

We've got one UID per site, so we need "real" Unix users.

Il faut donc utiliser des vrais/faux users locaux, grâce à libnss-pgsql : <file:///usr/share/doc/libnss-pgsql1/nss-pgsql.html>.

TODO : gaffe à ce que ça implique :

  • shell=/bin/false suffit ?
  • PAM : ajouter un check à tous les services utilisant pam_unix ; appeler pam_shells dans /etc/pam.d/common-* devrait suffire
  • services n'utilisant pas PAM mais NSS directement ? oulala... 'fin apparemment ça n'arrivera pas, ouais ouais le monde est bien fait.

Pour ce qui est des relations d'appartenance à un groupe, notre cas est beaucoup plus simple que le cas général ; en effet, un web_master n'administre qu'un web_site, et par conséquent, au sens NSS, un user n'appartient qu'à un groupe. Ainsi, dans /etc/nss-pgsql.conf, nous pourrons mettre :

  passwdtable      = ftp_passwd
  grouptable       = ftp_group
  groupmembertable = ftp_passwd
  group_member      = login
  querypasswd      = SELECT login,passwd,uid,gid,gecos,homedir,shell FROM ftp_passwd
  querygroup       = SELECT name,passwd,gid FROM ftp_group
  querymembers      = SELECT login FROM ftp_passwd WHERE gid=%d
  queryids      = SELECT gid FROM ftp_passwd WHERE false

Attention ! /etc/nss-pgsql.conf doit être lisible par les users qui doivent s'en servir, et il contient le mot de passe d'accès à la table contenant les passwords ftp (hashés)... il s'agit donc d'étanchéifier tout ça.

Postfix, par exemple, met du temps à se lancer s'il ne peut lire ce fichier. Pas grave, na.

nss-mysql a un truc pour éviter ce problème, et Lunar bosse sur un patch apportant la même fonctionnalité à nss-pgsql : un peu le même principe que pour /etc/{passwd,shadow}, en fait.

TODO : tester ce patch

Remote web site editing

The web sites admins need to edit their sites files with a FTP-like method, without any password or bit of data travelling in cleartext over the Internet.

After studying the various solutions, we finally decided to setup a lightweight VServer dedicated to webmasters, hence its name : webmasters. The webmasters are given ssh access to this VServer. This solution is described on WebSite.

PHP working directories

Every site have its own upload_tmp_dir and session.save_path, located in web:/var/tmp/frangipane/$DOMAIN/$SITE/php/{upload,sessions.

CMS farm

We'd like to be able to host several sites on the same CMS install, such as SPIP, which will soon provide this functionnality :

  • consider this centralized install as one web_site instance
  • set ftp_status to off for this web_site object
  • every webmaster for these sites hosted on this common CMS install have to be web_master objects