NGINX Güvenliği (Virtual Domain güvenliği)
Merhaba,
Bilindiği gibi nginx, virtual domainler üzerinde nginx:nginx kullanıcı ve grubu ile işlem yapmaktadır. Tüm virtual domain’leriniz default olarak nginx:nginx kullanıcısına aittir. Onlarca web siteniz olduğunu düşünün, içlerinden herhangi birisi bir şekilde hacklendiğinde diğer web sitelerinizi de güvenlik olarak ciddi tehlikelere düşürecektir. Bu yazıda farklı php-fpm socketleri kullanarak farklı kullanıcıların virtual domain üzerinden çalışmasını ve güvenlik sağlamasından bahsedeceğim.
Özellikle wordpress, joomla gibi hazır sitelerinde açıklarından faydalanıp backdoor, shell atarak tüm sitelerinize ulaşılabilir hale gelmek çok zor olmayacaktır. Her web sitesinin kendi kullanıcı adı ve grubu ile hareket etmesi, hacklenen sitenizin başka sitelere de zarar vermesini engelleyecek, sunucunuzdaki açığı da bulmanızı kolaylaşacaktır. Güvenliği sağlamadan önce nginx’in son sürümü kullandığınızdan emin olun ve nginx’i nasıl update edeceğinizi şu yazımda okuyun.
Nginx’i update ettikten sonra aşağıdaki talimatları (mantığını anlayarak) yerine getirin.
Öncelikle her virtual domain için bir kullanıcı adı ve grup oluşturacağız. Ancak bu kullanıcıların ssh giriş yetkileri bulunmayacak. Böylelikle ssh üzerinden gelebilecek olası saldırları da önlemiş olacağız.
Virtual domain adına bir grup oluşturun. Buradaki grup adları illaki domain adı olmak zorunda değil, ancak ileride karıştırmamak adına domainadi.com olarak oluşturuyoruz.
1 | $ groupadd domainadi.com |
Virtual domain adına bir user oluşturun.
1 | adduser -s /sbin/nologin -d [dosyalarin bulundugu dizin] -g [grup adı] [açacağınız kullanıcı adı] |
1 | adduser -s /sbin/nologin -d /var/www/domainadi.com -g domainadi.com domainadi.com |
-s /sbin/nologin açacağımız kullanıcının ssh üzerinden oturum açmasını engelleyecek.
Şimdi /etc/php-fpm.d/ klasörüne giriş yapınız.
1 | # cd /etc/php-fpm.d/ |
php-fpm.d klasörü her linux sürümlerinde farklı yerlerde veya isimlerde olabilir. Genellikle /etc klasörü altında yer almaktadır. Eğer cpanel, vpanel gibi özel paneller kullanıyorsanız bu klasörlerin yerleri farklı olacaktır. Cpanel gibi paneller zaten sizin yerinize bu güvenliği sağlıyor olabilir.
php-fpm.d klasörü içerisinde www.conf adında bir dosya var. Bu dosyada “;” hariç olan satırları sıralayınca aşağıdaki gibi bir çıktı elde edersiniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # grep -v ^\; www.conf [www] user = nginx group = nginx listen = /run/php-fpm/php7.1-fpm.sock listen.owner = nginx listen.group = nginx listen.mode = 0660 listen.allowed_clients = 127.0.0.1 pm = dynamic pm.max_children = 50 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 35 slowlog = /var/log/php-fpm/www-slow.log php_admin_value[error_log] = /var/log/php-fpm/www-error.log php_admin_flag[log_errors] = on php_value[session.save_handler] = files php_value[session.save_path] = /var/lib/php/session php_value[soap.wsdl_cache_dir] = /var/lib/php/wsdlcache |
Yukarıdaki standart www.conf dosyası php7.1-fpm.sock adında bir socket dosyası oluşturup nginx:nginx kullanıcısı üzerinden web sayfasını dinlemektedir. Web sayfasının php dosyaları da bu socket üzerinden derlenerek kullanıcıların karşısına tarayıcı tarafından çıkarılmaktadır. Biz her virtual domain için bir conf dosyası oluşturacağız. Aşağıdaki örneğe bakın
1 2 | # cd /etc/php-fpm.d/ # touch domainadi.com.conf |
Yukarıda conf dosyamızı oluşturduk. İçerisine aşağıdaki kodları ekleyelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | [domainadi.com] user = domainadi.com group = domainadi.com listen = /run/php-fpm/domainadi.com.sock listen.owner = nginx listen.group = nginx listen.mode = 0660 listen.allowed_clients = 127.0.0.1 pm = dynamic pm.max_children = 50 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 35 php_admin_value[disable_functions] = exec,passthru,shell_exec,system php_admin_flag[allow_url_fopen] = off slowlog = /var/log/php-fpm/domainadi.com-slow.log php_admin_value[error_log] = /var/log/php-fpm/domainadi.com-error.log php_admin_flag[log_errors] = on php_value[session.save_handler] = files php_value[session.save_path] = /var/lib/php/session php_value[soap.wsdl_cache_dir] = /var/lib/php/wsdlcache |
Yukarıdaki kodu bir metin programı ile domainadi.com.conf dosyası içerisine yapıştırın. Burada dikkat etmeniz gereken şey; az önce açtığınız kullanıcı ve grup adını kullanmanız ve socket’i domainadi.com.sock olarak kullanmanız. php tarafında da bazı kısıtlamalara gittik, mesela exec’i disable ettik. Bunun sebebi insanlar php üzerinden linux komutlarını çalıştıramasın. Fazla detaya girmeden bu kısmı atlıyorum.
Yukarıdaki işlem bittikten sonra aynı klasörde iki adet conf dosyası görmeniz gerekiyor. Şimdi php-fpm’i restart edelim.
1 | # systemctl restart php-fpm |
Restart sonrasında socket’in çalışıp çalışmadığına bakalım.
1 2 3 | # ps -aux | grep php domain.+ 23383 0.0 0.0 364104 7580 ? S Mar01 0:00 php-fpm: pool domainadi.com nginx 23384 0.0 0.1 370244 15692 ? S Mar01 0:05 php-fpm: pool www |
çalışan servislerde domainadi.com’u görüyor olmanız lazım. Eğer görüyorsanız işlemlerin büyük kısmı tamamlanmış demektir. Şimdi nginx’in ilgili virtual domain conf dosyasında değişiklik yapalım.
1 2 | # cd /etc/nginx/sites-available/ # nano domainadi.com.conf |
Yukarıdaki conf dosyası sizin domainadi.com sitenize ait NGINX conf dosyasıdır. Az önceki php-fpm conf dosyası ile karıştırmayınız. /etc/nginx/sites-available/ içerisindeki conf dosyası sizin nginx sürümünüze göre farklılık gösterebilir. Bu nedenle farklı klasör veya isimlerde olabilir. Her sunucuya özgün klasör adları da olabilir. Bu nedenle bu dosyayı sizin bulmanız gerekiyor.
İlgili conf dosyası içerisinde
1 2 3 4 5 | fastcgi_pass unix:/run/php-fpm/php7.1-fpm-www.sock; yukarıdaki alanı aşağıdaki gibi değiştirin, kaydedip çıkın. fastcgi_pass unix:/run/php-fpm/domainadi.com.sock; |
Evet son olarak nginx’in çalışıp çalışmadığını nginx -t yaparak kontrol edin. Eğer çalışıyorsa systemctl restart nginx diyerek nginx’i restart edin. Hatasız değişiklikler meydana gelmişse, çalışacaktır.
Bir sonraki yazıda görüşmek üzere…