Asciinema: Неверный запрос на загрузку записей размером> 4 КБ под CentOS (Python 3.4)

Созданный на 7 июн. 2017  ·  58Комментарии  ·  Источник: asciinema/asciinema

Отчет об ошибке

Системная информация:

  • Используемая версия: 1.4.0 (1.1.1 также имеет такую ​​же проблему)
  • ОС: CentOS Linux версии 7.3.1611
  • Версия Python
  • Инструменты установки: yum (из репозитория EPEL)

Действия по воспроизведению:

  1. asciinema upload asciicast.json

Ожидаемое поведение:

Файл загружен на asciinema.org

Фактическое поведение:

Сообщение об ошибке печати клиента:

Error: Invalid request: <html><body><h1>400 Bad request</h1>
Your browser sent an invalid request.
</body></html>

Дополнительная информация:

Клиент создает неработающую запись, если используется zsh (в моем случае 4.3.11 (x86_64-redhat-linux-gnu) ) и установлен oh-my-zsh. Если oh-my-zsh отключен или bash используется в качестве оболочки, клиент создает и загружает запись без каких-либо проблем.

Запись JSON: https://gist.github.com/andyone/b2a883e8c3795a6ad393a715ff7a41df

compatibility help wanted hosting

Самый полезный комментарий

Я только что вернулся к предыдущей конфигурации (отключение SSL в Nginx). Дайте мне знать, работает ли это для вас сейчас @andyone @ThiefMaster @benaryorg @peterbrittain @ThomasWaldmann

Все 58 Комментарий

Со мной тоже бывает. Использует ЗШ, но не ОМЗ.

$ zsh --version
zsh 5.3.1 (x86_64-pc-linux-gnu)
$ asciinema --version
asciinema 1.4.0

tmpw6byrbv8-asciinema.json

Я обнаружил, что если я изменю URL-адрес API с HTTPS на HTTP, все будет работать нормально.

Вчера я изменил конфигурацию балансировщика нагрузки, так что это может быть связано.

Мне удалось воспроизвести это в Centos 7 Vagrant VM. Я думаю, это как-то связано с балансировщиком нагрузки Brightbox (с завершением SSL, автоматическим сертификатом Let's Encrypt), который мы используем со вчерашнего дня.

@andyone @ThiefMaster можешь попробовать сейчас? Возможно, я решил это.

все еще получаю 400

Я думаю, что это проблема, связанная с OpenSSL. Отправка данных с помощью curl - это нормально, потому что curl использует NSS (службы сетевой безопасности) для работы с SSL / TLS.

с балансировщиком нагрузки Brightbox

Это решение на базе nginx?

@andyone Я думаю, что балансировщик нагрузки Brightbox использует Haproxy.

Я могу постоянно воспроизводить это. Я создал Vagrantfile и инструкции: https://github.com/sickill/bb-lb-400

@andyone проблема, похоже, не в этой конкретной строке в вашей записи, а в общем размере загруженного файла json.

Я создал прокси https://ascii.kaos.io на основе webkaos (он улучшил nginx с помощью BoringSSL) с этой конфигурацией . Мои записи и записи @ThiefMaster успешно загружены через этот прокси.

Вот что я знаю на данный момент:

HTTP-запросы проходят через балансировщик нагрузки Brightbox, но HTTPS-запросы дают 400 Bad Request
для запроса, размер тела которого превышает 4 КБ.

Интересно, что мы получаем 400 для HTTPS под CentOS. HTTPS под macOS работает нормально. (HTTP везде работает нормально).

Я посмотрел глубже, попытался выяснить, в чем разница. Я использовал tcpdump для просмотра запросов как в CentOS, так и в macOS (HTTP, предполагалось, что сам запрос отформатирован так же, как и в HTTPS).

Единственная разница, похоже, состоит в 2 пустых строках перед телом в macOS и 1 пустой строке в CentOS (вероятно, из-за немного другой версии urllib, которая поставляется с Python 3 в этих ОС):

CentOS:

POST /api/asciicasts HTTP/1.1
Accept-Encoding: identity
User-Agent: asciinema/1.4.0 CPython/3.4.5 Linux/3.10.0-514.16.1.el7.x86_64-x86_64-with-centos-7.3.1611-Core
Authorization: Basic <61 bytes of base64 encoded credentials>
Content-Length: 13582
Content-Type: multipart/form-data; boundary=c3f4e35afa4a4ce6b65b6420da09b46e
Connection: close
Host: asciinema.org

--c3f4e35afa4a4ce6b65b6420da09b46e
Content-Disposition: form-data; name="asciicast"; filename="asciicast.json"
Content-Type: application/json

<about 13 kb of json>

macOS:

POST /api/asciicasts HTTP/1.1
Accept-Encoding: identity
Content-Length: 13582
Host: asciinema.org
User-Agent: asciinema/1.4.0 CPython/3.6.1 Darwin/16.5.0-x86_64-i386-64bit
Content-Type: multipart/form-data; boundary=71d5b757e9d1451b9540dc286f74207d
Authorization: Basic <61 bytes of base64 encoded credentials>
Connection: close


--71d5b757e9d1451b9540dc286f74207d
Content-Disposition: form-data; name="asciicast"; filename="asciicast.json"
Content-Type: application/json

<about 13 kb of json>

Чтобы увидеть, как это влияет на вещи, я временно изменил «Размер буфера запроса» на LB с 4096 (по умолчанию) на 8192 (максимум), и он внезапно начал нормально работать везде (все ОС, HTTPS), ура!

Я не очень уверен, что это окончательное решение, потому что с размером буфера 4096 это правда:

  • Я могу сделать запрос POST с телом 3 МБ без проблем
    HTTPS в macOS
  • Таким образом, я предполагаю, что этот размер буфера предназначен для заголовков, а не для тела запроса (это подтвердил Джон из Brightbox).
  • Я могу сделать запрос POST с телом <4KB без проблем с
    HTTPS в CentOS
  • Я НЕ могу сделать запрос POST с телом> 4KB через HTTPS на CentOS
  • Вышесказанное противоречит моему предположению о применении буфера только для заголовков ...
  • Заголовки запросов небольшие (~ 330 байт) во всех случаях.

Когда я увеличиваю "размер буфера запроса" до 8192, размер тела и протокол
не имеет значения, и все работает нормально. Интересно, может ли, натыкаясь
это на 8192 Я только покупаю время (чтобы меньше пострадавших людей) или это
полностью решает проблему (если да, то почему?).

Я связался с Brightbox по этому поводу, надеюсь, они смогут объяснить, что происходит.

Обновите размер буфера 8192 на стороне Brightbox: с этим номером он работает у меня под CentOS, но все еще не работает для @ThiefMaster .

Упс, извини.

Прежде чем я пропустил трафик через Brightbox LB, я отключил SSL в Nginx, и все работало нормально в течение многих лет. Если он работает с прокси @andyone , основанным на Nginx, то это может указывать на то, что Nginx более «снисходителен» к форматированию запросов, в то время как Haproxy более строг, и клиент asciinema неправильно форматирует запрос (для стандартов Haproxy) под Python 3.4 (и его urllib, который старше версии 3.6.1, которую я использую на Mac).

Я могу проверить это позже с помощью Haproxy, но моя версия построена с использованием LibreSSL вместо OpenSSL.

Моя текущая теория такова:

Одной новой строки перед заголовками и телом недостаточно, чтобы LB завершил чтение заголовков (он ожидает 2 новые строки), и он продолжает читать все данные под ним как заголовки, считая байты, которые в конечном итоге превышают максимальный размер для заголовков. Если LB имеет некоторую переменную, например bytes_read (байты читаются из сокета), он проверяет ее значение после завершения чтения заголовков, а затем снова после чтения тела. Если вы загружаете файл размером <4 КБ, он никогда не превышает ограничение в 4 КБ для заголовков, а если вы загружаете> 4 КБ, оно превышает его.
(и это происходит только по HTTPS)

Понятия не имею, так ли это, просто думаю вслух 😀

Обновлен исходный код, поэтому он добавляет дополнительную новую строку, проверяется в CentOS и по-прежнему не работает. Итак, приведенная выше теория неверна.

Это работает под CentOS с HTTPS:

curl -v -X POST -u $USER:api-token https://asciinema.org/api/asciicasts -F [email protected]

* About to connect() to asciinema.org port 443 (#0)
*   Trying 109.107.38.233...
* Connected to asciinema.org (109.107.38.233) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
*   subject: CN=asciinema.org
*   start date: Jun 07 09:12:00 2017 GMT
*   expire date: Sep 05 09:12:00 2017 GMT
*   common name: asciinema.org
*   issuer: CN=Let's Encrypt Authority X3,O=Let's Encrypt,C=US
* Server auth using Basic with user 'vagrant'
> POST /api/asciicasts HTTP/1.1
> Authorization: Basic <...hidden...>
> User-Agent: curl/7.29.0
> Host: asciinema.org
> Accept: */*
> Content-Length: 5658
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=----------------------------6ca3f3de6469

Так, может быть, SSL lib, используемый Python, отличается от curl, и проблема кроется где-то в SSL-мире?

Я думаю так. Python использует OpenSSL, curl использует NSS.

@andyone сертификат для ascii.kaos.io не Let's Encrypt?

RapidSSL SHA256withRSA

Обычно я бы сказал, что в CentOS отсутствует корневой сертификат для Let's Encrypt (или что-то в этом роде 😊), но выполняется SSL-соединение, и ошибка находится на уровне протокола HTTP (400 Bad Request), поэтому ... 👐

Если корневой сертификат для Let's Encrypt отсутствует, он не будет работать даже с curl.

Наш (Brightbox) балансировщик нагрузки действительно использует haproxy. HTTP RFC и документы haproxy заявляют, что для отделения заголовков от тела требуется один CRLF:

https://github.com/haproxy/haproxy/blob/master/doc/internals/http-parsing.txt

Возможно ли, что вы отправляете здесь только CR или LF, а не полный CRLF?

@sickill Это прокси на HA-Proxy 1.7.5 с LibreSSL 2.5.0 - https://ascii-ha.kaos.io. Мои записи и записи @ThiefMaster , а также over-4k.json из вашего репозитория успешно загружены через этот прокси.

@andyone хорошо. Итак, можете ли вы изменить tune.bufsize (https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#3.2-tune.bufsize) на 4096?

@johnl Я проверил CRLF, и здесь все в порядке.

Я снова tcpdumped запрос как на CentOS, так и на macOS (опять же через HTTP, при условии, что полезная нагрузка HTTP одинакова для HTTPS).

dump-centos.pcap.txt и dump-mac.pcap.txt содержат захват tcpdump ( tcpdump -s 0 dst port 80 -w dump-centos.pcap.txt ).
dump-centos-hex.txt и dump-mac-hex.txt содержат дампы в шестнадцатеричном формате (через hexdump -C ).

дамп-centos-hex.txt
дамп-centos.pcap.txt
дамп-mac-hex.txt
дамп-mac.pcap.txt

Кажется, что в обеих ОС для новых строк используется CRLF, и между заголовками и телом есть одна пустая строка.

Слева CentOS, справа macOS:

centos-mac-comparison

@sickill Config обновлен. over-4k.json тоже загружено.

@andyone спасибо за обновление. Кажется, он не добавляет заголовок X-Forwarded-Proto (потому что возвращенный URL записи - http:// ). Можете ли вы добавить http-request set-header X-Forwarded-Proto https if { ssl_fc } ?

Это мой конфиг:

frontend www-https
    bind 207.154.241.251:443 ssl crt /etc/ssl/private/kaos.pem
    reqadd X-Forwarded-Proto:\ https
    default_backend www-backend

backend www-backend
    server asciinema-backend asciinema.org:80

Где мне добавить эту строку?

@andyone Я думаю, что нужно перейти в раздел backend (хотя я не эксперт по haproxy).

@andyone, кстати, я ДЕЙСТВИТЕЛЬНО благодарен вам за помощь в отладке 😍 Спасибо!

не забывайте и вперед. Это должно очень точно повторить настройку, включая ssl-шифры:

    tune.bufsize 4096
    tune.ssl.default-dh-param 2048
    tune.maxrewrite 40

frontend www-https
    bind 207.154.241.251:443 ssl no-sslv3 crt /etc/ssl/private/kaos.pem ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
    reqadd X-Forwarded-Proto:\ https
    default_backend www-backend

backend www-backend
    server asciinema-backend asciinema.org:80
    mode http
    option forwardfor
    option httplog

Я изменил конфигурацию на это, но безуспешно:

    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option                  http-server-close
    option                  forwardfor
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

frontend www-https
    bind 207.154.241.251:443 ssl crt /etc/ssl/private/kaos.pem
    reqadd X-Forwarded-Proto:\ https
    default_backend www-backend

backend www-backend
    http-request set-header X-Forwarded-Proto https
    server asciinema-backend asciinema.org:80

Клиент по-прежнему возвращает ссылки с http:// .

Всегда рад помочь улучшить полезные сервисы 😉.

@johnl Это полная конфигурация, все необходимые параметры установлены в разделах defaults и global :

    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    tune.bufsize 4096

    # SSL configuration
    tune.ssl.default-dh-param 2048
    ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
    ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
    ssl-default-server-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
    ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option                  http-server-close
    option                  forwardfor
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

frontend www-https
    bind 207.154.241.251:443 ssl crt /etc/ssl/private/kaos.pem
    reqadd X-Forwarded-Proto:\ https
    default_backend www-backend

backend www-backend
    http-request set-header X-Forwarded-Proto https
    server asciinema-backend asciinema.org:80

Если конфигурация haproxy @andyone теперь очень близка к BB, и мы все еще не можем воспроизвести проблему, имеет ли смысл попробовать сертификат Let's Encrypt? Это одно из различий между https://ascii-ha.kaos.io и https://asciinema.org.

Это одно из различий между https://ascii-ha.kaos.io и https://asciinema.org.

Нет. BB LB можно построить с помощью OpenSSL (я использую LibreSSL).

Я попробую добавить сертификат Let's Encrypt для https://ascii-ha.kaos.io.

Готово - https://ascii.kaos.re
HA-Proxy 1.7.5 (с LibreSSL 2.5.0) + сертификат Let's Encrypt (создан Certbot)
Конфиг:

    tune.bufsize 4096
    tune.ssl.default-dh-param 2048
    tune.maxrewrite 40

frontend www-https
    bind 207.154.241.251:443 ssl no-sslv3 crt /etc/ssl/private/ascii.kaos.re.pem ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
    reqadd X-Forwarded-Proto:\ https
    default_backend www-backend

backend www-backend
    server asciinema-backend asciinema.org:80
    mode http
    option forwardfor
    option httplog

Похоже, все работает нормально. over-4k.json успешно загружено.

У меня нет других идей по этому поводу. Я рассматриваю возможность отката к моему собственному экземпляру Nginx для балансировки нагрузки и завершения SSL 🤕

Я пытаюсь свести это к одной команде curl, которая может воспроизвести проблему, но еще не справилась с этим, может ли кто-нибудь помочь?

Я отправляю тело 5k с именем пользователя / паролем для аутентификации с помощью curl. Я использую балансировщик нагрузки Brightbox с бэкэндом веб-сервера netcat, поэтому я могу видеть необработанный текст запроса. Он всегда проходит - не может вызвать неверный ответ на запрос.

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

Я пробовал curl на ubuntu и centos7, и в частности с openssl (обратите внимание, что вы можете указать команду --engine для curl, чтобы выбрать, какую библиотеку sslib использовать. Двоичные файлы curl centos7 созданы для большинства параметров)

@johnl, спасибо, что

Имеет смысл использовать netcat в качестве бэкэнда для тестирования 👍

Эквивалент curl для asciinema upload over-4k.json примерно такой:

curl -v -X POST -u test:uuid4 https://asciinema.org/api/asciicasts -F [email protected]

(замените uuid4 результатом python3 -c 'import uuid; print(uuid.uuid4())' )

И это действительно работает с curl ...

Я сравнил tcpdump из asciinema upload и приведенный выше curl, и на уровне протокола HTTP нет ничего подозрительного для меня. Однако некоторые кадры TCP отображаются в разных местах (может быть, больше / меньше данных отправляется / помещается в каждый пакет TCP).

Я записал HTTP-запрос (на http://asciinema.org) с помощью tcpflow в CentOS 7 VM:

sudo tcpflow -p -C -i eth0 port 80 >tcpflow-req.txt

Затем в другой оболочке (в той же виртуальной машине) выполнялось:

ASCIINEMA_API_URL=http://asciinema.org asciinema upload /vagrant/over-4k.json

Я отрезал от него ответ, оставив только запрос. Вот что отправляется побайтно: tcpflow-req.txt

Я воспроизвел этот захваченный HTTP-запрос на asciinema. org: 80 с nc :

bash-4.4$ (cat tcpflow-req.txt; cat) | nc asciinema.org 80
HTTP/1.1 201 Created
Server: nginx
Date: Mon, 12 Jun 2017 13:30:03 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 48
Connection: close
Status: 201 Created
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Location: http://asciinema.org/a/4lgbbik7li4ywzqrfak0e7eku
ETag: "9beb7ac6bb5981f06fdc71df3947d8b0"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 2a8a8c75-ed06-4741-9adb-e5d276032ded
X-Runtime: 0.360858
Vary: Accept-Encoding
Strict-Transport-Security: max-age=15768000

http://asciinema.org/a/4lgbbik7li4ywzqrfak0e7eku

Все хорошо.

Теперь я отправил через SSL в asciinema. org: 443 :

(cat tcpflow-req.txt; cat) | openssl s_client -connect asciinema.org:443

Вот результат:

CONNECTED(00000003)
depth=1 /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/CN=asciinema.org
   i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFFDCCA/ygAwIBAgISBDhrp0YwV5NtleFOG+Zj61lQMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNzA2MDcwOTEyMDBaFw0x
NzA5MDUwOTEyMDBaMBgxFjAUBgNVBAMTDWFzY2lpbmVtYS5vcmcwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+/g237mVels4G9blsZlaeeiURbSp22eGO
T5OZ5As9NyuxSvRVEJrs4xk/RBEkCVgeZspSOmkRLwXG+FSMtjhbqIUt73AUKMdm
4DG+OwkVxjZatskL0wUWRcU7DmyW/Ls/OFJpPPcZ+pqu/v/ek99EiVNoAHJzXMXJ
ZsWy5KLE3fhkrlyMvdIkOkCK5zHOT95t0i8OmdaPIekPBa57VhvnDlUJsYyCF9GN
mP8Qg6OygexyULJGqBwiZ0BN2J6cYwChUlSvqFnkL4OzfixZ+mItuhl1b1vx/N5K
XMtPiM+nc/S+/liIWgtt7HIy9NmrOtSKbPTh3Bv/rfNdaiYx5CUHAgMBAAGjggIk
MIICIDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF
BwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFNAMhQNNwl+/bJjml9hrrHYzBxbf
MB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsGAQUFBwEBBGMw
YTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNyeXB0Lm9y
ZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNlbmNyeXB0Lm9y
Zy8wLwYDVR0RBCgwJoINYXNjaWluZW1hLm9yZ4IVc3RhZ2luZy5hc2NpaW5lbWEu
b3JnMIH+BgNVHSAEgfYwgfMwCAYGZ4EMAQIBMIHmBgsrBgEEAYLfEwEBATCB1jAm
BggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlwdC5vcmcwgasGCCsGAQUF
BwICMIGeDIGbVGhpcyBDZXJ0aWZpY2F0ZSBtYXkgb25seSBiZSByZWxpZWQgdXBv
biBieSBSZWx5aW5nIFBhcnRpZXMgYW5kIG9ubHkgaW4gYWNjb3JkYW5jZSB3aXRo
IHRoZSBDZXJ0aWZpY2F0ZSBQb2xpY3kgZm91bmQgYXQgaHR0cHM6Ly9sZXRzZW5j
cnlwdC5vcmcvcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBABxmJxdQQCcy
FpCkiDrB+vonBUCLYSJtrFkmRdmj9W8/ADpC6M/EhYFOCgrO2cmhYfy1SxDAP5Hd
KIhd3p1F931MMXVcxYt2n6FiDJHN531qp6eBzjZsVIgHXS27PAV466IIMTydNQSe
reyDc9fi+q+ji1Gz89nI8lHIOlRt3dzVGT2J3oQidsm4ZuPNJFj4y8MUrbUAOOH6
YY4n395OKV7vWzl7VPKiCWx+zsv4bzr6IGUPlwqCN2e6cppPWE47ugnYsarINCHO
ie5lU4E2N0k2qVWe/+uYbwSUQ0nrEx8R078m6+6EjDkR4VLboLjuV5tGBgHsJLQB
CmLH6CmNCRE=
-----END CERTIFICATE-----
subject=/CN=asciinema.org
issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
---
No client certificate CA names sent
---
SSL handshake has read 3436 bytes and written 456 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES128-SHA
    Session-ID: AC26CBF8D3719B1DE709A9A8AEAB43D20B14C62085A74604338C512CEA4472C5
    Session-ID-ctx:
    Master-Key: 0C59B1A2B6802D35FAD26DEE139043A853F3E62787E9AA743A8CAFDA95744DB73AB42B511F37EA7D6BB398A352938551
    Key-Arg   : None
    Start Time: 1497273777
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
HTTP/1.0 400 Bad request
Cache-Control: no-cache
Connection: close
Content-Type: text/html

<html><body><h1>400 Bad request</h1>
Your browser sent an invalid request.
</body></html>

/ cc @johnl

@sickill Можете ли вы проверить тот же запрос с https://ascii.kaos.re?

@andyone только что проверил. (cat tcpflow-req.txt; cat) | openssl s_client -connect ascii.kaos.re:443 - успешно загружено.

Я здесь больше покопался. curl на centos7 использует nss, но wget использует openssl. Я могу успешно отправить запрос с помощью curl или wget. Я даже могу отправить с помощью инструмента python httpie (под python 3).

но он не может отправить его в openssl s_client через stdin

но ему удается отправить его в openssl s_client, вставив в него запрос, а не используя stdin!

Теперь я почти уверен, что это потому, что что-то отправляет запросы с окончанием строки LF, а не с требуемым окончанием строки CRLF, но я не совсем уверен, что именно. Я думаю, что "openssl s_client" - плохой инструмент для тестирования и затрудняет понимание того, что происходит.

Но мне еще предстоит воспроизвести это с помощью надлежащего http-клиента, независимо от того, используется ли nss или openssl (curl на ubuntu использует openssl и тоже отлично работает, поэтому дважды подтвердил это). Кто-нибудь еще справится с этим?

Я только что провел небольшое тестирование и могу подтвердить, что эта проблема сохраняется с длиной содержимого 4520, но не с тем же запросом, разделенным на 1000 символов ( Content-Length скорректировано в соответствии с внесенными изменениями).

CRLF присутствуют во всех моих тестах, и xxd подтверждает, что они отправляются по каналу.
Я также мог протестировать с помощью OpenBSD nc (который поддерживает TLS).

Из документации :

tune.bufsize
Устанавливает размер буфера равным этому размеру (в байтах). Более низкие значения позволяют больше
сеансы сосуществуют в одном и том же объеме ОЗУ, а более высокие значения позволяют некоторым
приложения с очень большими файлами cookie для работы. Значение по умолчанию - 16384 и
можно изменить во время сборки. Настоятельно рекомендуется не изменять это
от значения по умолчанию, так как очень низкие значения нарушат работу некоторых служб, таких как
статистика и значения, превышающие размер по умолчанию, увеличивают использование памяти,
возможно, из-за нехватки памяти в системе. Хотя бы глобальный maxconn
параметр должен быть уменьшен во столько же раз, как этот.
Если HTTP-запрос больше, чем (tune.bufsize - tune.maxrewrite), haproxy будет
вернуть ошибку HTTP 400 (неверный запрос). Аналогично, если ответ HTTP больше
чем этот размер, haproxy вернет HTTP 502 (Bad Gateway).

В отличие от nginx, который не хранит весь запрос в памяти, а передает его на лету (AFAIK) или, по крайней мере, буферизует его во временный файл.

Существует опция no option http-buffer-request , которая, если у меня есть это право, отключает именно это поведение (написано для option http-buffer-request , без no ):

Иногда желательно дождаться тела HTTP-запроса перед
принятие решения. Это то, что делает "balance url_param" для
пример. Первый вариант использования - это буферизация запросов от медленных клиентов перед
подключение к серверу. Другой вариант использования состоит в том, чтобы использовать маршрутизацию
решение, основанное на содержании тела запроса. Эта опция помещена в
интерфейс или серверная часть заставляют обработку HTTP ждать, пока
получено тело, или буфер запроса заполнен, или первый фрагмент
завершено в случае кодирования по частям. Он может иметь нежелательные побочные эффекты с
некоторые приложения злоупотребляют HTTP, ожидая небуферизованной передачи между
интерфейс и серверная часть, поэтому это определенно не должно использоваться
дефолт.

Я тоже только что ударил. Мне кажется, что с вашим тестированием одного и того же контента, работающего по HTTP, но не по HTTPS, маловероятно, что виноват размер буфера, если только что-то между вашим клиентом и прокси-сервером не добавляет много дополнительных заголовков.

Но, возможно, есть ошибка в том, что прерывает ваши SSL-соединения, так что это немного повреждает заголовки.

Если это так, есть вариант, который снижает безопасность HAProxy, но пропускает менее совместимый HTTP-трафик. См. Https://stackoverflow.com/questions/39286346/extra-space-in-http-headers-gives-400-error-on-haproxy

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

@peterbrittain на данный момент asciinema.org использует балансировщик нагрузки Brightbox Cloud, поэтому я не контролирую их конфигурацию Haproxy. Мы использовали для прерывания SSL в нашем собственном Nginx, и это работало нормально. Поскольку я перешел на BB LB, эта проблема возникает (у некоторых). Вы испытываете это в CentOS или другой системе?

Честно говоря, у меня не было проблем с предыдущим решением на основе Nginx. Срок действия SSL-сертификата истек, поэтому я решил использовать Let's Encrypt. Поскольку сертификаты LE недолговечны, лучше всего ими управлять автоматически, и Brightbox LB делает это за меня. Я просто хотел сэкономить время на настройке LE, и BB LB показался самым простым решением (поскольку asciinema.org спонсируется Brightbox и работает на их великолепной инфраструктуре). Теперь я думаю, что самостоятельная настройка LE в Nginx, вероятно, займет 1/10 того времени, которое я уже потратил на устранение этой проблемы 😞😞😞

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

И в ответ на ваш вопрос: моя коробка - это виртуальная машина CentOS 6.

Я также только что столкнулся с проблемой неправильного запроса, используя asciinema 1.2.0 (версия от ubuntu 16.04 lts).

Приведенный выше метод curl сработал, спасибо.

Я только что обнаружил, что тот же самый файл выдает неверный запрос на моем компьютере Gentoo [1], но не на моем компьютере OpenBSD [2].
OpenBSD загружает это нормально.
Я думаю, что необходимо дальнейшее исследование разницы между этими клиентами.
Блок Gentoo поддерживает следующие цели Python для каждой сборки:

PYTHON_TARGETS="python3_4 -python3_5"

В настоящее время я не могу легко протестировать python3.5, но, возможно, это уже помогает.

Изменить : я добавил версии OpenSSL, полностью забыл о них.

  • asciinema 1.4.0

    • выполняется с использованием python-exec 2.4.5

    • в свою очередь выполнение Python 3.4.6

  • OpenSSL 1.0.2l 25 мая 2017 г.

  • asciinema 1.3.0

    • выполняется с использованием Python 3.6.0
  • LibreSSL 2.5.2

Я только что вернулся к предыдущей конфигурации (отключение SSL в Nginx). Дайте мне знать, работает ли это для вас сейчас @andyone @ThiefMaster @benaryorg @peterbrittain @ThomasWaldmann

@sickill Я только на 85% уверен, что это тот же файл, который раньше не удался, но если это так, вы его исправили.

@sickill Теперь для меня работает как шарм. 👍

Да, у меня тоже работает (с asciinema upload ). Спасибо!

Была ли эта страница полезной?
0 / 5 - 0 рейтинги