Взял тут: http://itix.pp.ua/2011/02/16/%D0%B7%D0%B0%D0%BC%D0%B5%D1%82%D0%BA%D0%B8-%D0%BF%D0%BE-%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D0%B9-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B5-apache2nphp/
C тех пор, как на личном сервере поселился не только мой сайт с личными заметками, то встал вопрос о безопасности. Хотя бы потому, что продвинутый файловый менеджер на php+ajax при определенной настройке имел доступ к любому файлу на сервере, хоть и с правами только на чтение, что не есть айс (если не сказать, что это реальное дырище). Итак, я поступил следующим образом...
Как выяснилось, при должной настройке апач может запускать каждый виртуальный хост от имени определенного юзера. Таким образом при теоретическом взломе одного из хостов мы оградим взломщика от других хостов. Пересоберем апач с данной возможностью, за которую отвечает флаг APACHE2_MPMS="itk". Его, в принципе, можно вписать прямиком в /etc/make.conf.
На момент настройки на сервере присутствовало два вирт.хоста (здесь назовем их site1 и site2), используя их я заодно продемонстрирую настройку и вирт.хостов. Виртуальные хосты прописываем в /etc/apache2/vhosts.d/00_default_vhost.conf:
<VirtualHost *:80>
ServerName site1
DocumentRoot /var/www/localhost/htdocs/site1
<Directory /var/www/localhost/htdocs/site1>
Options all
Options -Indexes #не разрешаем просматривать содержимое каталогаOrder deny,allow
Deny from all
Allow from 127.0.0.1 #делаем так, что бы нельзя было зайти на сайт мимо nginx, указав порт апачаAllowOverride FileInfo Limit AuthConfig #разрешаем переназначать только определенный набор директив в пользовательских .htaccess</Directory>
</VirtualHost><VirtualHost *:80>
ServerName site2
DocumentRoot /var/www/localhost/htdocs/site2
<Directory /var/www/localhost/htdocs/site2>
Options all
Options -Indexes #не разрешаем просматривать содержимое каталогаOrder deny,allow
Deny from all
Allow from 127.0.0.1 #делаем так, что бы нельзя было зайти на сайт мимо nginx, указав порт апача
AllowOverride FileInfo Limit AuthConfig #разрешаем переназначать только определенный набор директив в пользовательских .htaccess</Directory>
</VirtualHost>
Так же указываем апачу, что он должен работать с вирт.хостами:
nano -w /etc/conf.d/apache2
Ищем строчку APACHE2_OPTS и, учитывая, что апач работает и с php, то общий вид строки будет (возможно опций у вас будет больше в силу конкретной настройки):
APACHE2_OPTS="-D DEFAULT_VHOST -D PHP5"
Проверяем каждый из хостов, все должно работать.
Т.к. каждый из хостов работает под своим юзером, добавим их в систему (папки у меня уже созданы, поэтому опцию -m не использовал):
useradd site1 -d /var/www/localhost/htdocs/site1 -U -s /bin/false
useradd site2 -d /var/www/localhost/htdocs/site1 -U -s /bin/false
Теперь раздаем права папкам. Идеология принципа раздачи прав у каждого может немного отличаться. Но тем не менее главное, что бы у группы other не было прав на запись. Идеально конечно вообще группе other выдать нулевые права, но в моем случае перед апачем работает еще и nginx, то с нулевыми правами на other он не сможет напрямую выдать клиенту статические файлы.
Сначала сменим владельцев:
chown -R site1:site1 /var/www/localhost/htdocs/site1
chown -R site2:site2 /var/www/localhost/htdocs/site2
Выдаю права:
chmod -R 775 /var/www/localhost/htdocs/site1
chmod -R 775 /var/www/localhost/htdocs/site2
Но к статическим файлам ведь не относятся php файлы. Посему конкретно на них и выставим права 770 следующей командой:
find /var/www/localhost/htdocs/site1 -name *.php | xargs chmod 770
find /var/www/localhost/htdocs/site1 -name *.php | xargs chmod 770
Можно эти команды в cron добавить дабы новые файлы тоже были с верными правами.
Пора настроить апач.
К каждому вирт.хосту привязываем своего пользователя. Для этого в конфиге вирт.хостов следует дописать AssignUserId site1 site1 и AssignUserId site2 site2 для каждого из хостов. В итоге получится:
<VirtualHost *:80>
ServerName site1
DocumentRoot /var/www/localhost/htdocs/site1
AssignUserId site1 site1
<Directory /var/www/localhost/htdocs/site1>
Options all
Order deny,allow
Deny from all
Allow from 127.0.0.1
AllowOverride all
</Directory>
</VirtualHost><VirtualHost *:80>
ServerName site2
DocumentRoot /var/www/localhost/htdocs/site2
AssignUserId site2 site2
<Directory /var/www/localhost/htdocs/site2>
Options all
Order deny,allow
Deny from all
Allow from 127.0.0.1
AllowOverride all
</Directory>
</VirtualHost>
Скрываем информацию, т.к. сервер может выдавать слишком много информации о себе. В этот раз настройки нашлись в /etc/apache2/modules.d/00_default_settings.conf. Проверяем записи, которые должны выглядеть так:
ServerTokens Prod
ServerSignature Off
Неплохо бы иметь фильтр от нежелательных команд/символов в GET запросе, ибо полностью полагаться на писателя php-кода мы никогда не сможем. И такой фильтр существует в виде модуля:
emerge -av mod_security
Этот модуль действует согласно правилам, которые вы и напишете (об этом в интернете полно статей). Тем не менее в репозитариях генту прилагается (и ставится с модулем) неплохой набор рабочих правил. Активируем модуль, приведя строку APACHE2_OPTS в /etc/conf.d/apache2 к такому виду:
APACHE2_OPTS="-D DEFAULT_VHOST -D PHP5 -D SECURITY"
Подредактируем наши вирт.хосты, итоговый вид:
<VirtualHost *:80>
ServerName site1
DocumentRoot /var/www/localhost/htdocs/site1
AssignUserId site1 site1
SecAuditEngine On #включаем подробное логированиеSecAuditLog /путь/к/папке/логов/site1.audit.log
SecDebugLog /путь/к/папке/логов/site1.debug.log
<Directory /var/www/localhost/htdocs/site1>
Options all
Order deny,allow
Deny from all
Allow from 127.0.0.1
AllowOverride all
</Directory>
</VirtualHost><VirtualHost *:80>
ServerName site2
DocumentRoot /var/www/localhost/htdocs/site2
AssignUserId site2 site2
SecAuditEngine On #включаем подробное логированиеSecAuditLog /путь/к/папке/логов/site2.audit.log
SecDebugLog /путь/к/папке/логов/site2.debug.log
<Directory /var/www/localhost/htdocs/site2>
Options all
Order deny,allow
Deny from all
Allow from 127.0.0.1
AllowOverride all
</Directory>
</VirtualHost>
Но дефолтные правила, это дефолтные правила. Как оказалось они блокируют работу phpmyadmin (что логично, ибо скрипт работает напрямую с БД, что распознается как sql атака). Как вариант, поместить в отдельную папку и назначить на нее отдельные права. Редактируем /etc/apache2/vhosts.d/00_default_vhost.conf и добавляем после всех наших вирт.хостов следующую запись:
<Directory /путь/к/папке/phpmyadmin>
SecRuleEngine Off #отключаем модуль (здесь следует обратить внимание, что синтаксис и семантика модуля 2й версии отличается от 1й версии; эта директива работает для модуля 2й версии)Order deny,allow
Allow from 1.1.1.1 #разрешаем заходить только с определенного ipDeny from all
</Directory>
Переходим к настройке php.
Думаю многие слышали о директиве safe_mode. Что это такое? При включении безопасного режима (safe_mode) ограничивается использование некоторых потенциально опасных возможностей PHP. Для включения или выключения безопасного режима параметру safe_mode присваивается значение on или off. Механизм ограничения основан на сравнении идентификатора пользователя (UID) выполняющегося сценария с идентификатором пользователя того файла, к которому этот сценарий пытается обратиться. Если идентификаторы совпадают, функция выполняется; в противном случае попытка завершается неудачей. Безопасный режим не может использоваться в том случае, если PHP откомпилирован в виде модуля Apache. Дело в том, что при работе PHP в режиме модуля Apache все сценарии PHP работают под тем же идентификатором, что и Apache, что не позволяет различать владельцев разных сценариев. Соответствующую информацию по настройке при использовании модуля надо искать отдельно. В частности, при включении безопасного режима действуют следующие ограничения:
- Функции ввода/вывода (в частности, fopen ( ), filе( ) и include ( )) работают только с файлами, принадлежащими владельцу сценария. Предположим, в безопасном режиме сценарий, принадлежащий пользователю site1, вызывает функцию fopen( ). Если функция попытается открыть файл, принадлежащий site2, ее вызов завершится неудачей. Но если site1 принадлежит как сценарий, вызывающий fopen( ), так и открываемый файл, все будет нормально.
- Запуск внешних сценариев функциями popen( ), system( ) или ехес( ) разрешается лишь в том случае, если запускаемый сценарий находится в каталоге, определяемом параметром safe_mode_exec_dir.
- Новые файлы создаются только в каталогах, принадлежащих владельцу сценария.
- Аутентификация HTTP становится более жесткой, поскольку в ней также учитывается UID аутентифицирующего сценария.
- Имя пользователя, использованное при подключении к серверу MySQL, должно совпадать с именем владельца файла, вызывающего mysql_connect( ).
Полный список функций, на которые распространяется безопасный режим: chgrp, include, require, chmod, link, rmdir, chown, passthru, symlink, exec, popen, system, fopen, readfile, unlink, file, rename.
Вроде все вышеописанное очень красиво. Если бы не одно но - safe_mode полная лажа
(да и не подойдет в моем случае, ибо у меня собрано модулем). Обходится в два счета, и в следующем поколении php (php 6) его планируется вообще убрать. А иногда активация данного режима не позволяет работать вполне "законным" скриптам.
Посему воспользуемся директивой php, которая позволяет запретить перечисленные в ней команды. Внесем ее сразу в php.ini дабы распространение имело место на все виртуальные хосты. Так как php у меня собран модулем, то:
nano -w /etc/php/apache2-php5.3/php.ini #путь может отличаться в зависимости от версии, у меня, как видите 5.3
Находим строку disable_functions и приведем ее к виду:
disable_functions ="popen, exec, system, passthru, proc_open, shell_exec, apache_get_modules, apache_get_version, apache_getenv, apache_note, apache_setenv, disk_free_space, diskfreespace, dl, highlight_file, ini_alter, ini_restore, openlog, proc_nice, show_source, symlink, phpinfo"
Мною был выбран именно этот перечень. Вам ничего не мешает этот перечень изменить по вкусу. Тем, кто задаст вопрос "а не повлияет ли такое ограничение на работу всякого рода CMS?", отвечу - тестировал на Drupal, DLE, WordPress, Joomla, проблем не обнаружено.
Так же отключаем всякого рода сообщения о php-ошибках в том же php.ini. На продакшн сервере им не место:
track_errors = Off
display_errors = Off
Запрещаем регистрировать глобальные переменные (в php.ini) т.к. это огромная дыра в безопасности (при наличии плохо защищенного скрипта):
register_globals = Off
Теперь запрещаем php выходить выше пользовательской домашней директории. Эти ограничения пропишем отдельно для каждого вирт.хоста в настройках апача, таким образом продемонстрирую работу некоторых полезных директив.
Для работы с php в конфигурационных файлах Apache доступны 4 директивы: php_value, php_flag, php_admin_value, php_admin_flag, которые отличаются значимостью, типом устанавливаемых значений и местом применения.
Директивы php_value и php_flag могут быть переопределены в пользовательских файлах .htaccess или пользовательских скриптах (при наличии соответствующих привилегий AllowOverride).
Директивы php_admin_value и php_admin_flag могут быть переопределены т.е. устанавливаются жестко.
Директивы php_flag и php_admin_flag служат для установки логических значений директив php.ini.
Синтаксис директив php_flag и php_admin_flag:
php_flag имя_директивы_php On|Off
php_admin_flag имя_директивы_php On|Off
Директивы php_value и php_admin_value служат для установки строковых и числовых значений директив php.ini, т.е. любых типов значений, за исключением логических.
Синтаксис директив php_value и php_admin_value:
php_value имя_директивы_php значение
php_admin_value имя_директивы_php значение
Вернемся к нашей настройке. Ограничим каждый вирт.хост его каталогом:
php_admin_value open_basedir "/путь/к/каталогу/сайта/:."
Назначим папку для временных загрузок, ибо после применения open_basedir аплоад некоторых движков может не работать (не забываем предварительно создать оную папку и сделать ей chmod 770):
php_admin_value upload_tmp_dir "/путь/к/каталогу/сайта/tmp"
Ограничиваем область работы php функций require(), include() и fopen_with_path() домашней папкой сайта:
php_admin_value include_path .:/путь/к/каталогу/сайта
Определяем директиву, отвечающую за путь к хранилищу файлов сессий:
php_admin_value session.save_path "/путь/к/каталогу/сайта/tmp"
Ограничим объем выделяемой памяти для пользовательских скриптов. Это важный параметр, так как он предотвращает перегрузку сервера из-за ошибок в скриптах, вызывающих неограниченное использование памяти. Так же этим мы уменьшаем опасность “DoS” атак:
php_admin_value memory_limit "128M"
Запрещаем открывать соединения с внешними серверами с помощью функций fopen(), file() и т.д.:
php_admin_value allow_url_fopen off
Указываем, что скрипт нужно обрывать после 30 секунд работы. Эта опция важна для предотвращения зацикливаний, а так же снижает опасность “DoS” атак на сервер:
php_admin_value max_execution_time 30
Так же для удобства разрешим использование сокращенного синтаксиса в php:
php_flag short_open_tag on
И на всякий случай отключим отображение ошибок в момент запуска php:
php_flag display_startup_errors off
В итоге у нас получилось:
<VirtualHost *:80>
ServerName site1
DocumentRoot /var/www/localhost/htdocs/site1
AssignUserId site1 site1
php_admin_value open_basedir "/var/www/localhost/htdocs/site1/:."
php_admin_value upload_tmp_dir "/var/www/localhost/htdocs/site1/tmp"
php_admin_value include_path .:/var/www/localhost/htdocs/site1
php_admin_value session.save_path "/var/www/localhost/htdocs/site1/tmp"
php_admin_value memory_limit "128M"
php_admin_value allow_url_fopen off
php_admin_value max_execution_time "30"
php_flag short_open_tag on
php_flag display_startup_errors off
<Directory /var/www/localhost/htdocs/site1>
Options all
Order deny,allow
Deny from all
Allow from 127.0.0.1
AllowOverride all
</Directory>
</VirtualHost><VirtualHost *:80>
ServerName site2
DocumentRoot /var/www/localhost/htdocs/site2
AssignUserId site2 site2
php_admin_value open_basedir "/var/www/localhost/htdocs/site2/:."
php_admin_value upload_tmp_dir "/var/www/localhost/htdocs/site2/tmp"
php_admin_value include_path .:/var/www/localhost/htdocs/site2
php_admin_value session.save_path "/var/www/localhost/htdocs/site2/tmp"
php_admin_value memory_limit "128M"
php_admin_value allow_url_fopen off
php_admin_value max_execution_time "30"
php_flag short_open_tag on
php_flag display_startup_errors off
<Directory /var/www/localhost/htdocs/site2>
Options all
Order deny,allow
Deny from all
Allow from 127.0.0.1
AllowOverride all
</Directory>
</VirtualHost>
Что будет, если взломщик во временную папку закачает через дырявый скрипт свой скрипт (далеко не первой полезности)? Поэтому надругаемся над этой папкой. Итоговый вид нашей конфигурации:
<VirtualHost *:80>
ServerName site1
DocumentRoot /var/www/localhost/htdocs/site1
AssignUserId site1 site1
php_admin_value open_basedir "/var/www/localhost/htdocs/site1/:."
php_admin_value upload_tmp_dir "/var/www/localhost/htdocs/site1/tmp"
php_admin_value include_path .:/var/www/localhost/htdocs/site1
php_admin_value session.save_path "/var/www/localhost/htdocs/site1/tmp"
php_admin_value memory_limit "128M"
php_admin_value allow_url_fopen off
php_admin_value max_execution_time "30"
php_flag short_open_tag on
php_flag display_startup_errors off
<Directory /var/www/localhost/htdocs/site1>
Options all
Order deny,allow
Deny from all
Allow from 127.0.0.1
AllowOverride all
</Directory>
<Directory /var/www/localhost/htdocs/site1/tmp>
Order allow,deny
Deny from all
php_flag engine 0 #отключаем php интерпретаторAddType "text/html" .php .cgi .pl .fcgi .fpl .phtml .shtml .php2 .php3 .php4 .php5 .asp .jsp .inc .class #все перечисленные расширения открывать как обычный текстовый файл
Options None
AllowOverride None #на случай злоумышленного закачивания .htaccess файла просто его отключить</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName site2
DocumentRoot /var/www/localhost/htdocs/site2
AssignUserId site2 site2
php_admin_value open_basedir "/var/www/localhost/htdocs/site2/:."
php_admin_value upload_tmp_dir "/var/www/localhost/htdocs/site2/tmp"
php_admin_value include_path .:/var/www/localhost/htdocs/site2
php_admin_value session.save_path "/var/www/localhost/htdocs/site2/tmp"
php_admin_value memory_limit "128M"
php_admin_value allow_url_fopen off
php_admin_value max_execution_time "30"
php_flag short_open_tag on
php_flag display_startup_errors off
<Directory /var/www/localhost/htdocs/site2>
Options all
Order deny,allow
Deny from all
Allow from 127.0.0.1
AllowOverride all
</Directory>
<Directory /var/www/localhost/htdocs/site2/tmp>
Order allow,deny
Deny from all
php_flag engine 0 #отключаем php интерпретаторAddType "text/html" .php .cgi .pl .fcgi .fpl .phtml .shtml .php2 .php3 .php4 .php5 .asp .jsp .inc .class #все перечисленные расширения открывать как обычный текстовый файл
Options None
AllowOverride None #на случай злоумышленного закачивания .htaccess файла просто его отключить</Directory>
</VirtualHost>
Так же стоит обратить внимание, на то что помимо "*.php", есть еще два расширения, определяющие PHP сценарии: "*.inc" и "*.class". Программисты часто включают дополнительные файлы, с этими расширением. Поскольку, по умолчанию, файлы с этими расширениями обрабатываются как постоянные файлы, то их загрузка покажет исходный текст, содержащийся в них. Это может привести к раскрытию различного рода чувствительной информации:
nano -w /etc/apache2/modules.d/70_mod_php5.conf
И приводим примерно к такому виду:
<IfDefine PHP5>
<IfModule !mod_php5.c>
LoadModule php5_module modules/libphp5.so
</IfModule>
<IfModule mod_mime.c>
AddHandler application/x-httpd-php .php .php5 .phtml .inc .class
AddHandler application/x-httpd-php-source .phps
</IfModule>
DirectoryIndex index.php index.phtml
</IfDefine>
Кроме всего этого сервер выдает один не приятный заголовок, который появляется когда информация выводится с помощью php скрипта и рапортует о версии php интерпретатора. Исправим это дело в /etc/php/apache2-php5.3/php.ini. Найдем опцию и приведем к виду:
expose_php = Off
Так же есть одна небезопасная опция, которая должна быть выключена (правда она касается больше связки nginx + fastcgi):
cgi.fix_pathinfo 0
Если вкратце, то она преобразует /scripts/1px.gif/test.php в /scripts/1px.gif. Размещение графических файлов в неверном месте оставим на совести программиста, но обезопасить себя надо.
Не оставим без внимания механизм создания идентификаторов сессий. При использовании веб-приложением стандартных сессий PHP есть возможность их предугадывать. Директива session.entropy_file задаёт путь ко внешнему ресурсу (файлу), который будет использован как дополнительный источник в процессе создания session id. Указание /dev/random или /dev/urandom, которые доступны на многих Unix-системах - хорошая практика.
И последнее - правда это уже больше касается аспектов программирования. И тем не менее.
magic_quotes_gpc = Off
magic_quotes_runtime = Off
magic_quotes_sybase = Off
magic_quotes - это процесс автоматического экранирования входящих данных PHP-скрипта. Желательно отключать директиву magic quotes и вместо этого экранировать данные в процессе разработки, если это необходимо. Если эта опция включены, то все символы ' (одиночные кавычки), » (двойные кавычки), \ (обратный слэш) и NULL автоматически экранируются обратным слэшем.
Существует три вида директив волшебных кавычек:
- magic_quotes_gpc - Воздействует на данные HTTP-запроса (GET, POST и COOKIE). Не может быть изменена во время выполнения
- magic_quotes_runtime - большинство функций, которые возвращают данные из внешнего источника, включая базы данных и текстовые файлы, будут экранировать кавычки с помощью обратного слэша. для данных, поступающих во время выполнения (например, данные из SQL, из exec() и т.д)
- magic_quotes_sybase - одиночная кавычка экранируется одиночной кавычкой вместо обратного слэша. данная опция полностью перекрывает установкуmagic_quotes_gpc. В случае, если включены обе директивы, выполняется экранирование только одиночных кавычек с помощью ». Двойные кавычки, обратные слэши, значение NULL останутся нетронутыми и неэкранированными. в стиле Sybase (экранирование ' с помощью '' вместо \').
Настройка nginx
Скрываем версию. Открываем /etc/nginx/nginx.conf и вовнутрь секции http дописываем:
server_tokens off;
Взломщики могут использовать ботов для сканирования подсетей и поиска уязвимых Web-серверов. Обычно боты просто перебирают диапазоны IP-адресов в поисках открытых 80 портов и посылают запрос HEAD для получения информации о веб-сервере (или главной странице). Можно легко предотвратить такой скан, запретив обращение к серверу по IP-адресу (добавить в подсекцию location):
if ($host !~ ^(site1|www.site1|site2|www.site2)$ ) {return 444;}
Некоторые боты используют различные методы обращения к серверу для попытки определения его типа и/или проникновения, однако в документе RFC 2616 четко сказано, что Web-сервер не обязан реализовывать их все, и неподдерживаемые методы могут просто не обрабатываться. Сегодня используемыми остаются только методы GET (запрос документа), HEAD (запрос заголовков сервера) и POST (запрос на публикацию документа), поэтому все остальные можно безболезненно отключить с помощью помещения следующих строк в секцию server конфигурационного файла:
if ($request_method !~ ^(GET|HEAD|POST)$ ) {return 444;}
Приведу еще пару приемчиков, которые сам лично не использовал, но на заметку взять можно.
Другой способ блокирования ботов, сканеров и прочей нечисти основан на определении типа клиента (user-agent). Он не слишком эффективен, потому как большинство ботов косят под вполне легитимные браузеры, но в ряде случаев остается полезным (помещаем в секцию server):
if ($http_user_agent ~* LWP::Simple|BBBike|wget|msnbot|scrapbot) {return 403;}
Если твой сайт публикует Web-логи в общедоступном виде, ты легко можешь стать жертвой Referrer-спама (когда спам-боты обращаются к твоему серверу, указывая в заголовке referrer – адрес рекламируемого сайта). Такой вид спама может легко испортить SEO-рейтинги интернет-страницы, поэтому его необходимо блокировать в обязательном порядке. Один из способов сделать это – занести наиболее частые слова, встречающиеся в адресах рекламируемых сайтов, в черный список (помещаем в секцию server):
if ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) ) {return 403;}
Хотлинк – это включение в страницу изображения (или иного контента) с другого сайта. По сути, это воровство, потому как изображение, на которое ты потратил не один час своего свободного времени, не только свободно используется другими, но и создает нагрузку на твой Web-сервер, не приводя на него посетителей. Для борьбы с хотлинками достаточно сделать так, чтобы изображения отдавались клиенту только в том случае, если он запросил их, уже находясь на сайте (другими словами, заголовок referrer-запроса должен содержать имя нашего сайта). Добавляем в секцию server конфигурационного файла nginx.conf следующие строки:
location /путь/к/папке/с/картинками {valid_referers none blocked www.site1 site1 www.site2 site2; if ($invalid_referer) {return 403;}}
В качестве альтернативы можно настроить сервер на отдачу специального баннера с сообщением о воровстве вместо запрашиваемого изображения. Для этого заменим строку return 403 на строку:
rewrite ^/путь/к/папке/с/картинками.*\.(gif|jpg|jpeg|png)$ http://site1/наш_баннер.jpg last
Таким образом спать можно немножко спокойней
Данные советы не являются окончательными, безопасности никогда не бывает много.
Комментариев нет:
Отправить комментарий