Тонка настройка Nginx
Виділений Web-сервер на основі nginx – чудовий спосіб підвищення продуктивності Web-сайтів. У швидкості обробки статичного контенту йому просто немає рівних: він легко витримує кілька тисяч одночасних з'єднань і може бути легко оптимізований та підігнаний під будь-яку конфігурацію. Проте? виступаючи як фронт-енд для Apache, nginx виявляється найбільш вразливим місцем всієї Web-інфраструктури, тому безпеки nginx необхідно приділити особливу увагу.
Пакет nginx доступний у прекомпільованому вигляді для будь-якого дистрибутива. Однак зібравши сервер самостійно, ти зможеш зробити його компактнішим і надійнішим, а також отримаєш можливість змінити рядок вітання Web-сервера, щоб відбити нетямущих скрипт-кідді.
Зміни рядок вітання Web-сервера
Скачай вихідні записи nginx, відкрий файл src/http/ngx_http_header_filter_module.c і знайди наступні два рядки:
static char ngx_http_server_string[] = "Server: nginx" CRLF; static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;
Заміни їх на щось на зразок цього:
static char ngx_http_server_string[] = "Server: ][ Web Server" CRLF; static char ngx_http_server_full_string[] = "Server: ][ Web Server" CRLF;
Видалити всі nginx-модулі, що не використовуються тобою
Деяка частина модулів nginx підключається до Web-серверу безпосередньо під час компіляції, і кожен із них таїть у собі потенційну небезпеку. Можливо, в майбутньому в одному з них буде знайдено вразливість і твій сервер опиниться під загрозою. Вимкнувши непотрібні модулі, ти зможеш значно знизити ризик виникнення такої ситуації.
Виконайте збірку за допомогою наступних команд:
# ./configure --without-http_autoindex_module--without-http_ssi_module # make # make install
Так ти отримаєш nginx із заздалегідь відключеними (і в більшості випадків марними) модулями SSI (Server Side Includes) та Autoindex. Щоб дізнатися, які модулі можна безболісно викинути з Web-сервера, запусти скрипт configure з прапором '—help'.
Препаруємо nginx.conf
Після встановлення nginx слід налаштувати. На сторінках журналу вже був матеріал, що описує цей процес, ми ж дотримуватимемося теми статті та поговоримо про способи підвищення безпеки сервера.
Вимкни показ версії сервера на всіх помилкових сторінках
Додай у файл nginx.conf рядок “server_tokens off”. Це змусить nginx приховувати інформацію про тип та версію Web-сервера на сторінках, що генеруються у відповідь на помилковий запит клієнта.
Налаштувати захист від зриву стека
Додай до секції server наступні рядки:
# Максимальний розмір буфера для зберігання запиту клієнта client_body_buffer_size 1K; # Максимальний розмір буфера для зберігання заголовків запиту клієнта client_header_buffer_size 1k; # Максимальний розмір тіла запиту клієнта, прописаний у полі Content-Length заголовка. Якщо сервер повинен підтримувати завантаження файлів, це значення необхідно збільшити client_max_body_size 1k; # Кількість та розмір буферів для читання великого заголовка запиту клієнта large_client_header_buffers 2 1k;
Зверніть увагу на директиву large_client_header_buffers. За умовчанням, для зберігання рядка URI nginx виділяє чотири буфери, розмір кожного з яких дорівнює розміру сторінки пам'яті (для x86 це 4 Кб). Буфери звільняються щоразу, коли після закінчення обробки запиту з'єднання перетворюється на стан keep-alive. Два буфери по 1 Кб можуть зберігати URI завдовжки лише 2Кб, що дозволяє боротися з ботами та DoS-атаками.
Для підвищення продуктивності додай наступні рядки:
# Таймаут під час читання тіла запиту клієнта client_body_timeout 10; # Таймаут під час читання заголовка запиту клієнта client_header_timeout 10; # Таймаут, після якого keep-alive з'єднання з клієнтом не буде закрито з боку сервера keepalive_timeout 5 5; # Таймаут під час передачі відповіді клієнту send_timeout 10;
Контролюй кількість одночасних з'єднань
Для захисту Web-сервера від перевантаження та спроб здійснити DoS-атаку додай у конфіг наступні рядки:
# Описуємо зону (slimits), де зберігатимуться стану сесій. Зона розміром 1 Мб може зберігати близько 32000 станів, ми встановлюємо її розмір рівним 5 Мб limit_zone $binary_remote_addr 5m; # Задаємо максимальну кількість одночасних з'єднань для однієї сесії. По суті це число задає максимальну кількість з'єднань з одного IP
Перша директива повинна знаходитись у секції HTTP, друга – у секції location. Коли кількість з'єднань вийде межі лімітів, клієнт отримає повідомлення «Service unavailable» з кодом 503.
Дозволь коннект тільки до свого домену
^(host.comwww.host.com)$ ) return 444; >
Обмежити кількість доступних методів звернення до Web-сервера
Деякі роботи використовують різні методи звернення до сервера для спроби визначення його типу та/або проникнення, проте в документі RFC 2616 чітко сказано, що Web-сервер не зобов'язаний реалізовувати їх усі, і непідтримувані методи можуть просто не оброблятися. Сьогодні використовуються тільки методи GET (запит документа), HEAD (запит заголовків сервера) і POST (запит напублікацію документа), тому решту можна безболісно відключити за допомогою приміщення наступних рядків у секцію server конфігураційного файлу:
Відшивай ботів
Інший спосіб блокування ботів, сканерів та іншої нечисті заснований на визначенні типу клієнта (user-agent). Він не надто ефективний, тому що більшість ботів косять під цілком легітимні браузери, але в ряді випадків залишається корисним:
# Блокуємо менеджери завантаження if ($http_user_agent
* LWP::SimpleBBBikewget) return 403; > # Блокуємо деякі типи ботів if ($http_user_agent
* msnbotscrapbot) return 403; >
Блокуй Referrer-спам
# Секція server if ($http_referer
* (Babesforsalegirljewelrylovenuditorganicpokerpornsexteen) ) return 403; >
Блокуй хотлінк
location /images/ valid_referers none blocked www.host.com host.com; if ($invalid_referer) return 403; > >
В якості альтернативи ти можеш налаштувати сервер на віддачу спеціального банера з повідомленням про крадіжку замість зображення, що запитується. Для цього заміни рядок «return 403» на рядок:
rewrite ^/images/uploads.*\.(gifjpgjpegpng)$ http://www.host.com/banned.jpg last
Захищай важливі каталоги від сторонніх
location /uploads/ # Дозволяємо доступ тільки машинам локальної мережі allow 192.168.1.0/24; # Відшиваємо всіх інших deny all; >
Тепер до документів каталогу uploads матимуть доступ лише користувачі локальної мережі. Для встановлення пароля доведеться зробити більш складні дії. Спочатку необхідно створити приватний для nginx-файл паролів і додати до нього необхідних користувачів (як приклад додамо користувача admin):
# mkdir/etc/nginx/.htpasswd # htpasswd -c /etc/nginx/.htpasswd/passwd admin
Далі відкрий файл nginx.conf і впиши до нього наступні рядки:
location /admin/ auth_basic "Restricted"; auth_basic_user_file /etc/nginx/.htpasswd/passwd; >
Нових користувачів можна додати за допомогою наступної команди:
# htpasswd -s /etc/nginx/.htpasswd/passwd користувач
Використовуй SSL
Якщо твій сайт працює з приватними даними користувачів, такими як номери кредитних карток, паролі від інших сервісів, або надає доступ до іншої важливої інформації, яка може стати ласим шматочком для третіх осіб, подбайте про шифрування. Nginx добре працює з SSL, і цією можливістю не можна нехтувати.
Для налаштування SSL-шифрування засобами nginx виконати кілька простих кроків. Спочатку ти маєш створити сертифікат за допомогою наступної послідовності команд:
# cd /etc/nginx # openssl genrsa -des3 -out server.key 1024 # openssl req -new -key server.key -out server.csr # cp server.key server.key. org # openssl rsa -in server.key.org -out server.key # openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Потім описати сертифікат у конфігураційному файлі nginx:
server server_name host.com; listen 443; ssl on; ssl_certificate /etc/nginx/server.crt; ssl_certificate_key /etc/nginx/server.key; access_log /etc/nginx/logs/ssl.access.log; error_log /etc/nginx/logs/ssl.error.log; >
Після цього можна перезавантажити Web-сервер:
Звичайно, без підтримки з боку самого Web-сайту це робити безглуздо.
Інші способи
Встанови правильні значення системних змінних
Відкрий файл /etc/sysctl.conf тапомісти в нього наступні рядки:
# Захист від smurf-атак net.ipv4.icmp_echo_ignore_broadcasts = 1 # Захист від неправильних ICMP-повідомлень net.ipv4.icmp_ignore_bogus_error_responses = 1 # Захист від SYN-ф. ipv4.tcp_syncookies = 1 # Забороняємо маршрутизацію від джерела net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.default.accept_source_route = 0 # Захист від спуфінгу >net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 # Ми не маршрутизатор net.ipv4.ip_forward = 0 net.ipv4. conf.all.send_redirects = 0 net.ipv4.conf.default.send_redirects = 0 # Включаємо ExecShield kernel.exec-shield = 1 kernel.randomize_va_space = 1 # Розширюємо діапазон доступних портів net.ipv4.ip_local_port_range = 2000 65000 # Збільшуємо максимальний розмір TCP-буферів net.ipv4.tcp_rmem = 4096 87380 8388608 net.ipv8t8. 08 net.core.rmem_max = 8388608 net.core.wmem_max = 8388608 net.core.netdev_max_backlog = 5000 net.ipv4.tcp_window_scaling = 1
Розмісти кореневий каталог Web-сервера на виділеному розділі
Помістивши кореневий каталог Web-сервера у виділений розділ і заборонивши розміщення будь-яких виконуваних файлів і файлів-пристроїв, ти убезпечиш решту системи від тих, хто зможе отримати доступ до кореня Web-сервера. При цьому запис у файлі /etc/fstab повинен мати приблизно такий вигляд:
/dev/sda5 /nginx ext4 defaults,nosuid,noexec,nodev 1 2
Помісти nginx в chroot/jail-оточення
Будь-яка сучасна *nix-система дозволяє замкнути програму в ізольованому середовищі виконання. У Linux для цього можна використовувати технології KVM, Xen, OpenVZ і VServer, у FreeBSD – Jail, Solaris – Zones. Якщо жодна з цих технологій недоступна, ти можеш помістити nginx в класичний chroot, який хоч і набагато тендітніший, але більшість зломщиків зупинити зможе.
Встанови правила SELinux для захисту nginx
Хорошою альтернативою ізольованим середовищам виконання є локальні системи виявлення та запобігання вторгненням, такі як SELinux або AppArmor. Будучи правильно налаштованими, вони зможуть запобігти спробам зламування Web-сервера. За дефолтом жодна з них не налаштована для роботи у зв'язці з nginx, проте в рамках проектуSELinuxNginx (http://sf.net/projects/selinuxnginx/) були створені правила для SELinux, які можуть використовувати будь-які бажаючий. Залишається тільки завантажити та встановити:
# tar -zxvf se-ngix_1_0_10.tar.gz # cd se-ngix_1_0_10/nginx # make # /usr/sbin/semodule -i nginx.pp
Налаштування брандмауера
Зазвичай nginx встановлюють на виділених машинах, готових до високого навантаження, тому він залишається єдиним мережевим сервісом, що працює на сервері. Щоб убезпечити сервер, достатньо створити зовсім невеликий набір правил, які будуть відкривати 80, 110 і 143 порти (якщо, звичайно, nginx повинен працювати ще й як IMAP/POP3-проксі) і закривати від зовнішнього світу все інше.
Обмежити кількість з'єднань за допомогою брандмауера
# iptables -A INPUT -p tcp --dport 80 -i eth0 \ -m state --state NEW -m recent --set # iptables -A INPUT -p tcp --dport 80 -i eth0 \ -m state --state NEW -m recent --update \ --seconds 60 --hitcount 15 -j DROP
Правила урізують ліміт на кількість підключень з одного IP на хвилину до 15. Те саме можна зробити і за допомогою pf:
Крім ліміту на кількість послідовних підключень (15 за хвилину), це правило встановлює додатковий ліміт на кількістьодночасних підключень дорівнює 100.
Налаштування PHP
Якщо ти використовуєш nginx у зв'язці з PHP, не забудь налаштувати його. Ось як має виглядати конфігураційний файл /etc/php/php.ini захищеного сервера:
# Відключаємо небезпечні функції disable_functions = phpinfo, system, mail, exec # Максимальний час виконання скрипту max_execution_time = 30 # Максимальний час, який може витратити скрипт на обробку даних запиту max_input_time = 60 # Максимальна кількість пам'яті, що виділяється кожному скрипту memory_limit = 8M # Максимальний розмір даних, що відсилаються скрипту за допомогою методу POST post_max_size = 8M # Максимальний розмір файлів, що завантажуються upload_max_filesize = 2M # Не показувати помилки PHP-скриптів користувачам display_errors = Off # Включаємо Safe Mode safe_mode = On # Включаємо SQL Safe Mode sql.safe_mode = On # Дозволяємо виконувати зовнішні команди тільки в цьому каталозі safe_mode_exec_dir = /шлях/к/захищеному/каталогу # Захищаємось від витоку інформації про PHP expose_php = Off # Ведемо логи log_errors = On # Забороняємо відкриття віддалених файлів allow_url_fopen = Off
Застосувавши описані у статті рекомендації, ти отримаєш набагато більш захищений Web-сервер. Але май на увазі, що не всі техніки підійдуть до твоєї конфігурації. Наприклад, захист від брутфорсу, заснований на урізанні розмірів буферів, що виділяються nginx під обробку запитів клієнтів, може призвести до падіння продуктивності, а в деяких випадках і збоїв в обробці запитів. Обмеження на кількість підключень завдасть сильного удару по продуктивності навіть середньонавантаженого Web-сайту, але принесе користь, якщо сторінка має низький потік відвідувачів. Завжди перевіряй, як внесені тобоюзміни вплинули на продуктивність та загальну працездатність Web-сторінки.