Salı, Kasım 04, 2008

Apache2, VirualHost ve SSL

Evet yıllar sonraki ilk "teknik" blog yazımla karşınızdayım. :) Bu gece ODTÜ Robot Topluluğu için hazırladığımız yeni sunucuya SVN ve Trac sistemleri kuruyordum ve bunu yaparken SSL ile güvenli iletişim desteğini de aradan çıkartayım dedim. Demez olaydım. Gerçekten çok ilginç problemlerle karşılaşabiliyorsunuz. Edindiğim tecrübeleri bu işle uğraşacakların Amerika'yı yeniden keşfetmekle zaman kaybetmemeleri açısından burada paylaşmaya karar verdim.

Öncelikle kullandığımız sunucu Ubuntu 8.04 kurulu sıradan bir bilgisayar. Bu yüzden yazı büyük ihtimalle sadece Debian tabanlı sistemler için geçerli olacak(örn. Ubuntu). Ancak ayar dosyalarının kendi sisteminizdeki yolunu bulabilirseniz(ki çok zor değil) mantık ve yazılan değerler aynı sayılır.

Öncelikle Apache2 için ssl modunun kurulu ve etkin durumda olduğundan emin olun. Eğer etkin olmadığını düşünüyorsanız
sudo a2enmod ssl
komutuyla etkinleştirebilirsiniz.

Bu işlemin devamında sanal sunucularınızı port 80'i dinleyenler ve port 443'ü(SSL portu) dinleyenler olarak ikiye ayırmak için /etc/apache2/sites-enabled/default dosyasının başındaki NameVirtualHost satır(lar)ının aşağıdaki satırları içerdiğine emin oluyoruz(tavsiyem silip aşağıdaki satırları yazmanız):
NameVirtualHost *:80
NameVirtualHost *:443
Not: Eğere sunucunuz özel bir IP adresini dinleyecek şekilde yapılandırıldıysa * yazan yerlere bu IP adresini yazmanız gerekiyor.

Bunları yaptıktan sonra ilgili alan adımızın tanım dosyasına gidiyoruz(örn: /etc/apache2/sites-enabled/ssl-sitesi.conf) ve ilk satırındaki tanımın sonuna port numarasını 443 olarak belirtiyoruz. Örnek:
<VirtualHost *:443>
Bu işlemi yaptıktan sonra alan adımız 443 numaralı portu dinlemeye başlayacak. Bu durumda http bağlantılarının artık çalışmayacağını unutmayın.

SSL için bir sertifikaya ihtiyacımız olduğundan bu noktada Apache'ye biraz ara verip kendimize ait SSL sertifikalarını oluşturmaya geçiyoruz. Bu kısım için http://www.xenocafe.com/tutorials/linux/centos/openssl/self_signed_certificates/index.php adresindeki yazından faydalandım. Herşeyden önce sistemimizde openssl'in kurulu olduğundan emin oluyoruz:
sudo apt-get update
sudo apt-get install openssl
Devamında sertifikaları yerleştireceğimiz dizine gidiyoruz. Ben /etc/apache2/ssl şeklinde bir dizin oluşturup burayı kullanmayı tercih ettim. Önce bir anahtar oluşturmalıyız. Anahtarı oluştururken bizden bir parola oluşturmamız istenecek. Bu parola en az 12 haneli ve güvenli bir şey olmalı. Devam eden kısımlarda bu parolaya ihtiyacımız olacak o yüzden not almayı unutmayın.
sudo openssl genrsa -des3 -out ssl-sitesi.key 1024
Buradaki "ssl-sitesi.key" anahtar dosyamızın adı. Karışıklık olmaması için site adıyla aynı adı kullanmayı tercih ediyorum. ".key" uzantısının aynı kalması ise yine karmaşayı engellemek adına önemli.

Anahtarımızı yaptıktan sonra anahtarımızın bizimle ilişkilendirilmesi için:
sudo openssl req -new -key ssl-sitesi.key -out ssl-sitesi.csr
komutunu çalıştırıyoruz. Az önce seçtiğimiz parolanın istenmesini takiben çeşitli bilgiler sorulmaya başlanıyor. Ülke kodu olarak TR girip, Province-State ve devamındaki soruyu bulunduğumuz şehri yazarak cevaplıyoruz. Bir sonraki soruda organizasyon adı ve devamında sertifikayı alan kişinin hangi departmanda olduğu soruluyor(bu bilgi seçimlik/opsiyonel). Bu noktada referans aldığım yazı isimleri girerken "&" işaretinden kaçınmamızı öğütlüyor, aklınızda bulunsun.

Tüm bu bilgileri de girdikten sonra "common name" diye bir bilgi sorulacak ki asıl önemli kısım burası. Buraya alan adınızı düzgün ve tam olarak yazmanız çok önemli(örn: robot.metu.edu.tr). Bunu da yaptıktan sonra iki ek soru sorulacak ki bunları basitçe enter'a basarak boş geçebiliriniz. Evet sonunda bizimle ilişkili bir anahtarımız oldu.

Sıra anahtarımızı imzalamaya geldi. Eğer çok ciddi bir site işletiyorsanız az önceki işlemden çıkan "csr" uzantılı dosyayı uygun ve güvenilir bir sertifika onaylayıcısına onaylatmanız gerekiyor ki bu işlem paralı olduğundan yazımızın konusu da sertifikayı kendi kendimize imzalamak yönünde ilerleyecek.

Sertifikamızı imzalamak için
sudo openssl x509 -req -days 365 -in ssl-sitesi.csr -signkey ssl-sitesi.key -out ssl-sitesi.crt
komutunu çalıştırıyoruz. Burada 365 sayısı sertifikanın geçerli olacağı gün sayısını belirtiyor. Ben 1 yılı tercih ettim ancak sizin 10-15 yıl gibi uzun bir zaman dilimi seçmenizde de çok bir sakınca yok.

Evet son olarak her işlemde girmemiz istenen sertifika şifresini kaldırmamız gerekiyor. Aksi takdirde Apache her açılışta konsoldan bu şifreleri girmemizi bekleyecek ki genelde başında olmadığımız bir sunucunun yeniden başlaması gibi durumlarda pek istenen bir şey değil bu. Peki bunu yapmanın bir dezavantajı var mı? Malesef var. Böyle yaptığımızda özel anahtarımızı(private key) herkesin okuyabileceği bir biçime getirmiş oluyoruz. Bu yüzden önlem olarak işimiz bittiğinde dosyaların sahibini root kullanıcısı yapıp izinlerini de 400 olarak değiştireceğiz yani sahibi olan kullanıcı sadece okuyabilecek, başka kimse hiç bir şey yapamayacak. Bu işlemi yaparken son bir kez daha şifreyi girmemiz gerektiğini de eklemeliyim.
sudo cp ssl-sitesi.key ssl-sitesi.key.secure
sudo openssl rsa -in ssl-sitesi.key.secure -out ssl-sitesi.key
Evet sonunda sertifikamız hazır. Şimdi son hamle olarak bunu Apache ayarlarından alan adımıza bağlıyoruz ve sonrasında kendimizi SSL'in güvenli sularına bırakabiliriz. Bunu yapmak için sitemizin ayar dosyasını açıyoruz(örn: /etc/apache2/sites-available/ssl-sitesi.conf) ve </VirtualHost> kapanışından önce şu satırları ekliyoruz:
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/ssl-sitesi.crt
SSLCertificateKeyFile /etc/apache2/ssl/ssl-sitesi.key
Dosyayı kaydedip Apache'yi tekrar başlattığımızda SSL'li sitemiz çalışıyor olmalı.
sudo /etc/init.d/apache2 restart
Eğer bir sorununuz ya da düzeltmeniz olursa yorum sistemiyle bana bildirebilirsiniz. Kolay gelsin.

Ekleme: Bugün(2008-11-07) Ferruh Mavituna'nın "SSL Sorunları" adlı çok güzel bir yazısına rastladım. SSL kullanmayı düşünüyorsanız mutlaka okumanızı öneriyorum.