Asciinema: Mauvaise demande de téléchargement d'enregistrements> 4 ko sous CentOS (Python 3.4)

Créé le 7 juin 2017  ·  58Commentaires  ·  Source: asciinema/asciinema

Rapport d'erreur

Information système:

  • Version utilisée: 1.4.0 (1.1.1 a également le même problème)
  • Système d' exploitation: CentOS Linux version 7.3.1611
  • Version Python: Python 3.4.5
  • Installer les outils: yum (à partir du référentiel EPEL)

Étapes à suivre pour reproduire:

  1. asciinema upload asciicast.json

Comportement prévisible:

Fichier téléchargé sur asciinema.org

Comportement réel:

Message d'erreur d'impression du client:

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

Information additionnelle:

Le client crée un enregistrement interrompu si zsh ( 4.3.11 (x86_64-redhat-linux-gnu) dans mon cas) est utilisé et oh-my-zsh est installé. Si oh-my-zsh est désactivé ou si bash est utilisé comme shell, le client crée et télécharge l'enregistrement sans aucun problème.

Enregistrement JSON: https://gist.github.com/andyone/b2a883e8c3795a6ad393a715ff7a41df

compatibility help wanted hosting

Commentaire le plus utile

Je viens de revenir à la configuration précédente (terminaison de SSL dans Nginx). Faites-moi savoir si cela fonctionne pour vous maintenant @andyone @ThiefMaster @benaryorg @peterbrittain @ThomasWaldmann

Tous les 58 commentaires

Cela m'arrive aussi. Utilisation de ZSH mais pas d'OMZ.

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

tmpw6byrbv8-asciinema.json

J'ai trouvé que si je change l'URL de l'API de HTTPS à HTTP, tout fonctionne bien.

J'ai modifié la configuration de l'équilibreur de charge hier, cela peut donc être lié.

J'ai pu reproduire cela dans Centos 7 Vagrant VM. Je pense que cela a quelque chose à voir avec l'équilibreur de charge Brightbox (avec terminaison SSL, certificat automatique Let's Encrypt) que nous utilisons depuis hier.

@andyone @ThiefMaster pouvez-vous essayer maintenant? J'ai peut-être résolu le problème.

obtenir encore un 400

Je pense que c'est un problème lié à OpenSSL. L'envoi de données avec curl est acceptable car curl utilise NSS (Network Security Services) pour travailler avec SSL / TLS.

avec l'équilibreur de charge Brightbox

C'est une solution basée sur nginx?

@andyone Je pense que l'équilibreur de charge Brightbox utilise Haproxy.

Je peux reproduire cela de manière cohérente. J'ai créé Vagrantfile et les instructions: https://github.com/sickill/bb-lb-400

@andyone le problème ne semble pas être cette ligne spécifique dans votre enregistrement, mais la taille globale du fichier json téléchargé.

J'ai créé un proxy https://ascii.kaos.io basé sur webkaos (c'est nginx amélioré avec BoringSSL) avec cette configuration . Mes enregistrements et @ThiefMaster ont été téléchargés avec succès via ce proxy.

Voici ce que je sais jusqu'à présent:

Les requêtes HTTP se passent bien via l'équilibreur de charge Brightbox, mais celles HTTPS donnent 400 Bad Request
pour la demande où le corps de la demande est supérieur à environ 4 Ko.

Ce qui est intéressant, c'est que nous obtenons 400 pour HTTPS sous CentOS. HTTPS sous macOS fonctionne très bien. (HTTP fonctionne bien partout).

J'ai regardé plus profondément, essayé de découvrir où était la différence. J'ai utilisé tcpdump pour voir les requêtes sur CentOS et macOS (HTTP, supposé que la requête elle-même est formatée de la même manière que sous HTTPS).

La seule différence semble être 2 lignes vides avant le corps sur macOS, 1 ligne vide sur CentOS (probablement en raison de la version légèrement différente d'urllib fournie avec Python 3 sur ces systèmes d'exploitation):

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>

Pour voir comment cela affecte les choses, j'ai temporairement changé la "Taille du tampon de demande" sur LB de 4096 (par défaut) à 8192 (max) et cela a soudainement commencé à fonctionner correctement partout (tous les systèmes d'exploitation, HTTPS), yay!

Je ne suis pas très sûr que ce soit la solution ultime car avec une taille de tampon de 4096, c'est vrai:

  • Je suis en mesure de faire une demande POST avec un corps 3MB sans problème
    HTTPS sur macOS
  • Ainsi, je suppose que cette taille de tampon est pour les en-têtes et non le corps de la demande (cela a été confirmé par John de Brightbox)
  • Je suis capable de faire une demande POST avec un corps <4 Ko sans problème
    HTTPS sur CentOS
  • Je ne suis PAS en mesure de faire une demande POST avec un corps> 4KB sur HTTPS sur CentOS
  • Ci-dessus contredit mon hypothèse sur le tampon ne s'appliquant qu'aux en-têtes ...
  • Les en-têtes de requête sont petits (~ 330 octets) dans tous les cas

Lorsque je passe "la taille du tampon de demande" à 8192, la taille du corps et le protocole
n'a pas d'importance et tout fonctionne bien. Je me demande si en se cognant
il à 8192 je n'achète que du temps (fait moins de gens touchés) ou ceci
résout complètement le problème (si oui, pourquoi?).

J'ai contacté Brightbox à ce sujet, j'espère qu'ils pourront expliquer ce qui se passe.

Mise à jour de la taille de la mémoire tampon de 8192 côté Brightbox: avec ce numéro, cela fonctionne pour moi sous CentOS mais ne fonctionne toujours pas pour @ThiefMaster .

Ops, désolé.

Avant de faire passer le trafic via Brightbox LB, j'ai mis fin à SSL dans Nginx et tout fonctionnait bien pendant des années. Si cela fonctionne avec le proxy de @andyone basé sur Nginx, cela peut suggérer que Nginx est plus "indulgent" sur le formatage des requêtes, alors qu'Haproxy est plus strict et que le client asciinema formate la requête de manière incorrecte (pour les standards Haproxy) sous Python 3.4 (et son urllib, qui est plus ancien que le 3.6.1 que j'utilise sous mac).

Je peux le vérifier plus tard avec Haproxy, mais ma version est construite avec LibreSSL au lieu d'OpenSSL.

Ma théorie actuelle est la suivante:

Cette seule nouvelle ligne avant les en-têtes et le corps n'est pas suffisante pour que LB finisse de lire les en-têtes (il attend 2 nouvelles lignes), et il continue à lire toutes les données en dessous comme en-têtes, en comptant les octets, qui dépassent finalement la taille maximale des en-têtes. Si LB a une variable comme bytes_read (octets lus depuis le socket), il vérifie sa valeur après avoir fini de lire les en-têtes, puis à nouveau après avoir lu le corps. Si vous téléchargez un fichier <4 Ko, il ne dépasse jamais la limite de 4 Ko pour les en-têtes, et si vous téléchargez> 4 Ko, il le dépasse.
(et cela ne se produit que sous HTTPS)

Je ne sais pas si c'est le cas, je pense juste à voix haute 😀

Code source mis à jour afin d'ajouter une nouvelle ligne supplémentaire, vérifié sous CentOS et échoue toujours. La théorie ci-dessus est donc fausse.

Cela fonctionne sous CentOS avec 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

Alors peut-être que la bibliothèque SSL utilisée par Python est différente de curl et que le problème se situe quelque part dans SSL-land?

Je pense que oui. Python utilise OpenSSL, curl utilise NSS.

@andyone le certificat pour ascii.kaos.io n'est pas Let's Encrypt?

RapidSSL SHA256avecRSA

Normalement, je dirais que CentOS n'a pas de certificat racine pour Let's Encrypt (ou quelque chose comme ça 😊), mais la connexion SSL est en cours et l'erreur est au niveau du protocole HTTP (400 Bad Request) donc ...

Si le certificat racine de Let's Encrypt est manquant, il ne fonctionnera pas même avec curl.

Notre équilibreur de charge (Brightbox) utilise en effet haproxy. Le RFC HTTP et les documents haproxy indiquent qu'un CRLF est requis pour séparer les en-têtes du corps:

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

Est-il possible que vous n'envoyiez ici qu'un CR ou un LF, plutôt qu'un CRLF complet?

@sickill Ceci est un proxy sur HA-Proxy 1.7.5 avec LibreSSL 2.5.0 - https://ascii-ha.kaos.io. Mes enregistrements et @ThiefMaster , et over-4k.json de votre référentiel ont été téléchargés avec succès via ce proxy.

@andyone ok. Alors, pouvez-vous changer tune.bufsize (https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#3.2-tune.bufsize) en 4096?

@johnl J'ai vérifié CRLF et tout va bien ici.

J'ai tcpdumped la demande sur CentOS et macOS à nouveau (sur HTTP, encore une fois, en supposant que la charge utile HTTP est la même pour HTTPS).

dump-centos.pcap.txt et dump-mac.pcap.txt contiennent la capture tcpdump ( tcpdump -s 0 dst port 80 -w dump-centos.pcap.txt ).
dump-centos-hex.txt et dump-mac-hex.txt contiennent des vidages au format hexadécimal (via hexdump -C ).

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

Il semble que sur les deux systèmes d'exploitation, CRLF est utilisé pour les nouvelles lignes, et il y a une ligne vide entre les en-têtes et le corps.

Sur le CentOS de gauche, sur le macOS de droite:

centos-mac-comparison

@sickill Config mis à jour. over-4k.json mis en ligne.

@andyone merci pour la mise à jour. Il semble qu'il n'ajoute pas l'en-tête X-Forwarded-Proto (car l'URL d'enregistrement renvoyée est http:// ). Pouvez-vous ajouter http-request set-header X-Forwarded-Proto https if { ssl_fc } ?

C'est ma config:

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

Où dois-je ajouter cette ligne?

@andyone Je pense qu'il doit aller dans la section backend (je ne suis pas un expert en haproxy cependant).

@andyone btw, j'apprécie VRAIMENT que vous aidiez à déboguer ceci 😍 Merci!

n'oubliez pas aussi de faire avancer les choses. Cela devrait reproduire la configuration assez étroitement, avec les chiffrements ssl également:

    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

J'ai modifié la configuration pour cela, mais sans chance:

    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

Le client renvoie toujours des liens avec http:// .

Je suis toujours heureux d'aider à améliorer les services utiles 😉.

@johnl Ceci est une configuration complète, toutes les options requises sont définies dans les sections defaults et 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

Si @andyone « s config haproxy est maintenant très proche de BB et nous ne pouvons pas reproduire le problème, est - il logique d'essayer avec Crypter cert Let? C'est l'une des différences entre https://ascii-ha.kaos.io et https://asciinema.org.

C'est l'une des différences entre https://ascii-ha.kaos.io et https://asciinema.org.

Non. BB LB peut être construit avec OpenSSL (j'utilise LibreSSL).

J'essaierai d'ajouter le certificat Let's Encrypt pour https://ascii-ha.kaos.io.

Terminé - https://ascii.kaos.re
HA-Proxy 1.7.5 (avec LibreSSL 2.5.0) + certificat Let's Encrypt (créé par Certbot)
Config:

    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

On dirait que tout fonctionne bien. over-4k.json téléversé avec succès.

Je n'ai aucune autre idée à ce sujet. J'envisage de revenir à ma propre instance Nginx pour l'équilibrage de charge et la terminaison SSL 🤕

J'essaie de réduire cela à une seule commande curl qui peut reproduire le problème, mais je ne l'ai pas encore géré, quelqu'un peut-il m'aider?

Je POST un corps 5k, avec un nom d'utilisateur / mot de passe d'authentification utilisant curl. Je rencontre un équilibreur de charge Brightbox avec un backend de serveur web netcat, donc je peux voir le texte brut de la requête. Cela passe toujours - ne peut pas le faire déclencher une mauvaise réponse à la demande.

Si cela est rejeté par l'équilibreur de charge, je ne devrais pas avoir besoin d'une instance réelle de l'application sur le backend, car elle ne devrait jamais aller aussi loin - nous devrions donc être en mesure de reproduire cela avec curl et sans application.

J'ai essayé curl sur ubuntu et centos7, et avec openssl spécifiquement (notez que vous pouvez spécifier la commande --engine à curl pour choisir la bibliothèque sslib à utiliser. Les binaires curl centos7 sont construits avec la plupart des options)

@johnl merci d'avoir examiné cela.

Il est logique d'utiliser netcat comme backend pour les tests 👍

curl équivalent pour asciinema upload over-4k.json est plus ou moins ceci:

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

(remplacez uuid4 par le résultat de python3 -c 'import uuid; print(uuid.uuid4())' )

Et cela fonctionne avec curl en effet ...

J'ai comparé tcpdump de asciinema upload et le curl ci-dessus et il n'y a rien au niveau du protocole HTTP qui me semble suspect. Cependant, certaines trames TCP apparaissent à différents endroits (peut-être que plus / moins de données sont envoyées / tiennent dans chaque paquet TCP).

J'ai capturé la requête HTTP (sur http://asciinema.org) avec tcpflow dans CentOS 7 VM:

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

Puis dans un autre shell (dans la même machine virtuelle) a couru:

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

J'en ai coupé la réponse, ne laissant que la demande. Voici ce qui est envoyé, octet par octet: tcpflow-req.txt

J'ai rejoué cette requête HTTP capturée contre asciinema. org: 80 avec 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

Tout bon.

Maintenant, j'ai envoyé SSL à asciinema. org: 443 :

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

Voici le résultat:

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 Pouvez-vous vérifier la même demande avec https://ascii.kaos.re?

@andyone vient de vérifier. Est-ce que (cat tcpflow-req.txt; cat) | openssl s_client -connect ascii.kaos.re:443 - a été téléversé avec succès.

J'ai creusé plus ici. curl sur centos7 utilise nss mais wget utilise openssl. Je peux envoyer la demande avec succès avec curl ou wget. Je peux même envoyer en utilisant l'outil python httpie (sous python 3).

mais il ne parvient pas à l'envoyer à openssl s_client via stdin

mais il réussit à l'envoyer à openssl s_client en y collant la requête, plutôt qu'en utilisant stdin!

Je suis maintenant à peu près sûr que c'est parce que quelque chose envoie des demandes avec des fins de ligne LF plutôt que les fins de ligne CRLF requises, mais je ne sais pas trop quoi. Je pense que "openssl s_client" est un mauvais outil de test et il est difficile d'être sûr de ce qui se passe.

Mais je n'ai pas encore reproduit cela avec un client http approprié, que ce soit en utilisant nss ou openssl (curl sur ubuntu utilise openssl et fonctionne bien aussi, donc double confirmé). Quelqu'un d'autre gère-t-il ça?

Je viens de faire quelques tests par moi-même et je peux confirmer que ce problème persiste avec une longueur de contenu de 4520, pas cependant avec la même requête dépouillée de 1000 caractères ( Content-Length ajusté en fonction des modifications apportées).

Les CRLF sont présents dans tous mes tests et xxd confirme qu'ils sont envoyés sur le tube.
Je pourrais également tester avec nc d'OpenBSD (qui prend en charge TLS).

De la documentation :

tune.bufsize
Définit la taille de la mémoire tampon sur cette taille (en octets). Des valeurs plus basses permettent plus
sessions de coexister dans la même quantité de RAM, et des valeurs plus élevées permettent à certains
applications avec de très gros cookies pour fonctionner. La valeur par défaut est 16384 et
peut être modifié au moment de la construction. Il est fortement recommandé de ne pas changer cela
à partir de la valeur par défaut, car des valeurs très faibles interrompront certains services tels que
les statistiques et les valeurs supérieures à la taille par défaut augmenteront l'utilisation de la mémoire,
peut entraîner un manque de mémoire du système. Au moins le maxconn global
le paramètre doit être diminué du même facteur que celui-ci est augmenté.
Si la requête HTTP est plus grande que (tune.bufsize - tune.maxrewrite), haproxy
renvoie l'erreur HTTP 400 (demande incorrecte). De même si une réponse HTTP est plus grande
que cette taille, haproxy renverra HTTP 502 (Bad Gateway).

Contrairement à nginx qui ne garde pas toute la requête en mémoire mais la transmet à la volée (AFAIK) ou à tout le moins la met en mémoire tampon dans un fichier temporaire.

Il y a l' option no option http-buffer-request , qui, si j'ai ce droit, désactive exactement ce comportement (écrit pour option http-buffer-request , sans no ):

Il est parfois souhaitable d'attendre le corps d'une requête HTTP avant
prendre une décision. C'est ce que fait "balance url_param" pour
Exemple. Le premier cas d'utilisation est de mettre en mémoire tampon les demandes des clients lents avant
connexion au serveur. Un autre cas d'utilisation consiste à prendre le routage
décision basée sur le contenu du corps de la requête. Cette option placée dans un
frontend ou backend force le traitement HTTP à attendre que soit l'ensemble
body est reçu, ou le tampon de requête est plein, ou le premier bloc est
complet en cas de codage fragmenté. Il peut avoir des effets secondaires indésirables avec
certaines applications abusent de HTTP en s'attendant à des transmissions sans tampon entre
le frontend et le backend, donc cela ne devrait certainement pas être utilisé par
défaut.

Je viens de frapper ça aussi. Il me semble qu'avec vos tests du même contenu fonctionnant sur HTTP mais pas HTTPS, il est peu probable que la taille de la mémoire tampon soit en faute, à moins que quelque chose entre votre client et le proxy ajoute beaucoup d'en-têtes supplémentaires.

Mais peut-être qu'il y a un bogue dans tout ce qui met fin à vos connexions SSL, de sorte qu'il corrompt légèrement les en-têtes.

Si tel est le cas, il existe une option qui réduit la sécurité de HAProxy, mais autorise un trafic HTTP moins conforme. Voir https://stackoverflow.com/questions/39286346/extra-space-in-http-headers-gives-400-error-on-haproxy

Bien que je ne recommande pas de réduire la sécurité comme solution finale, cela pourrait vous permettre de maintenir le service pendant que vous le déboguez.

@peterbrittain pour le moment asciinema.org utilise l'équilibreur de charge Brightbox Cloud, donc je ne contrôle pas leur configuration Haproxy. Nous avions l'habitude de terminer SSL dans notre propre Nginx et cela fonctionnait bien. Depuis que je suis passé à BB LB, ce problème se produit (pour certains). Le rencontrez-vous sous CentOS ou un autre système?

Franchement, je n'ai eu aucun problème avec la solution précédente basée sur Nginx. Le certificat SSL que nous avions expirait alors j'ai pensé que j'irais avec Let's Encrypt. Étant donné que les certificats LE sont de courte durée, ils sont mieux gérés automatiquement et Brightbox LB le fait pour moi. Je voulais juste me sauver du travail dans la configuration de LE et BB LB semblait être la solution la plus simple (puisque asciinema.org est sponsorisé par Brightbox et fonctionne sur leur excellente infrastructure). Maintenant, je pense que configurer moi-même LE dans Nginx prendrait probablement 1/10 du temps que j'ai déjà passé à résoudre ce problème 😞😞😞

Ah. Je n'ai pas repéré la subtilité de savoir qui possédait quels morceaux. Avez-vous eu de la chance d'obtenir des diagnostics de BB pour ce problème?

Et en réponse à votre question: ma box est une VM CentOS 6.

Je viens également de rencontrer le problème de la demande incorrecte, en utilisant asciinema 1.2.0 (version d'ubuntu 16.04 lts).

Le hack curl donné ci-dessus a fonctionné, merci.

Je viens de découvrir que le même fichier produit une mauvaise requête sur ma boîte Gentoo [1], mais pas sur ma boîte OpenBSD [2].
OpenBSD le télécharge très bien.
Je pense qu'il devrait y avoir une enquête plus approfondie sur la différence entre ces clients.
La boîte Gentoo prend en charge les cibles Python suivantes par ebuild:

PYTHON_TARGETS="python3_4 -python3_5"

Cependant, je ne peux pas tester facilement python3.5 actuellement, mais peut-être que cela aide déjà.

Edit : j'ai ajouté les versions d'OpenSSL, j'ai complètement oublié celles-ci.

  • asciinème 1.4.0

    • exécuté avec python-exec 2.4.5

    • à son tour en exécutant Python 3.4.6

  • OpenSSL 1.0.2l 25 mai 2017

  • asciinème 1.3.0

    • exécuté avec Python 3.6.0
  • LibreSSL 2.5.2

Je viens de revenir à la configuration précédente (terminaison de SSL dans Nginx). Faites-moi savoir si cela fonctionne pour vous maintenant @andyone @ThiefMaster @benaryorg @peterbrittain @ThomasWaldmann

@sickill Je suis sûr à 85% seulement que c'est le même fichier qui a échoué auparavant, mais si c'est le cas, vous l'avez corrigé.

@sickill Fonctionne comme un charme pour moi maintenant. 👍

Ouais, ça marche pour moi (avec asciinema upload ) aussi maintenant. Merci!

Cette page vous a été utile?
0 / 5 - 0 notes