Apache jest jednym z najpopularniejszych serwerów WWW. Co prawda ostatnio pojawiła się konkurencja w postaci serwera nginx, niemniej jak na razie jego pozycja jest niezagrożona. W dalszej części będziemy się zajmować konfiguracją serwera Apache pod Linuksem, a dokładniej pod SuSE Linux, chociaż na większości dystrybucji wygląda to bardzo podobnie.
Minimalny zestaw pakietów, żeby zadziałał serwer:
Dodatkowo możemy też doinstalować przykładowe strony:
Po instalacji pakietów oraz uruchomieniu serwera
# rcapache2 start
otwieramy przeglądarkę i wprowadzamy adres http://localhost/. Powinniśmy zobaczyć stronę startową, w przypadku SLES 10 jest to po prostu napis „It works!”. Dokładniej, pod tym adresem widoczna jest zawartość katalogu /srv/www/htdocs, przy czym nie wskazując żadnego pliku (żądanym zasobem w tym adresie to „”), serwer domyślnie pokaże zawartość pliku index.html (domyślnie, w tym katalogu są kopiowane strony z pakietu apache2-example-pages). Katalog /srv/www/htdocs jest nazywany DocumentRoot. Ponieważ mamy mapowanie katalogu /srv/www/htdocs na adres http://localhost/ , możemy więc tworzyć podkatalogi, czyli np. /srv/www/htdocs/admin/ będzie dostępny pod adresem http://localhost/admin/
Pliki konfiguracyjne są w katalogu /etc/apache2. Kilka istotniejszych plików z tego katalogu:
httpd.conf – główny plik konfiguracyjny
default-server.conf - podstawowa konfiguracja serwera (np. określony tam jest DocumentRoot oraz podstawowy dostęp dla DocumentRoot)
vhost.d/ - pliki konfiguracyjne wirtualnych hostów
uid.conf – tożsamość, w kontekście której będzie działa proces serwera Apache (domyślnie użytownik wwwrun i grupa www)
listen.conf – tam określamy porty i interfejsy, na których serwer będzie nasłuchiwał
server-tuning.conf – parametry, które pozwalają na zwiększenie wydajności serwera w pewnych sytuacjach, np. przy bardzo dużym obciążeniu na bardzo wydajnym serwerze
error.conf – szereg wpisów określających zachowanie w przypadku, gdy żądanie nie może być zrealizowane poprawnie (np. są określone dokumentu dla poszczególnych kodów błędów, przykładowo 404 czy 500)
ssl-global.conf – globalna konfiguracja dla protokołu SSL.
Podstawowym elementem konfiguracji są dyrektywy (np. Include, Order, Allow), które można grupować i aplikować tylko do wybranych katalogów poprzez konstrukcję <Directory "/path/to/catalog">...</Directory>. Znak # służy do tworzenia komentarzy.
Kilka istotniejszych dyrektyw:
Po edycji plików konfiguracyjnych, serwer apache należy przeładować komendą
# rcapache2 reload
a czasami nawet zrestartować
# rcapache2 restart
Zawsze też możemy sprawdzić poprawność plików konfiguracyjnych poleceniem
# apache2ctl configtest
W klasycznym podejściu, któremu przyjrzeliśmy się do tej pory, serwer WWW może pod adresem http://localhost/ (lub poprzez FQDN, np. http://www.onet.pl/) prezentować zawartość dokładnie jednego katalogu (zwykle htdocs). To prowadzi do sytuacji, że każda domena jest obsługiwana przez inny komputer. Tak podejście byłoby oczywiście bardzo kłopotliwe, jednak aby zaradzić problemowi mamy mechanizm tzw. wirtualnych hostów. Dzięki niemu jeden serwer WWW może obsługiwać wiele domen. Działa to w skrócie następująco:
Hosty wirtualne mają swoje pliki konfiguracji w katalogu /etc/apache2/vhosts.d/
Wybrane dyrektywy do konfiguracji hosta wirtualnego:
Utwórzmy zatem przykładowy host wirtualny dla domeny www.example.com:
127.0.0.1 localhost www.example.com
mkdir -p /srv/www/vhosts/www.example.com
echo "www.example.com" > /srv/www/vhosts/www.example.com
cd /etc/apache/vhosts.d/ cp vhost.template www.example.com.conf
ErrorLog /var/log/apache2/www.example.com-error_log CustomLog /var/log/apache2/www.example.com-access_log combined
/srv/www/vhosts/www.example.com(pierwotnie jest /srv/www/vhosts/dummy-host.example.com)
# rcapache2 restarta następnie uruchamiamy przeglądarkę i wpisujemy adres
http://www.example.com/Powinien się w niej pojawić napis
www.example.com
Przy domyślnej konfiguracji serwera WWW, dostęp do udostępnianych zasobów mają wszyscy użytkownicy. Piszę udostępnianych, ponieważ domyślnie dostęp do np. katalogu głównego serwera jest zablokowany, zresztą przy wykorzystywaniu ogólnych mechanizmów, które dalej zostaną omówione.
Na poziomie samego serwera Apache mamy dwa mechanizmy sterowania dostępem:
Do uzyskania tej funkcjonalności wykorzystujemy dyrektywy Order, Allow i Deny, które osadzamy w sekcji Directory, określającej dla jakiego katalogu definiujemy prawa dostępu. Jak się łatwo domyślić, Allow określa kto ma dostęp do katalogu, a Deny określa kto dostępu nie ma. Z Order jest z kolei związana kwestia wyliczania, czy dany host ostatecznie ma dostęp do witryny, ponieważ Allow i Deny mogą występować razem. Wyliczanie działa zgodnie z zasadą „ostatnie na wierzchu” i najlepiej chyba będzie pokazać to na małym przykładzie:
<Directory "/srv/www/htdocs"> Order deny,allow Deny from all Allow from 192.168.0.0/24 </Directory>
Dyrektywa Order określa, że wyliczana jest najpierw dyrektywa Deny, a potem Allow. Po wyliczeniu Deny mamy sytuację, że nikt nie ma dostępu. Następnie wyliczamy Allow, który określa, że dostęp jest dla hostów z siecie 192.168.0.0/24. Więc ostatecznie dostęp jest zabroniony dla wszystkich hostów oprócz tych z sieci 192.168.0.0/24, ponieważ Allow tak jakby nadpisał wcześniej wyliczone prawa na obszarze hostów z 192.168.0.0/24, dając im dostęp.
Co możemy pisać po from:
Poza wyliczaniem uprawnień kolejność podana po Order ma jeszcze jedną konsekwencję:
W tym scenariuszu korzystamy z mechanizmu zwanego Basic Authentication. Utworzenie tego typu zabezpieczenia składa się z dwóch kroków: utworzenie bazy użytkowników oraz zabezpieczenie wybranego katalogu.
Utworzenie użytkowników
Wykorzystujemy do tego polecenie htpasswd2. Podstawowe użycia:
# htpasswd2 /etc/apache2/htpasswd username
# htpasswd2 -D /etc/apache2/htpasswd username
Plik /etc/apache2/htpasswd występujący w powyższych poleceniach jest plikiem z użytkownikami i hasłami. Jeśli pliku nie ma, to przy tworzeniu pierwszego użytkownika dodajemy opcję -c; polecenie wtedy wygląda następująco:
# htpasswd2 -c /etc/apache2/htpasswd username
Bardzo ważne jest, aby plik ten był dostępny dla użytkownika systemu wwwrun, ale nie był dostępny przez WWW.
Ustawienie dostępu dla katalogu
Do sekcji opisującej katalog dodajemy następujące wiersze:
AuthType Basic AuthName "Opis obszaru chroniony" AuthUserFile /etc/apache2/htpasswd Require user pawel bea
Znaczenie wierszy jest raczej jasne, krótki komentarz tylko do ostatniego wiersza. Dyrektywa Require określa, kto będzie miał dostęp do zasobów. Oczywiście wprowadzeni użytkownicy muszą być wcześniej zdefiniowani w pliku z hasłami. Mamy dwa sposoby określania dostępu:
Na koniec jeszcze krótki komentarz jak wygląda protokół w przypadku uwierzytelnienia na podstawie login i hasła.
HTTP/1.1 401 Authorization Required ... WWW-Authenticate: Basic realm="Secure Area" ...
... Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Ładnie jest to opisane w Wikipedii: http://en.wikipedia.org/wiki/Basic_access_authentication.
Uwaga: cała transmisja domyślnie nie jest w żaden sposób zabezpieczona, więc kluczowym elementem dla wykorzystania powyższego mechanizmu jest konfiguracja protokołu SSL (omówiona w dalszej części).
Zanim przejdziemy dalej warto odnotować, że możliwości sterowania dostępem są dużo bardziej rozbudowane od wyżej przedstawionych. Od prostej i naturalnej możliwości tworzenia grup użytkowników, do sprzężenia logowania z serwerem LDAP oraz ustawieniu wielu różnych opcji czy szczegółów. Zainteresowani bez problemu znajdą w tym temacie sporo artykułów w Sieci, niemało jest też na samych stronach Apache’a.
W wielu sytuacjach udostępnienie aplikacji za pomocą szyfrowanego kanału SSL jest kluczowe dla bezpiecznego funkcjonowania aplikacji. Okazuje się, że konfiguracja serwera Apache do pracy z SSL-em jest całkiem łatwe. Ponieważ żywię przekonanie, że przykłady potrafią często najlepiej przedstawić zagadnienie, dalej przedstawię kroki prowadzące doprowadzą do sytuacji, w której:
Pierwsze wspólne kroki dla obu punktów są następujące:
# openssl req -new -x509 -out apachecert.pemPodczas generowania zostaniemy zapytani o szereg danych, ważne, aby jako common name podać domenę, dla której certyfikat jest generowany (wpisujemy www.example.com, patrz uwaga poniżej).
# openssl rsa -in privkey.pem -out apachekey.pemUwaga: żeby było bardzo ok, należałoby wygenerować dwa certyfikaty z odpowiednio wpisanym z common name localhost i www.example.com. Żeby kroki były jak najprostsze, ograniczymy się do utworzenia jednego certyfikatu dla domeny www.example.com.
Dalej, najpierw uruchomimy adres https://localhost/. Aby to zrobić, najpierw tworzymy plik wirtualnego hosta (nazwa localhost-ssl.conf nie większego znaczenia, o ile ma rozszerzenie .conf):
# cp /etc/apache2/vhosts/vhost-ssl.template /etc/apache2/vhosts/localhost-ssl.conf
Następnie odnajdujemy w pliku localhost-ssl.conf linie z dyrektywami SSLCertificateFile oraz SSLCertificateKeyFile i ustawiamy je następująco:
SSLCertificateFile /etc/apache2/ssl.crt/apachecert.pem SSLCertificateKeyFile /etc/apache2/ssl.key/apachekey.pem
Warto w tym miejscu odnotować, że istotne są jeszcze wiersze SSLEngine oraz SSLCipherSuite, ale są one w tym pliku już poprawnie ustawione. Ostatecznie restartujemy serwer
# rcapache2 restart
I localhost na SSL-u powinien już działać.
Teraz uruchomimy na SSL-u wirtualny host www.example.com. Jak poprzednio, najpierw tworzymy plik wirtualnego hosta:
# cp /etc/apache2/vhosts/vhost-ssl.template /etc/apache2/vhosts/www.exampel.com-ssl.conf
Następnie wykonujemy w pliku www.example.com-ssl.conf następujące zmiany:
SSLCertificateFile /etc/apache2/ssl.crt/apachecert.pem SSLCertificateKeyFile /etc/apache2/ssl.key/apachekey.pem
<Directory /srv/www/vhosts/www.example.com> Order allow,denny Allow from all </Directory>
Ostatecznie restartujemy serwer apache
# rcapache2 restart
i sprawdzamy, że pod adresem https://www.example.com/ mamy dostępną stronę z oczekiwaną zawartością.
No koniec jedno spostrzeżenie: jeśli byśmy utworzyli plik wirtualnego hosta dla www.example.com:443 (czyli dla SSL), a nie utworzyli wirtualnego hosta www.example.com (czyli bez SSL), to po wpisaniu w przeglądarce http://www.example.com/ pojawiłaby się taka sama witryna, jak ta dostępna pod adresem http://localhost/.