<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">пн, 17 сент. 2018 г. в 4:37, Maxim Dounin <<a href="mailto:mdounin@mdounin.ru">mdounin@mdounin.ru</a>>:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello!<br>
<br>
On Sat, Sep 15, 2018 at 02:35:35PM +0300, Gena Makhomed wrote:<br>
<br>
> On 12.09.2018 17:36, Maxim Dounin wrote:<br>
> <br>
> >>>>>>> Лучше всего - сделать так, чтобы OpenSSL научился проверять<br>
> >>>>>>> OCSP-ответы не полной цепочкой сертификатов вплоть до доверенного<br>
> >>>>>>> root'а, а ровно так, как и должно быть по стандарту - с помощью<br>
> >>>>>>> одного только сертификата issuer'а.  Тогда проблема исчезнет.<br>
> <br>
> Задал вопрос по этому поводу в списке рассылки openssl-users:<br>
> <a href="https://mta.openssl.org/pipermail/openssl-users/2018-September/008795.html" rel="noreferrer" target="_blank">https://mta.openssl.org/pipermail/openssl-users/2018-September/008795.html</a><br>
> - пока что мне там никто ничего так и не ответил.<br>
> <br>
> >>> В зависимости от того, каким сертификатом подписан OCSP-ответ -<br>
> >>> этого может быть достаточно или нет.  RFC 6960 допускает два<br>
> >>> варианта подписи в OCSP-ответах:<br>
> <br>
> >>> - issuer подписывает OCSP-ответ сам; или<br>
> >>> - issuer выпускает сертификат, которым подписываются OCSP-ответы<br>
> >>>     (и этот сертификат включается в OCSP-ответ).<br>
> <br>
> >>> В обоих случаях для проверки OCSP-ответа достаточно знать<br>
> >>> issuer'а, однако второй случай в OpenSSL не работает (впрочем, я<br>
> >>> давно не порверял; но если верить "документации", в этом месте<br>
> >>> ничего не зименилось).  При этом по понятным причинам мало кто<br>
> >>> использует собственно CA для подписи OCSP-ответов, соответственно<br>
> >>> не работает это приблизительно всегда.<br>
> <br>
> Проверил второй случай, openssl-1.0.2k из CentOS 7.5 все работает:<br>
> <br>
> 1. Получаю сертификат сервера (0) и сертификат issuer'а (1):<br>
> openssl s_client -showcerts -connect <a href="http://www.godaddy.com:443" rel="noreferrer" target="_blank">www.godaddy.com:443</a> < /dev/null | less<br>
> <br>
> Сертификат сервера сохраняю в файл www.godaddy.com-cert.pem<br>
> а сертификат issuer'а - в файл www.godaddy.com-issuer.pem<br>
> <br>
> 2. Узнаю OCSP URI, это <a href="http://ocsp.godaddy.com/" rel="noreferrer" target="_blank">http://ocsp.godaddy.com/</a><br>
> openssl x509 -text -noout -in www.godaddy.com-cert.pem | less<br>
> <br>
> 3. Делаю запрос на получение OCSP ответа от этого сервера:<br>
> openssl ocsp -verify_other www.godaddy.com-issuer.pem  -issuer <br>
> www.godaddy.com-issuer.pem  -cert www.godaddy.com-cert.pem  -text -url <br>
> <a href="http://ocsp.godaddy.com/" rel="noreferrer" target="_blank">http://ocsp.godaddy.com/</a> -header "Host" "<a href="http://ocsp.godaddy.com" rel="noreferrer" target="_blank">ocsp.godaddy.com</a>" | less<br>
> <br>
> Из ответа видно, что для подписи используется отдельный сертификат<br>
> Go Daddy Validation Authority - G2, при этом "Response verify OK",<br>
> то есть OpenSSL может проверить ответ сервера и в этом случае.<br>
> <br>
> Если убрать параметр '-verify_other www.godaddy.com-issuer.pem'<br>
> тогда возвращается сообщение про ошибку:<br>
> <br>
> Response Verify Failure<br>
> 140345419933584:error:27069065:OCSP <br>
> routines:OCSP_basic_verify:certificate verify <br>
> error:ocsp_vfy.c:138:Verify error:unable to get local issuer certificate<br>
> <br>
> Получается, что OpenSSL уже очень давно умеет проверять<br>
> OCSP-ответ с помощью одного только сертификата issuer'а?<br>
<br>
Получается, что в CentOS 7.5 есть bundle с доверенными корневыми <br>
сертификатами, который используется openssl по умолчанию.  Если <br>
его отключить - указав параметры -CAfile и -CApath явно - то <br>
валидация сломается.<br>
<br>
> >>>> Насколько я понял из предыдущего обсуждения, нет разумных причин,<br>
> >>>> чтобы выключать использование OCSP stapling и ocsp_stapling_verify.<br>
> >>>><br>
> >>>> И вместе с тем, есть причины, чтобы их включать:<br>
> >>>> OCSP stapling - сайт у клиентов будет открываться быстрее.<br>
> >>>> ocsp_stapling_verify - не будет проблем с неразумными браузерами.<br>
> >><br>
> >>> Про "быстрее" - есть нюансы.  В частности, OCSP-ответ отправляется<br>
> >>> клиенту, пытающемуся использовать OCSP stapling, в каждом<br>
> >>> SSL handshake'е (а это местами может быть больно с точки зрения latency, не<br>
> >>> говоря уже про трафик), в то время как в значительной части<br>
> >>> случаев он клиенту на самом деле не нужен (например, уже есть в<br>
> >>> кэше).<br>
> <br>
> Почему это может быть больно с точки зрения latency? Ведь nginx держит<br>
> OCSP-ответ в своей памяти и отдает его клиенту практически мгновенно.<br>
> Этот ответ как правило валиден от 24 часов до 7 или даже 14 дней.<br>
> <br>
> Трафик - это дополнительный килобайт, максимум два килобайта.<br>
> Разве это много? Страница сайта весит от сотен килобайт<br>
> до нескольких мегабайт, и 1-2 килобайта роли не играют.<br>
<br>
Дополнительная пара килобайт в начале соедениния - это <br>
потенциальный выход за пределы исходного окна, и соответственно <br>
лишний RTT на соединение.<br>
<br>
С получившим сейчас достаточно широкое распространение initcwnd10 <br>
(rfc6928, окно до 14k) - скорее всего плохо не будет (но тоже <br>
вопрос, какая цепочка сертификатов при этом стоит), а если <br>
используется более традиционный rfc3390 с окном до 4 килобайт - <br>
как раз из-за stapling'а нарваться на лишний round-trip <br>
элементарно.<br>
<br>
Что до трафика, то всё зависит как раз от того, какой в данном <br>
конкретном случае средний трафик передаётся по соединению.  И <br>
далеко не везде это сотни килобайт.<br>
<br>
> Если OCSP-статус сертификата клиенту не нужен,<br>
> зачем же в таком случае клиент его постоянно запрашивает?<br>
> <br>
> Это же клиент решает, получать ему OCSP-статус сертификата или нет.<br>
<br>
Клиент не может знать, нужен ему статус или нет.  Более того - он <br>
даже не может знать, какой сертификат ему вернут.  Соответственно <br>
если он использует stapling - то в любом полном handshake'е <br>
вынужден получать и stapling тоже.<br>
<br>
[...]<br>
<br>
> >>> Про verify - тоже есть нюансы.  Дискуссия, если я её правильно<br>
> >>> понял, как раз о том, что включать verify обходится дороже с<br>
> >>> административной точки зрения, чем хотелось бы.  При этом плюсы -<br>
> >>> призрачны, ибо защищают от атак, которых на практике не бывает<br>
> >>> (а если бы они были - браузеры бы давно исправились).<br>
> >><br>
> >> В начале дискуссии вопрос был о том, почему для того чтобы директива<br>
> >> ssl_stapling_verify on; нормально работала необходимо также прописывать<br>
> >> ssl_trusted_certificate /etc/letsencrypt/live/<a href="http://example.com/chain.pem" rel="noreferrer" target="_blank">example.com/chain.pem</a>;<br>
> >> если содержимое файла chain.pem можно получить из файла fullchain.pem<br>
> >> выбросив оттуда первый сертификат, который является сертификатом сайта?<br>
> > <br>
> > И ответ на этот вопрос - потому что интерфейс проверки сертификатов<br>
> > кривой, и требует массы дополнительных приседаний, чтобы работать.<br>
> > Именно поэтому по умолчанию используется ssl_stapling_verify off.<br>
> <br>
> Передать библиотеке OpenSSL сертификат issuer'а два раза,<br>
> в параметрах -issuer и -verify_other - это не выглядит очень сложным.<br>
<br>
К сожалению, это работает не так.  Точнее - так это не работает.  <br>
Всё что можно передать - nginx передаёт, но этого недостаточно, <br>
если OCSP-ответы подписаны с использованием промежуточного <br>
сертификата.<br>
<br>
> > Кроме того, если у вас в ssl_certificate указана полная цепочка,<br>
> > включая сертификат root CA, то это неправильно.  Root-сертификат у<br>
> > клиентов и так есть, отправлять клиентам его - бессмысленная трата<br>
> > ресурсов, соответственно и включать его в цепочку в<br>
> > ssl_certificate - не надо.<br>
> <br>
> У меня сертификат получен с помощью certbot,<br>
> "Let’s Encrypt Authority X3" - это промежуточный сертификат.<br>
> Он подписан с помощью "DST Root CA X3", подробности здесь:<br>
> <a href="https://letsencrypt.org/certificates/" rel="noreferrer" target="_blank">https://letsencrypt.org/certificates/</a><br>
> <br>
> В конфиге nginx прописано<br>
> <br>
>       ssl_stapling on;<br>
>       ssl_stapling_verify on;<br>
>       resolver 127.0.0.1;<br>
> <br>
>       ssl_certificate         /etc/letsencrypt/live/.../fullchain.pem;<br>
>       ssl_certificate_key     /etc/letsencrypt/live/.../privkey.pem;<br>
> <br>
> Директива ssl_trusted_certificate вообще нигде в конфиге не указана,<br>
> при этом - nginx не пишет в лог никаких ошибок верификации сертификата.<br>
<br>
Потому что letsencrypt - подписывает OCSP-ответы непосредственно <br>
issuer'ом, не используя промежуточный сертфикат.  Соответственно <br>
для него - ssl_stapling_verify работает без дополнительных <br>
приседаний, хватает сертифката issuer'а, который nginx достаёт из <br>
цепочки ssl_certificate.<br>
<br>
К сожалению, это далеко не всегда так.  И к ещё большему сожалению - <br>
никто не гарантирует, что в один прекрасный момент это не <br>
перестанет быть так и для letsencrypt тоже.<br>
<br>
[...]<br>
<br>
> Кстати, пользователи жалуются, что есть BUG в nginx,<br>
> связанный с сертификатами с флагом "OCSP Must Staple":<br>
> <a href="https://blog.crashed.org/nginx-stapling-busted/" rel="noreferrer" target="_blank">https://blog.crashed.org/nginx-stapling-busted/</a><br>
<br>
Потому что "Must Staple" - это попытка превратить OCSP stapling из <br>
механизма оптимизации в обязательный механизм, аналогичный <br>
короткоживущим сертификатам.  Не сюрприз, что так не работает - <br>
требования совершенно разные.<br>
<br>
Любители Must Staple общаются в траке в двух тикетах:<br>
<br>
<a href="https://trac.nginx.org/nginx/ticket/812" rel="noreferrer" target="_blank">https://trac.nginx.org/nginx/ticket/812</a><br>
<a href="https://trac.nginx.org/nginx/ticket/990" rel="noreferrer" target="_blank">https://trac.nginx.org/nginx/ticket/990</a><br>
<br>
Пока что они делают это с нулевым полезным выходом.<br></blockquote><div><br></div><div>из этих тикетов, в общем, есть здравое зерно, что было бы неплохо каким-то проактивным способом уметь получать OCSP ответы.</div><div><br></div><div>почему это разумно</div><div><br></div><div>1) список сертов более или менее известен (пока что nginx не умеет и не планировать выпускать серты самостоятельно)</div><div>2) это сокращает время доставки контента и делает процедуру более предсказуемой (по сравнению с тем, когда надо пойти за OCSP ответом в то время, когда на проводе сидит пользователь)</div><div><br></div><div>я не уверен, что архитектурно правильным решением будет делать это именно силами nginx. возможно, некое стороннее приложение (надо удобным способом уметь согласовывать список сертов и момент перечитывания OCSP с диска)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
-- <br>
Maxim Dounin<br>
<a href="http://mdounin.ru/" rel="noreferrer" target="_blank">http://mdounin.ru/</a><br>
_______________________________________________<br>
nginx-ru mailing list<br>
<a href="mailto:nginx-ru@nginx.org" target="_blank">nginx-ru@nginx.org</a><br>
<a href="http://mailman.nginx.org/mailman/listinfo/nginx-ru" rel="noreferrer" target="_blank">http://mailman.nginx.org/mailman/listinfo/nginx-ru</a></blockquote></div></div>