Сервер Apache: Как ограничить доступ к сайту по IP адресам

There is no translation available.

Как ограничить доступ к сайту

Ограничение доступа можно настроить на уровне:

 
  • всего веб-сервера
  • виртуального хоста (одного сайта)
  • одной или нескольких папок сайта

Показанные ниже настройки можно вносить в конфигурационный файл Apache, а также в файл .htaccess. На большинстве хостингов мы не можем менять настройки веб-сервера, но при этом также на большинстве хостингов для владельцев сайтов включена поддержка файла .htaccess. Поэтому в этой инструкции я будут показывать примеры ограничения доступа с использованием файла .htaccess. Вы можете создать (если его ещё нет) этот файл в корне вашего сайта – и тогда вносимые изменения будут распространятся на весь сайт, в том числе на вложенные папки, либо вы можете создать этот файл в любой папке вашего сайта – тогда настройки, сделанные в .htaccess, будут иметь силу только в папке, где размещён этот файл, и во всех вложенных в эту папку подпапках.

Контроль доступа в Apache 2.4 и Apache 2.2

В Apache 2.2 используются директивы AllowDeny и Order, которые обеспечиваются старой версией модуля mod_access_compat. Для версии Apache 2.4 они являются устаревшими и будут убраны в будущих релизах Apache.

Для серии Apache 2.2.x полностью остановлена разработка и выпуск патчей, в том числе относящихся к безопасности. Последний релиз 2.2.34 вышел в июле 2017 и начиная с 2018-01-01 больше никаких оценок безопасности и выпуска патчей не будет.

Данная инструкция предназначена для Apache 2.4. Если вы попытаетесь использовать описанные здесь примеры на Apache 2.2, то получите ошибку:

1
2
Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.

Рекомендуется пользоваться современным программным обеспечением. Тем не менее, если у вас Apache 2.2 и вы не можете это изменить (например, сайты работают на общем (shared) хостинге), то посмотрите несколько примеров с Allow, Deny и Order в конце статьи. Но не используйте их на современных версиях Apache!

Контроль доступа к сайту по IP

Как запретить доступ к сайту или папке по IP

Чтобы закрыть доступ к сайту с определённых IP адресов используйте следующую конструкцию:

1
2
3
4
<RequireAll>
    Require all granted
    Require not ip 213.167.206.7
</RequireAll>

Вместо 213.167.206.7 подставьте IP адрес, которому вы хотите заблокировать вход на ваш сайт.

Вы можете указать несколько адресов:

1
2
3
4
5
6
<RequireAll>
    Require all granted
    Require not ip 213.167.206.7
    Require not ip 195.254.134.242
    Require not ip 193.169.145.202
</RequireAll>

И для каждого из этих адресов будет закрыт доступ на сайт.

Эта запись равнозначна следующей записи, когда IP адреса перечисляются в одну строку через пробел:

1
2
3
4
<RequireAll>
    Require all granted
    Require not ip 213.167.206.7 195.254.134.242 193.169.145.202
</RequireAll>

Как для всех закрыть доступ к сайту

Чтобы полностью закрыть доступ к сайту для всех (например, на время обслуживания или других работ), используйте директиву:

1
Require all denied

Обратите внимание, что для неё не требуется конструкции <RequireAll>…</RequireAll>.

Как запретить доступ к сайту для диапазона адресов

Чтобы закрыть доступ к подсети, т.е. для диапазона адресов, можно использовать часть IP адреса:

1
2
3
4
<RequireAll>
    Require all granted
    Require not ip 213.167
</RequireAll>

Можно указывать часть IP адреса несколько раз и для каждой подсети будет ограничен доступ:

 
1
2
3
4
5
6
<RequireAll>
    Require all granted
    Require not ip 213.167.206
    Require not ip 195.254
    Require not ip 193
</RequireAll>

Для более точного указания подсетей можно использовать нотацию с маской подсети вида a.b.c.d и маска w.x.y.z:

1
2
3
4
<RequireAll>
    Require all granted
    Require not ip 10.1.0.0/255.255.0.0
</RequireAll>

Также поддерживается спецификация CIDR вида сеть/nn:

1
2
3
4
<RequireAll>
    Require all granted
    Require not ip 10.1.0.0/16
</RequireAll>

Последние две записи равнозначны (обозначают одинаковый диапазон IP адресов).

Как запретить доступ к сайту или папке по имени хоста

Если вам нужно закрыть доступ по имени хоста, то это делается следующим образом:

1
2
3
4
<RequireAll>
        Require all granted
        Require not host hostwindsdns.com
</RequireAll>

Можно указывать сразу по нескольку хостов:

1
2
3
4
5
<RequireAll>
        Require all granted
        Require not host hostwindsdns.com
        Require not host 47-50-159-110.static.olve.mo.charter.com
</RequireAll>

Как и с IP адресами, можно указывать только часть доменного имени, например, в следующем примере заблокированы все хосты, в чьём имени имеется «gov»:

1
2
3
4
<RequireAll>
        Require all granted
        Require not host gov
</RequireAll>

Можно комбинировать имена хостов, IP адреса, части имён хостов и IP адресов:

1
2
3
4
5
6
<RequireAll>
        Require all granted
        Require not ip 192.168.205
        Require not host phishers.example.com moreidiots.example
        Require not host gov
</RequireAll>

Как запретить доступ к сайту для определённых IPv6

Для IPv6 поддерживаются различные формы записи, в том числе сокращённые и использованием маски подсети:

1
2
3
4
5
6
7
<RequireAll>
        Require all granted
        Require not ip 2001:db8::a00:20ff:fea7:ccea
        Require not ip 2001:db8:1:1::a
        Require not ip 2001:db8:2:1::/64
        Require not ip 2001:db8:3::/48
</RequireAll>

Как разрешить доступ к сайту только для локальных адресов и запретить для всех остальных

Если вам нужно ограничить доступ для всех IP, кроме локальных, то используйте:

1
Require local

Доступ будет разрешён только если истинно одно из следующих условий:

  • адрес клиента соответствует 127.0.0.0/8
  • адрес клиента ::1
  • адрес клиента и сервера подключения одинаковы

Это удобный способ определить подключения, которые исходят от локального хоста.

Обратите внимание, что в данном случае не считаются локальным адреса вида 192.168.*.* и 10.*.*.* и т.п., которые также являются частными (немаршрутизируемыми).

В предыдущих примерах мы разрешали доступ всем, кроме определённых, заранее указанных IP. Теперь будет показано, как запретить доступ всем, кроме определённых IP. Обратите внимание, что для этого нам не требуется конструкции <RequireAll>…</RequireAll>. Я расскажу, почему это так в этой же статье чуть позже. А также мы познакомимся с ещё двумя директивами.

Как разрешить доступ к сайту или папке определённому IP

Чтобы к папку или сайт мог открыть только хост с разрешённым IP используйте:

1
Require ip 10.1.2.3

Замените 10.1.2.3 на IP, которому вы хотите открыть доступ.

Можно указать несколько IP адресов:

1
2
Require ip 10.1.2.3
Require ip 213.167.206.7

IP адреса можно указать в одну строку через пробел:

1
Require ip 10.1.2.3 213.167.206.7

Можно указывать IPv6 адреса:

1
2
Require ip 2001:db8::a00:20ff:fea7:ccea
Require ip 2001:db8:1:1::a

Напомню, аналог localhost в IPv6 это ::1/128 (0:0:0:0:0:0:0:1). То есть если вы хотите разрешить доступ IPv6 соответствующим localhost, то добавьте следующую строку:

1
Require ip ::1

Как разрешить доступ к сайту диапазону IP

Можно указать часть адреса, в том числе несколько адресов через пробле или несколько раз использовать Require ip:

1
2
Require ip 10.1
Require ip 10 172.20 192.168.2

Поддерживаются подсети с масками:

1
Require ip 10.1.0.0/255.255.0.0

И подсети в нотации CIDR:

1
Require ip 10.1.0.0/16

Как разрешить доступ к сайту по имени хоста

Чтобы разрешить доступ одному или нескольким хостам:

1
Require host phishers.example.com moreidiots.example

Можно указать часть имени хоста:

1
Require host gov

Директивы RequireAll, RequireAny и RequireNone

Из приведённых выше примеров, вы могли обратить внимание, что для отрицания используется not. Поскольку not является отрицанием значения, оно не может использоваться само по себе для разрешения или отказа запросу, поскольку not true не составляет false. Таким образом, чтобы отказать визиту, используя отрицание, блок должен иметь один элемент, которые сводится к true или false.

Проще говоря, если вы используете not, то необходимо использовать ещё одно выражение без not. Этим выражением может быть Require all granted (разрешить доступ всем). Чтобы выражения действовали как одно целое, используется одна из трёх директив RequireAllRequireAny или RequireNone.

С RequireAll мы уже знакомы, она объединяет группу директив авторизации, из которых ни одна не должна завершиться неудачей, и хотя бы одна должна завершиться успехом, чтобы вся директива считалась успешной.

Для контроля доступа, например, для блокировки по IP, нам не понадобятся RequireAny или RequireNone, поэтому мы не будем их рассматривать.

Запрет доступа к отдельным файлам

Выше были рассмотрены примеры запрета или разрешения доступа для папок. Но можно настраивать более точные правила – для отдельных файлов или для файлов определённого вида.

Для этого используется директива <Files>. Синтаксис использования:

1
2
3
4
<Files имя_файла>
    ………………
    ………………
</Files>

Вместо имя_файла файла нужно вписать файл, доступ к которому вы хотите отрегулировать. Вместо многоточий могут подставляться любые рассмотренные конструкция контроля доступа по IP.

Запрещение просмотра файлов .htaccess и .htpasswd веб-клиентами

Файлы .htaccess и .htpasswd находятся в директории с файлами сайта, но они не должны попадать в руки пользователю – т.е. при их запросе они не должны скачиваться. Чтобы запретить их скачивание, используйте:

1
2
3
<Files ".ht*">
    Require all denied
</Files>

Приведённый выше пример подходит для Apache 2.4. Для Apache 2.2 нужно писать так:

1
2
3
<Files ".ht*">
    Deny from all
</Files>

Т.е. можно использовать конструкции контроля доступа любой версии.

По умолчанию, в конфигурационном файле Apache уже есть это правило (т.е. обычно не нужно добавлять это правило). Любые попытки получить доступ к файлу .htaccess приведут к ошибке 403.

Аргумент с именем файла может содержать также подстановочные символы: ? (знак вопроса), который соответствует любому единичному символу, * (звёздочка) соответствует любой последовательности символов.

Можно использовать и регулярные выражения, для этого добавьте символ ~, пример:

1
2
3
<Files ~ "\.(gif|jpe?g|png)$">
    #...
</Files>

Предотвращение доступа к определённому файлу

Вы можете указать имя определённого файла, который запрещён для скачивания или открытия пользователями. К примеру, пользователи не должны получить файл _frame.htm. Тогда в Apache 2.4:

1
2
3
<Files _frame.htm>
    Require all denied
</Files>

В Apache 2.2:

1
2
3
<Files _frame.htm>
    Deny from all
</Files>

Предотвращение доступа к файлам нескольких типов

Директива <FilesMatch> работает также как <Files>, но в качестве аргумента принимает регулярные выражения.

Для ограничения доступа к ряду типов файлов, добавьте следующий блок и отредактируйте выражение в скобках, перечислив через трубу (| - в регулярных выражения этот символ означает логическое ИЛИ) расширения файлов, которые вы хотите защитить:

В Apache 2.4:

1
2
3
<FilesMatch "\.(htaccess|htpasswd|ini|phps|fla|psd|log|sh)$">
    Require all denied
</Files>

В Apache 2.2:

1
2
3
<FilesMatch "\.(htaccess|htpasswd|ini|phps|fla|psd|log|sh)$">
    Deny from all
</Files>

Запрет доступ к файлам резервных копий и исходному коду

Эти файлы могут быть оставлены некоторыми текстовыми/HTML редакторами (такими как Vi/Vim) и представляют большую угрозу безопасности, если они открыты публике.

Для Apache 2.4:

1
2
3
<FilesMatch "(\.(bak|config|dist|fla|inc|ini|log|psd|sh|sql|swp)|~)$">
    Require all denied
</FilesMatch>

Для Apache 2.2:

1
2
3
<FilesMatch "(\.(bak|config|dist|fla|inc|ini|log|psd|sh|sql|swp)|~)$">
    Deny from all
</FilesMatch>

Контроль доступа через ограничение определённых HTTP методов

Блокировка HTTP методов

Директива <Limit> позволяет указать, какие именно HTTP методы заблокированы.

Контроль доступа обычно затрагивает все методы доступа – и именно это обычно является желаемым поведением. В большинстве ситуаций, директивы контроля доступа не нужно помещать в секцию <Limit>.

Цель директивы <Limit> – ограничить эффект контроля доступа перечисленными HTTP методами. Для всех других методов ограничения доступа, помещённые в <Limit>, не будут иметь эффекта. Следующий пример применяет контроль доступа только для методов POSTPUT и DELETE, оставляя все другие методы незащищёнными:

1
2
3
<Limit POST PUT DELETE>
    Require all denied
</Limit>

Можно указать один или несколько методов из следующего списка: GET, POST, PUT, DELETE, CONNECT, OPTIONS, PATCH, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK и UNLOCK.

Имена методов чувствительны к регистру.

Если используется GET, то он также ограничить HEAD запросы.

Метод TRACE не может быть ограничен

Разрешение только определённых HTTP методов

Директива <LimitExcept> похожа на <Limit>. Но она ограничивает доступ для всех HTTP методов, кроме перечисленных.

Между <LimitExcept> и </LimitExcept> нужно указать группу директив контроля доступа, которые будут применены к любым методам HTTP доступа, не перечисленным в аргументах; т.е. в отличие от секции <Limit>, эта может использоваться для контроля как стандартных, так и нестандартных/неузнанных методов.

 

Например

1
2
3
<LimitExcept POST GET>
    Require ip 10.1.0.0/16
</LimitExcept>

Эта конструкция разрешит использование только методов POST и GET для пользователей из подсети 10.1.0.0/16; для всех остальных доступ будет закрыт полностью.

Всегда следует отдавать предпочтение секции <LimitExcept>, а не <Limit>. Поскольку секция <LimitExcept> обеспечивает защиту против произвольных методов.

Контроль доступа по произвольным переменным

В Apache 2.4 появилась новая директива <If>, которая очень сильно расширяет возможности сервера. К примеру, эта директива полностью заменяет собой mod_rewrite и умеет намного больше!

Используя <If> вы можете разрешить или запретить доступ на основе произвольных переменных окружения или значений заголовков запроса. К примеру, можно запретить доступ на основе пользовательского агента (user-agent) типа браузера.

Можно использовать фильтрацию на основе значений:

  • HTTP_ACCEPT
  • HTTP_COOKIE
  • HTTP_FORWARDED
  • HTTP_HOST
  • HTTP_PROXY_CONNECTION
  • HTTP_REFERER
  • HTTP_USER_AGENT

Ограничение доступа для определённых ботов (блок по User-Agent)

Чтобы закрыть доступ по строке User-Agent, используйте следующую конструкцию:

1
2
3
<If "%{HTTP_USER_AGENT} == 'BadBot'">
    Require all denied
</If>

Как можно догадаться, будет закрыт доступ клиенту, который в качестве User-Agent отправляет строку 'BadBot'.

Используй синтаксис Require expr это же можно записать следующим образом:

1
Require expr %{HTTP_USER_AGENT} != 'BadBot'

Пример блокировки по User-Agent с помощью mod_rewrite (работает на всех версиях сервера с включённым mod_rewrite):

1
2
3
4
5
6
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} ^HTTrack [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^sqlmap [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^wpscan [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^text [NC]
RewriteRule ^ - [F]

Этот пример блокирует ботов, у которых в качестве User-Agent указано HTTrack, sqlmap, wpscan или text.

Предупреждение: контроль доступа по User-Agent это ненадёжная техника, поскольку User-Agent в заголовке можно установить на любое значение по прихоти конечного пользователя.

Блокировка посетителей с определённым реферером (REFERER)

Вы можете заблокировать посетителя, пришедшего с определённого сайта, для этого используйте конструкцию:

1
2
3
<If "%{HTTP_REFERER} =~ /hatethissite.com/">
    Require all denied
</If>

Вместо hatethissite.com укажите URL, с которого вы не хотите получать посетителей.

Обратите внимание, что в качестве оператора сравнения используется =~, он означает, что строка сравнивается с регулярным выражением. Само регулярное выражение помещено в / …  / и не заключено в кавычки.

Блокировка доступа в определённое время

Директивами сервера можно заблокировать доступ в определённые часы. Это можно сделать как с помощью <If>, так и с помощью mod_rewrite.

Следующий набор директив запрещает доступ с 18 часов до 7 часов утра. При попытке посетить сайт в этот промежуток времени, будет выдан ответ 403 Forbidden (флаг [F]):

1
2
3
4
RewriteEngine On
RewriteCond "%{TIME_HOUR}" ">=18" [OR]
RewriteCond "%{TIME_HOUR}" "<07"
RewriteRule "^" "-" [F]

Кстати, поскольку используется mod_rewrite, то описанный способ применим и в Apache 2.4, и в Apache 2.2.

Контроль доступа в Apache 2.2

Описанные далее директивы сохранены для совместимости и в Apache 2.4. Но их не рекомендуют применять в новых версиях, поскольку они будут удалены. Также будьте осторожны, если вы смешиваете старые и новые директивы, поскольку результат может быть не тем, который вы ожидали – чтобы избежать этой проблемы, изучайте документацию.

Закрытие и разрешение доступа по IP в Apache 2.2

Как запретить доступ к сайту или папке по IP

Чтобы заблокировать доступ к сайту по IP используйте:

1
Deny from 213.167.206.7

Замените 213.167.206.7 на желаемый IP.

Чтобы запретить доступ для нескольких адресов, используйте Deny from несколько раз:

1
2
3
Deny from 185.220.101.34
Deny from 213.167.206.7
Deny from 11.22.33.44

Либо указывайте IP адреса в одну строку через пробел:

1
Deny from 185.220.101.34 213.167.206.7 11.22.33.44

Как для всех закрыть доступ к сайту

Чтобы закрыть доступ абсолютно для всех, используйте:

1
Deny from all

Как запретить доступ к сайту для диапазона адресов

Чтобы закрыть доступ на сайт диапазону IP, можно указывать часть IP адреса:

1
2
Deny from 10.1
Deny from 10 172.20 192.168.2

Для запрещения доступа из нескольких диапазонов, используйте Deny from нужное количество раз, либо пишите адреса в одну строку через пробел.

Поддерживается обозначение в виде пары сеть/маска. Используя этот синтаксис сеть a.b.c.d и сетевая маска w.x.y.z вы можете более точно выбрать диапазон:

1
Deny from 10.1.0.0/255.255.0.0

Также поддерживается спецификация CIDR в виде сеть/nn

1
Deny from 10.1.0.0/16

Как запретить доступ к сайту или папке по имени хоста

Вы можете запретить вход по имени хоста:

1
Deny from apache.org

Это будет работать, если вы укажите часть имени хоста или несколько хостов или частей их имени:

1
Deny from .net example.edu

Как запретить доступ к сайту для определённых IPv6

Пример запрета доступа к сайту для IPv6 2a02:418:6017::148:

1
Deny from 2a02:418:6017::148

Здесь доступны все те же возможности, как и для обычных IP, т.е.:

  • можно указывать по нескольку адресов
  • можно указывать части адресов
  • можно указывать диапазоны адресов в различном формате

Как разрешить доступ к сайту или папке определённому IP

Чтобы разрешить доступ для одного адреса и запретить для всех других, используйте следующую конструкцию:

1
2
3
Order deny,allow
Deny from all
Allow from 213.167.206.7

В ней 213.167.206.7 замените на желаемый адрес.

Можно использовать Allow from несколько раз, либо указать несколько IP адресов через пробел, тогда все они будут разрешены, а остальные адреса – нет:

1
2
3
4
5
Order deny,allow
Deny from all
Allow from 11.22.33.44
Allow from 33.44.55.66
Allow from 213.167.206.7

Это же самое:

1
2
3
Order deny,allow
Deny from all
Allow from 11.22.33.44 33.44.55.66 213.167.206.7

Как разрешить доступ к сайту диапазону IP

Пример разрешения доступа к сайту только для диапазона 213.167.206.0-213.167.206.255:

1
2
3
Order deny,allow
Deny from all
Allow from 213.167.206

Это же самое:

1
2
3
Order deny,allow
Deny from all
Allow from 213.167.206.0/255.255.255.0

Это же самое:

1
2
3
Order deny,allow
Deny from all
Allow from 213.167.206.0/24

Можно указать несколько диапазонов.

Как разрешить доступ к сайту по имени хоста

Вы можете ограничить доступ для всех, но открыть его для одного хоста, указав имя хоста или часть имени:

1
2
3
Order deny,allow
Deny from all
Allow from dev.example.com

Можно указывать несколько имён или частей имён хостов.

Директива Order

Директива Order контролирует состояние доступа по умолчанию и порядок, в котором оцениваются директивы Allow и Deny.

Директива Order, вместе с директивами Allow и Deny, контролирует трёх-проходную систему контроля доступа. Первый проход обрабатывает все директивы Allow или все директивы Deny в том порядке, как они указаны в директиве Order. Второй проход разбирает (парсит) оставшиеся директивы (Deny или Allow). Третий проход применяется ко всем запросам, которые не соответствуют ни одному из первых двух.

Помните, что обрабатываются все директивы Allow и Deny, в отличии от типичного файервола, где используется только первое совпадение. Последнее совпадение является эффективным (также в отличии от типичных файерволов). Дополнительно, порядок, в котором строки появляются в файлах конфигурации, не является важным: все строки Allow обрабатываются как группа, все строки Deny рассматриваются как другая группа, и состояние по умолчанию рассматривается само по себе.

Порядок:

1
Order Allow,Deny
  • означает, что вначале оцениваются все директивы Allow; по крайней мере одна должна совпадать или запросы отвергаются. Далее оцениваются все директивы Deny. Если имеются какие-либо совпадения, запрос принимается. Наконец, запросы, которые не соответствуют ни одной директиве Allow или Deny по умолчанию отбрасываются.

Порядок

1
Order Deny,Allow
  • означает, вначале оцениваются все директивы Deny; если какая-либо совпадает, запрос отбрасывается если он при этом не совпадает с какой-либо директивой Allow. Любые запросы, которые не совпадают с какой-либо директивой Allow или Deny разрешены.

Кроме порядка рассмотрения директив, Order также устанавливает состояние по умолчанию. Т.е. если последним словом идёт Allow, то по умолчанию для всех разрешён вход, если последним словом идёт Deny, то по умолчанию для всех запрещён вход.

Ключевые слова могут быть разделены только запятой, пробелы между ними не разрешены.

СовпадениеРезультат Allow,DenyРезультат Deny,Allow
Совпадает только с AllowЗапрос разрешёнЗапрос разрешён
Совпадает только с DenyЗапрос запрещёнЗапрос запрещён
Нет совпаденияЗначение по умолчанию сводится ко второй директиве: запретЗначение по умолчанию сводится ко второй директиве: разрешение
Совпадает и с Allow, и с DenyДействует последнее совпданеие: ЗапретДействует последнее совпданеие: Разрешено

Рассмотрим НЕПРАВИЛЬНЫЙ пример:

1
Allow from apache.org

По идее, этой строкой мы хотели разрешить доступ только для хоста apache.org. Но этот пример не будет работать как задумано: по умолчанию доступ открыт для всех, и любой может получить доступ к сайту, в том числе и apache.org.

Следующий пример является правильным:

1
2
3
Order Deny,Allow
Deny from all
Allow from apache.org

Строкой Order Deny,Allow устанавливается, что оценка директив начинается с Deny (первый проход). Строка Deny from all запрещает доступ для всех. Состоянием по умолчанию становится запрет доступ для всех. Поскольку используется слово all, то все запросы считаются совпавшими с данным. В результате, когда будет делаться третий проход – установление состояния по умолчанию для запросов, которые ранее не совпали ни с одной директивой, то не будет ни одного такого запроса. Т.е. состояние по умолчанию не окажет эффект на какой-либо запрос. Затем начинается рассмотрение директив с Allow (второй проход), строка Allow from apache.org разрешает доступ для хоста apache.org. Далее делается третий проход – установление состояния для хостов, которые не совпали ни с одним правилом, но как уже было сказано, он не оказывает влияния ни на один запрос, поскольку правило Deny from all сработало для абсолютно всех запросов. Итак, мы получаем то поведение, которые задумано: доступ закрыт для всех, кроме указанного хоста.

Этого же эффекта можно добиться следующим образом:

1
2
Order Allow,Deny
Allow from apache.org

При директиве Order последним словом является Deny, следовательно, состоянием по умолчанию является отказ в доступе. Но если запрос поступил от хоста apache.org, то для него вход открыт. Механизм следующий: в первом проходе обрабатываются директивы с Allow (т.к. это слово идёт первым в Order). В результате, разрешаются запросы с хоста apache.org. Во втором проходе должны бы были обработаться директивы с Deny – но их нет. В третьем проходе устанавливается состояние по умолчанию для запросов, которые не совпали с правилом ни одной из директив, – отклонить их (последним словом является Deny) – а это и есть все запросы, кроме пришедших с хоста apache.org.

Рассмотрим ещё один пример:

1
2
3
Order Allow,Deny
Allow from apache.org
Deny from foo.apache.org

В нём всем хостам с домена apache.org разрешён доступ, кроме хостов, на субдомене foo.apache.org, для которых доступ закрыт, а состоянием по умолчанию является запрет, т.е. всем хостам вход закрыт. Первыми оцениваются директории с Allow, в результате, для хоста apache.org вход открыт. Затем оцениваются директивы с Deny, в результате вход для foo.apache.org закрывается.

По итогу имеем: вход для всех закрыт, но открыт для хостов apache.org, но кроме тех из них, которые пришли с субдомена foo.apache.org.

Поменяем местами Allow и Deny из предыдущего примера:

1
2
3
Order Deny,Allow
Allow from apache.org
Deny from foo.apache.org

В результате мы получим, что доступ для всех хостов открыт (в строке с Order директива Allow идёт последней). Предположим, что пришёл запрос от хоста. В соответствии с указанным порядком обработки, первой будет рассмотрена директива Deny, которая заблокирует доступ foo.apache.org. Но затем будет рассмотрена директива Allow, которая разблокирует доступ для foo.apache.org, поскольку он соответствует указанному хосту apache.org. В результате доступ будет открыт для всех без исключения.

Итак, Order имеет двойной эффект:

  • устанавливает режим доступа по умолчанию
  • определяет порядок, в котором оцениваются директивы Deny и Allow

Уже была упомянута конструкция, которая полностью блокирует доступ для всех:

1
Deny from all

Точно такой же эффект даст

1
Order Allow,Deny

поскольку состоянием по умолчанию становится запрет доступа, и какие-либо  разрешающие директивы отсутствуют.

Следующий пример может показаться правильным, но он НЕВЕРНЫЙ из-за логической ошибки:

1
2
3
Order Deny,Allow
Allow from all
Deny from 185.117.153.79

Казалось бы, автор этой конструкции разрешает доступ для всех, а затем ограничивает доступ для IP 185.117.153.79. Но Order устанавливает, что начинается оценка с директивы Deny, которая запрещает доступ, а затем директива Allow from all разрешает доступ всем, в том числе и 185.117.153.79. В результате не будет заблокирован даже этот IP. Пример правильной конструкции имеется выше.

Контроль доступа по произвольным переменным в Apache 2.2

Ограничение доступа для определённых ботов (блок по User-Agent) в Apache 2.2

Поскольку Apache 2.2 не поддерживает директиву <If>, то для контроля доступа по переменным окружения используется модуль mod_authz_host в паре с with mod_setenvif. Они могут использоваться для закрытия доступа к вашему веб-сайту на основе значения произвольной переменной окружения. Для этого используется синтаксис Allow from env= и Deny from env=.

Помните, что контроль доступа по User-Agent не является надёжной техникой, поскольку конечный пользователь может указать в качестве User-Agent любое значение.

Пример:

1
2
3
4
SetEnvIf User-Agent BadBot GoAway=1
Order allow,deny
Allow from all
Deny from env=GoAway

В этом примере переменная окружения GoAway устанавливается на 1 если User-Agent совпадает с BadBot. Затем мы отклоняем доступ для любых запросов, когда эта переменная установлена. Это блокирует этого конкретного user agent на нашем сайте.

Можно инвертировать (заменить на противоположное) значение результата теста если использовать синтаксис =!:

1
Allow from env=!GoAway

Рассмотрим ещё один пример:

1
2
3
4
5
6
SetEnvIf User-Agent ^KnockKnock/2\.0 let_me_in
<Directory /docroot>
     Order Deny,Allow
     Deny from all
     Allow from env=let_me_in
</Directory>

Третий формат аргументов директивы Allow позволяет контролировать сервер на основе существования переменной окружения. Когда указывается Allow from env=env-variable запрос получает доступ если переменная окружения env-variable существует. Когда указывается Allow from env=!env-variable, запросу разрешён доступ если переменная окружения env-variable не существует. Сервер предоставляет возможность гибко устанавливать переменные окружения на основе характеристики запроса клиента, используя директивы модуля mod_setenvif. Следовательно, эта директива может использоваться для разрешения доступа на основе таких факторов как клиентский User-Agent (тип браузера), Referer или другие поля HTTP заголовков запросов.

Также в Apache 2.2 будет работать способ, показанный выше в пример блокировки по User-Agent с помощью mod_rewrite.

Заключение

Мы рассмотрели контроль доступа, не связанный с аутентификацией и авторизацией. Контроль доступа может основываться на IP, разрешая или блокируя доступ определённым адресам. Такой вариант ограничения доступа на сайт является надёжным.

Также можно ограничивать доступ по произвольным значениям, передаваемым в заголовках запросов, например, можно закрыть сайт для определённых ботов или браузеров. Такой способ ограничения не является надёжным, поскольку его можно легко обойти.

Apache 2.4 имеет свой собственный синтаксис контроля доступа, а также поддерживает синтаксис Apache 2.2. Но для Apache 2.4 рекомендуется использовать именной новый синтаксис, поскольку поддержка старого будет со временем удалена.