ПРОЕКТЫ 


  АРХИВ 


Apache-Talk @lexa.ru 

Inet-Admins @info.east.ru 

Filmscanners @halftone.co.uk 

Security-alerts @yandex-team.ru 

nginx-ru @sysoev.ru 


  СТАТЬИ 


  ПЕРСОНАЛЬНОЕ 


  ПРОГРАММЫ 



ПИШИТЕ
ПИСЬМА












     АРХИВ :: nginx-ru
Nginx-ru mailing list archive (nginx-ru@sysoev.ru)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Mutual authentication средствами nginx





четверг, 23 января 2014 г. пользователь Gena Makhomed написал:
On 23.01.2014 13:53, Илья Шипицин wrote:

Еще одной точки отказа тут нет, nginx в любом случае используется.
nginx стартует с рутовыми правами и доступ к сертификатам у него есть.
Если сервер не принял сертификат - значит у этого клиента доступа нет.

еще одна точка отказа тут есть.
nginx предъявляет свой сертификат серверу, сервер может отказать либо
потому что у пользователя нет доступа, либо в силу того, что сервер не
смог скачать CRL

Какая разница, кто делает исходящий https-запрос - nginx или backend ?
Тем более, что CRL скачивать не надо - это локальный файл. Экзотические
варианты "сломалась файловая система" и т.п. предлагаю не рассматривать.


CRL это свойство удостоверяющего центра, выпустившего сертификат клиента. в этом свойстве публикуется URL, по которому можно скачать актуальный список отозванных сертификатов. или не скачать, если по каким-то причинам адрес недоступен. посмотрите какой-нибудь корневой сертификат, там есть параметр CDP (CRL distribution point), о нем речь


CRL в файлике - да, так делают, но это не общий случай. как файлик узнает, что удостоверяющий центр отозвал очередной сертификат?
 

надо либо в одном случае возвращать "temp fail", в другом "perm fail",
либо что-то еще, но логику отработки ошибок надо как-то реализовывать на
стороне приложения

Почему надо возвращать "temp fail", если у пользователя нет доступа?
Доступа нет, а потом он появляется? Так бывает только в анекдотах:

именно так. доступа нет по причинам не зависящим напрямую от клиента и сервера
кроме магии с CRL очень легко налететь на. ситуацию "протухший сертификат" (истек срок действия)
 

Китайцы взломали сервер Пентагона, вот как это было:
1. Каждый китаец попробовал один пароль.
2. Каждый второй пароль был "Мао Цзедун"
3. На 74357181-й попытке- сервер согласился, что у него пароль "Мао Цзедун"

Если вся логика работы с TLS/SSL будет только на уровне nginx - это
нормально, а если часть там, часть там - то это layering violation.

если вся логика с ssl на стороне nginx, это точка отказа

Если используется только nginx - новых точек отказа не добавляется.
Если использовать еще дополнительно stunnel или OpenVPN - тогда
в системе появляются новые точки отказа, которых до того не было.

необязательно на C/C++, можно на nginx-lua за полдня набросать
то, что вы хотите.

    Каким образом, разве nginx-lua сможет добавить к proxy_pass
    ту функциональность, которой там сейчас нет, в частности, передачу
    на удаленный сервер клиентского сертификата и проверку серверного?

content_by_lua и любой креатив в ваших силах
ценой, возможно, большого оверхеда

http://wiki.nginx.org/HttpLuaModule#content_by_lua

Acts as a "content handler" and executes Lua code string specified in <lua-script-str> for every request. The Lua code may make API calls and is executed as a new spawned coroutine in an independent global environment (i.e. a sandbox).

Чем поможет "make API calls", если в nginx этой функциональности нет?


в content_by_lua можно запилить любой код на Lua и вернуть ответ в терминах nginx
 

Логично же делать максимальный уровень защиты
через Mutual authentication между сервисами.

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

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

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

а теперь представьте, что вы "прячете" топологию сервисов за nginx, все
становится еще сложнее, у nginx в коде события "tcp connect timeout"
(когда запрос не ушел и безопасно его еще раз повторить) и "http
response timeout" (когда надо быть максимально аккуратным) выглядят
одинаково

кстати, надо будет патч на эту тему сделать ))

Прятать топологию сервисов за nginx - это имхо общепринятая практика.
Если один backend не смог ответить на запрос - он направляется
на обработку другому.

Да, сервисы желательно делать идемпотентными. Это понятно.
Но к вопросу создания Mutual authentication между сервисами
средствами nginx вопросы идемпотентности какое имеют отношение?

nginx к этому имеет ровно то отношение, что у него срабатывает proxy_next_upstream, то есть кроме шифрования он делает перебор реплик

 

Грубо говоря, Mutual authentication с помощью "магии"
превращает незащищенное http соединение в высокозащищенное
HTTPS соединение. А софт на backend`е об этом не должен знать,
точно так же как он не должен знать про особенности работы TCP
протокола или про нюансы маршрутизации IP пакетов в сетях Ethernet.

ох уж эти затейники "приложение не должно знать про маршрутизацию IP", вот смотрите, приложение пишет в tcp сокет 1 байт и не хочет ничего знать про пакеты. что должна делать операционка ? добавить 40 байт хедера и отправить пакет, в котором будет 1 байт данных на 40 байт хедера ? подождать, может будут еще данные ? а если их долго не будет ? 

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


 

Вот потому и говорю, что по моим ощущениям, переносить логику работы
с Mutual authentication на backend - это есть 100% layering violation.

а вы никому не говорите про violation )) никто и не заметит
 

    Вот например, реальная задача. Есть небольшой хостинг -
    несколько десятков сайтов, которые созданы под заказ.

    Вместо того, чтобы для каждого сайта создавать свою админку,
    цеплять к ней SSL-сертификат, - проще и удобнее сделать всего
    одну админку, куда будут заходить пользователи по https,
    и там они смогут управлять своими сайтами. А сами сайты:

    www.example.com <http://www.example.com> - сюда ходят пользователи сайта
    api.example.com <http://api.example.com> - сюда ходит админка с
    Mutual authentication

    Сейчас - сайтов десятки, потом может быть сотни и тысячи.
    И что делать, настраивать и поддерживать в живом состоянии
    сотни и тысячи stunnel`ей? Каждому выделяя свой отдельный
    порт на стороне контейнера с админкой? Это будет nightmare.
    Практически это нереальный вариант. Наверное придется таки
    идти на layering violation и обучать админку делать https-
    запросы с предъявлением клиентского сертификата через curl.

реальна задача- это замечательно, но я не понял, в каком месте возникает
профит от mutual authentication, вероятно, надо больше деталей

Клиентские сайты могут быть размещены как на серверах компании,
которая занималась созданием этих сайтов, так и на собственных
серверах клиента. Управлять желательно и теми и теми одинаковым
образом из одной админки, чтобы не было "вагонов двух типов" -

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


 
про которые говорил Дейкстра в своей знаменитой притче:
http://www.vspu.ac.ru/~chul/dijkstra/pritcha/pritcha.htm

если вы хотите проверять серты на nginx и сообщать приложению, это
делается через переменные nginx, у нас такой сценарий используется, могу
конфиги помочь составить

Серверную часть " ... =(HTTPS)=> nginx2 =(http)=> tomcat2"
я уже настроил и здесь все работает просто отлично.

Кстати, сообщать приложению о том, что кто-то пытается
подключиться к api.example.com с невалидным сертификатом
не надо, смысла в этом никакого нет.

есть ситуации, когда это работает.
пример, есть домен с приложением, ssl используется для транспорта, пользователи ходят без сертификатов, на этом же домене по оптеделенному адресу, скажем /api/ работает сервис, который авторизует по сертификатам.

поэтому сертификат мы не требуем, но если есть - передаем в приложение и пусть оно само разбирается, кто это пришел
 

Проблемы осталась пока что только с настройкой
вот этой части: "tomcat1 =(http)=> nginx1 =(HTTPS)=> ..."
Не получается сделать так, чтобы nginx1 предъявлял удаленному
сервису свой клиентский сертификат и проверял сертификат
удаленного сервиса.

    ==============================__============================

    Вторая задача - это большой веб-сервис, который построен
    с использованием Micro Service Architecture, физически
    размещен на нескольких серверах с горизонтальным масштабированием

nginx ломает идею горизонтального масштабирования, или вы планируете
горизонтально плодить много экземпляров nginx?

Если есть 25 экземпляров tomcat`а - и каждый из них делает исходящие
запросы через свой nginx на 127.0.0.1:8080 - то понятно, что экземпляров
nginx тоже будет много, как минимум по количеству серверов/контейнеров.
И да, для простоты администрирования системы, 1 приложение == 1 tomcat.

а tomcat будет ходить только на свой nginx ? 

tomcat1 =(http)=> nginx1 =(HTTPS)=> nginx2 =(http)=> tomcat2

--
Best regards,
 Gena

_______________________________________________
nginx-ru mailing list
nginx-ru@xxxxxxxxx
http://mailman.nginx.org/mailman/listinfo/nginx-ru
_______________________________________________
nginx-ru mailing list
nginx-ru@xxxxxxxxx
http://mailman.nginx.org/mailman/listinfo/nginx-ru


 




Copyright © Lexa Software, 1996-2009.