--- title: nginx auth_request (1/3): Вводная tags: nginx, software, devel, репост --- У меня тут накопилось немного опыта работы с этим модулем, решил поделиться. Прежде всего - что это? Это модуль, который разрешает или запрещает прохождение запроса в nginx на основе **подзапроса**. Две основных схемы применения: * с его помощью можно соорудить WAF (web-application firewall) * ...и кастомный портал предварительной авторизации ...всё перечисленное - без модификации исходного сайта. - [Вводная](/articles/2017/05/16/nginx-authreq-1/) - [Многофакторная авторизация, NFA](/articles/2017/05/17/nginx-authreq-2/) - [WAF, Web-Application firewall](/articles/2017/05/18/nginx-authreq-3/) --- Выглядит это примерно так. Вот у нас есть типовой запрос, приходящий на некоторый вебсервер: GET /files/83084_s.jpg HTTP/1.1 Host: example.com User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0 Accept: */* Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive nginx пересылает его сначала на указанный location, затем на основе ответа, решает что делать - пустить дальше или выдать ошибку. Общая схема запросов ([исходник](req-graph.msc)): ![](req-graph.png) Authorizer - это отдельная internal локация nginx'а. Там может быть или `proxy_pass` на внешний сервер, или вызов скриптов с этого же сервера. Примерный конфиг nginx'а: location / { auth_request /auth; proxy_pass http://site.example.com; } location = /auth { internal; proxy_pass http://127.0.0.1/check.pl; proxy_pass_request_body off; # <- важно proxy_set_header Content-Length "0"; # <- важно proxy_set_header X-Original-URI $request_uri; } Обратите внимание на `Content-Length "0"`. Нужно это затем, чтобы в пересылаемом POST запросе получатель не ждал данных. Далее, допустим мы соорудили некий check.pl, который на основе пересланных запросов будет отвечать кодами 200/401/403/etc. С 200/OK - всё ясно, запрос проходит дальше. В случае остальных, например 403 - в дефолте nginx покажет простенькую, и совершенно неинформативную страничку "Access Denied". Чтобы этого не было, нам нужно добавить в блок `location / {}` перехват этих кодов: location / { <...> error_page 401 /auth.pl; error_page 403 /auth.pl; } ... где `/auth.pl` -- страница авторизации или сообщения об ошибке. Здесь вырисовывается две проблемы: во-первых, нам нужно прописать локейшн и для `/auth.pl`, во-вторых -- 401/403 коды могут использоваться и в самом сайте. Первое бы хрен с ним, но второе -- реально проблема, если перехватывать **все** 403 с сайта, мы можем использовать для этой ошибки только одну *глобальную* страницу на сайт. Для обхода этого кейса, я написал [небольшой патч](authreq-302.patch), который позволяет также использовать код 302, временный редирект. Правда с включением в апстрим меня завернули, дескать это поломает использование этого модуля как **одного из** факторов авторизации: location / { proxy_pass http://site.example.com; auth_req /auth; # запрос должен быть авторизован через nginx authreq allow 192.168.0.0/16; # ...ИЛИ идти из локальной сети deny all; satisfy any; # <- "или" - берётся отсюда } В принципе, надо - берите. Если таки забодаете апстрим - вообще респект и уважуха :-). Далее покажу примеры реального использования для каждого случая.