Asciinema: CentOS(Python 3.4)での4kbを超える録音のアップロードに対する不正なリクエスト

作成日 2017年06月07日  ·  58コメント  ·  ソース: asciinema/asciinema

バグレポート

システム情報:

  • 使用バージョン: 1.4.0(1.1.1にも同じ問題があります)
  • OS: CentOSLinuxリリース7.3.1611
  • Pythonバージョン: Python 3.4.5
  • ツールのインストール: 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

compatibility help wanted hosting

最も参考になるコメント

以前の構成に戻しました(NginxでSSLを終了します)。 それはあなたのために働くなら、私に教えてください今@andyone @ThiefMaster @benaryorg @peterbrittain @ThomasWaldmann

全てのコメント58件

私にも起こります。 ZSHを使用しますが、OMZは使用しません。

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

tmpw6byrbv8-asciinema.json

APIのURLをHTTPSからHTTPに変更すると、すべて正常に機能することがわかりました。

昨日ロードバランサーの構成を変更したので、これが関係している可能性があります。

これをCentos7 VagrantVMで再現することができました。 これは、昨日から使用しているBrightboxロードバランサー(SSLターミネーション、自動Let's Encrypt証明書)と関係があると思います。

@andyone @ThiefMaster今すぐお試しいただけますか? 私はそれを解決したかもしれません。

まだ400を取得しています

OpenSSL関連の問題だと思います。 curlはSSL / TLSの操作にNSS(Network Security Services)を使用するため、curlを使用してデータを送信することは問題ありません。

Brightboxロードバランサーを使用

それはnginxベースのソリューションですか?

@andyoneBrightboxロードバランサーはHaproxyを使用していると思います。

私はこれを一貫して再現することができます。 Vagrantfileと手順を作成しました: https

@andyone問題は、録音のこの特定の行ではなく、アップロードされたjsonファイルの全体的なサイズにあるようです。

私は、プロキシ作成https://ascii.kaos.ioに基づいてwebkaosと(それがBoringSSLとの改善nginxのだ) 、この設定を。 私と@ThiefMasterの録音は、このプロキシを介して正常にアップロードされました。

これが私がこれまでに知っていることです:

HTTPリクエストはBrightboxロードバランサーを介して正常に処理されますが、HTTPSリクエストは400の不正なリクエストを提供します
リクエスト本文が約4KBより大きいリクエストの場合。

興味深いのは、CentOSでHTTPS用に400を取得していることです。 macOSでのHTTPSは正常に機能します。 (HTTPはどこでも正常に機能します)。

私はもっ​​と深く見て、違いがどこにあるのかを見つけようとしました。 私はtcpdumpを使用して、CentOSとmacOSの両方でリクエストを確認しました(HTTP、リクエスト自体がHTTPSの場合と同じようにフォーマットされていると仮定)。

唯一の違いは、macOSでは本体の前に2行、CentOSでは1行の空行であるようです(おそらく、これらのOSのPython 3に付属するurllibのバージョンがわずかに異なるためです)。

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>

マックOS:

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(最大)に変更すると、突然どこでも(すべてのOS、HTTPS)正常に動作し始めました。

バッファサイズが4096の場合、これが当てはまるため、これが究極の解決策であるとは確信していません。

  • 3MBの本体でPOSTリクエストを問題なく行うことができます
    macOSでのHTTPS
  • したがって、このバッファサイズはヘッダー用であり、リクエスト本文用ではないと思います(これはBrightboxのJohnによって確認されました)
  • 本体が4KB未満のPOSTリクエストを問題なく行うことができます
    CentOS上のHTTPS
  • CentOSでHTTPSを介して4KBを超える本文でPOSTリクエストを行うことができません
  • 上記は、バッファがヘッダーにのみ適用されるという私の仮定と矛盾しています...
  • リクエストヘッダーはすべての場合に小さい(〜330バイト)

「リクエストバッファサイズ」を8192に上げると、ボディサイズとプロトコル
関係なく、すべて正常に動作します。 ぶつかってるのかな
それは8192に私は時間を買うだけです(影響を受ける人々を少なくします)またはこれ
問題を完全に解決します(もしそうなら、なぜですか?)。

私はこれについてBrightboxに連絡しました、うまくいけば彼らは何が起こっているのか説明することができます。

Brightbox側の再8192バッファサイズを更新します。この数値を使用すると、CentOSで機能しますが、 @ ThiefMasterでは機能しません。

申し訳ありません。

トラフィックをBrightboxLBに通す前に、NginxでSSLを終了しましたが、何年もの間すべてが正常に機能していました。 Nginxに基づく@andyoneのプロキシで動作する場合は、Nginxがリクエストのフォーマットについてより「寛容」であるのに対し、Haproxyはより厳密であり、asciinemaクライアントはPython 3.4(およびそのurllibは、私がMacで使用している3.6.1よりも古いものです)。

後でHaproxyで確認できますが、私のバージョンはOpenSSLではなくLibreSSLでビルドされています。

私の現在の理論はこれです:

ヘッダーと本文の前のこの1つの新しい行は、LBがヘッダーの読み取りを完了するのに十分ではなく(2つの新しい行が必要です)、その下のすべてのデータをヘッダーとして読み取り続け、バイトをカウントします。これは最終的にヘッダーの最大サイズを超えます。 LBにbytes_read (ソケットから読み取られたバイト数)のような変数がある場合、ヘッダーの読み取りが終了した後、本体の読み取り後に再度値をチェックします。 4kb未満のファイルをアップロードすると、ヘッダーの4kbの制限を超えることはなく、4kbを超えるファイルをアップロードするとそれを超えます。
(これはHTTPSでのみ発生します)

それが事実かどうかはわかりません、ただ大声で考えてください😀

ソースコードを更新して、新しい行を追加し、CentOSでチェックしても失敗するようにしました。 したがって、上記の理論は間違っています。

これは、HTTPSを使用するCentOSで機能します。

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

では、Pythonで使用されるSSL libは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のドキュメントには、ヘッダーを本文から分離するために1つのCRLFが必要であると記載されています。

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

完全なCRLFではなく、ここでCRまたはLFのみを送信している可能性はありますか?

@sickillこれは、LibreSSL2.5.0を使用したHA-Proxy1.7.5のプロキシです-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をチェックしましたが、ここではすべて問題あり

CentOSとmacOSの両方でリクエストを再度tcpdumpしました(HTTPペイロードがHTTPSで同じであると仮定して、HTTP経由で)。

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には、16進形式のダンプが含まれています( hexdump -C経由)。

dump-centos-hex.txt
dump-centos.pcap.txt
dump-mac-hex.txt
dump-mac.pcap.txt

どちらのOSでも、改行にCRLFが使用されており、ヘッダーと本文の間に1行の空白行があるようです。

左側のCentOS、右側のmacOS:

centos-mac-comparison

@sickillConfigが更新されました。 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

@andyoneのhaproxy構成がBBに非常に近く、それでも問題を再現できない場合、Let's Encrypt証明書を試してみるのは理にかなっていますか? これは、 https://ascii-ha.kaos.iohttps://asciinema.orgの違いの1つです

これは、 https://ascii-ha.kaos.iohttps://asciinema.orgの違いの1つです

いいえ。BBLBはOpenSSLで構築できます(私はLibreSSLを使用しています)。

https://ascii-ha.kaos.ioのLet'sEncrypt証明書を追加してみ

完了-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正常にアップロードされました。

これについてはこれ以上のアイデアはありません。 負荷分散とSSLターミネーションのために自分のNginxインスタンスにロールバックすることを検討しています🤕

私はこれを問題を再現できる単一のcurlコマンドに絞り込もうとしていますが、まだ管理していません。誰か助けてもらえますか?

curlを使用した認証ユーザー名/パスワードを使用して5kの本文をPOSTしています。 ネットキャットウェブサーバーバックエンドでBrightboxロードバランサーをヒットしているので、生のリクエストテキストを見ることができます。 それは常に通過します-悪い要求応答をトリガーさせることはできません。

これがロードバランサーによって拒否されている場合、バックエンドにアプリの実際のインスタンスは必要ありません。これは、それほど遠くまでは到達しないためです。したがって、アプリなしでカールを使用してこれを再現できるはずです。

私はubuntuとcentos7でcurlを試しましたが、特にopensslを使用しました(curlに--engineコマンドを指定して、使用するsslib libを選択できます。centos7curlバイナリはほとんどのオプションに対して構築されています)

@johnlこれを調べてくれてありがとう。

テストのバックエンドとしてnetcatを使用するのは理にかなっています👍

asciinema upload over-4k.json相当するcurlは、多かれ少なかれこれです。

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

uuid4python3 -c 'import uuid; print(uuid.uuid4())'結果に置き換えます)

そしてそれは確かにカールで動作します...

asciinema upload tcpdumpと上記のカールを比較しましたが、HTTPプロトコルレベルで疑わしいものは何もありません。 ただし、一部のtcpフレームは異なる場所に表示されます(各tcpパケットに送信されるデータが多い/少ない/収まる可能性があります)。

CentOS 7 VMでtcpflowを使用して(http://asciinema.orgへの)HTTPリクエストをキャプチャしました。

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

次に、別のシェル(同じVM内)で次のコマンドを実行しました。

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

私はそれからの応答を切り取り、要求だけを残しました。 送信されるものは次のとおりです

このキャプチャされたHTTPリクエストをasciinemaに対して再生しました。 org:80 with 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 -正常にアップロードされました。

ここでもっと掘り下げました。 centos7のcurlはnssを使用しますが、wgetはopensslを使用します。 curlまたはwgetのいずれかを使用してリクエストを正常に送信できます。 python httpieツール(python 3の下)を使用して送信することもできます。

ただし、stdin経由でopenssls_clientに送信できません。

ただし、stdinを使用するのではなく、リクエストを貼り付けることで、openssls_clientへの送信に成功します。

これは、何かが必要なCRLF行末ではなくLF行末でリクエストを送信しているためだと確信していますが、何が原因かはよくわかりません。 「openssls_client」は悪いテストツールであり、何が起こっているのかを確認するのが難しくなっていると思います。

しかし、nssまたはopensslのどちらを使用しているかにかかわらず、適切なhttpクライアントでこれを再現することはまだできていません(ubuntuのcurlはopensslを使用し、正常に動作するため、二重に確認しました)。 他の誰かがそれを管理しますか?

私は自分でいくつかのテストを行ったところ、この問題がコンテンツの長さ4520で持続することを確認できましたが、同じリクエストを1000文字削除しました( Content-Lengthは変更に応じて調整されました)。

CRLFは私のすべてのテストに存在し、 xxdはそれらがパイプを介して送信されることを確認します。
OpenBSDのnc (TLSをサポート)でテストすることもできます。

ドキュメントから:

tune.bufsize
バッファサイズをこのサイズ(バイト単位)に設定します。 値が小さいほど、より多くのことが可能になります
セッションは同じ量のRAMで共存でき、値が大きいほどいくつかのセッションが可能になります
動作する非常に大きなCookieを持つアプリケーション。 デフォルト値は16384で、
ビルド時に変更できます。 これを変更しないことを強くお勧めします
値が非常に低いと、次のような一部のサービスが機能しなくなるため、デフォルト値から
統計、およびデフォルトサイズより大きい値は、メモリ使用量を増やします。
システムのメモリが不足する可能性があります。 少なくともグローバルmaxconn
パラメータは、これを増やすのと同じ係数で減らす必要があります。
HTTPリクエストが(tune.bufsize --tune.maxrewrite)より大きい場合、haproxyは
HTTP 400(Bad Request)エラーを返します。 同様に、HTTP応答が大きい場合
このサイズよりも大きい場合、haproxyはHTTP 502(Bad Gateway)を返します。

リクエスト全体をメモリに保持せず、オンザフライで渡す(AFAIK)か、少なくとも一時ファイルにバッファリングするnginxとは対照的です。

no option http-buffer-requestオプションがあります。これは、私がその権利を取得した場合、その動作を正確に無効にします( noなしでoption http-buffer-request用に記述されています):

HTTPリクエストの本文を待つことが望ましい場合があります。
決定を下します。 これは、「balanceurl_param」によって実行されていることです。
例。 最初のユースケースは、遅いクライアントからのリクエストを前にバッファリングすることです
サーバーに接続しています。 別の使用例は、ルーティングを取ることです
リクエストボディの内容に基づいて決定します。 このオプションは
フロントエンドまたはバックエンドは、HTTP処理を強制的に全体が
本文が受信されたか、要求バッファーがいっぱいであるか、最初のチャンクが
チャンクエンコーディングの場合は完了。 それは望ましくない副作用をもたらす可能性があります
一部のアプリケーションは、バッファリングされていない送信を予期してHTTPを悪用します
フロントエンドとバックエンドなので、これは絶対に使用しないでください
デフォルト。

私もこれを打ったところです。 同じコンテンツのテストがHTTPSで機能しているが、HTTPSでは機能していない場合、クライアントとプロキシの間の何かが多くの余分なヘッダーを追加していない限り、バッファサイズに問題がある可能性は低いと思います。

ただし、SSL接続を終了しているものにバグがあり、ヘッダーがわずかに破損している可能性があります。

その場合、HAProxyのセキュリティを低下させるオプションがありますが、準拠性の低いHTTPトラフィックを通過させることができます。 https://stackoverflow.com/questions/39286346/extra-space-in-http-headers-gives-400-error-on-haproxyを参照して

最終的な修正としてセキュリティの低下を推奨していませんが、これにより、デバッグ中にサービスを維持できる可能性があります。

現時点では、asciinema.orgはBrightbox Cloudロードバランサーを使用しているため、Haproxy構成を制御していません。 以前は独自のNginxでSSLを終了していましたが、それは正常に機能していました。 BB LBに切り替えたので、この問題が発生します(一部の場合)。 CentOSまたは他のシステムでそれを経験していますか?

率直に言って、私は以前のNginxベースのソリューションに問題はありませんでした。 私たちが持っていたSSL証明書の有効期限が切れていたので、Let'sEncryptを使用するつもりでした。 LE証明書は短命であるため、自動的に管理するのが最適であり、BrightboxLBがそれを行います。 LEの設定作業を節約したかっただけで、BB LBが最も簡単なソリューションのようでした(asciinema.orgはBrightboxが後援し、優れたインフラストラクチャで実行されているため)。 今、Nginxで自分でLEをセットアップするのに、この問題のトラブルシューティングにすでに費やした時間の1/10かかると思います😞😞😞

ああ。 誰がどのビットを所有しているかの微妙さはわかりませんでした。 この問題についてBBから診断を取得する運がありましたか?

そしてあなたの質問に答えて:私の箱はCentOS6VMです。

また、asciinema 1.2.0(ubuntu 16.04 ltsからのバージョン)を使用して、悪いリクエストの問題が発生しました。

上記のカールハックはうまくいきました、ありがとう。

まったく同じファイルがGentoo [1]ボックスでは悪いリクエストを生成するが、OpenBSD [2]ボックスでは生成しないことを発見しました。
OpenBSDはそれをうまくアップロードします。
これらのクライアントの違いについては、さらに調査する必要があると思います。
Gentooボックスは、ebuildごとに次のPythonターゲットをサポートします。

PYTHON_TARGETS="python3_4 -python3_5"

現在、python3.5を簡単にテストすることはできませんが、おそらくこれはすでに役立つでしょう。

編集:OpenSSLバージョンを追加しましたが、それらを完全に忘れていました。

  • asciinema 1.4.0

    • python-exec2.4.5を使用して実行

    • 次にPython3.4.6を実行します

  • OpenSSL 1.0.2l 2017年5月25日

  • asciinema 1.3.0

    • Python3.6.0を使用して実行
  • LibreSSL 2.5.2

以前の構成に戻しました(NginxでSSLを終了します)。 それはあなたのために働くなら、私に教えてください今@andyone @ThiefMaster @benaryorg @peterbrittain @ThomasWaldmann

@sickill以前に失敗したのと同じファイルであると確信しているのは85%だけですが、そうである場合は修正しました。

@sickillは今私にとって魅力のように機能します。 👍

うん、今も私のために働いています( asciinema upload )。 ありがとう!

このページは役に立ちましたか?
0 / 5 - 0 評価

関連する問題

pfalcon picture pfalcon  ·  4コメント

omaraboumrad picture omaraboumrad  ·  10コメント

abaykan picture abaykan  ·  10コメント

ethanboxx picture ethanboxx  ·  6コメント

TyrfingMjolnir picture TyrfingMjolnir  ·  7コメント