nginx + http2: преждевременно закрытое соединение в восходящем направлении, PROTOCOL_ERROR

1428
cdauth

На моем сервере nginx работает с использованием стандартного образа докера nginx (версия 1.13.8) в качестве обратного прокси-сервера для Lychee (с использованием wonderfall / lychee ), программы для создания фотогалереи, написанной на PHP. Насколько я могу судить, само изображение Lychee также запускает nginx с php7.1-fpm.

Галерея работает нормально, только при попытке загрузить изображение или альбом я получаю странную ошибку в браузере. Chromium говорит «Failed - Network error», а другие браузеры выдают похожие сообщения об ошибках. Эта ошибка появляется, когда загрузка завершена, и при использовании браузера, который сохраняет неудачные загрузки, можно увидеть, что загруженный файл фактически завершен.

Ошибка появляется только при доступе к Lychee через nginx и при использовании HTTP / 2. Журнал nginx сообщает:

2018/01/15 15:37:34 [error] 8#8: *2960 upstream prematurely closed connection while sending to client, client: 192.168.255.1, server: example.com, request: "GET /2018/php/index.php?function=Photo::getArchive&photoID=123&password= HTTP/2.0", upstream: "http://10.93.1.23:8888/php/index.php?function=Photo::getArchive&photoID=123&password=", host: "example.com" 

Бревно Личи ничего не сообщает.

При попытке загрузить файл с помощью curl -v, это вывод:

* Trying 1.2.3.4... * TCP_NODELAY set * Connected to example.com (1.2.3.4) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/certs/ca-certificates.crt CApath: none } [5 bytes data] * TLSv1.2 (OUT), TLS handshake, Client hello (1): } [226 bytes data] * TLSv1.2 (IN), TLS handshake, Server hello (2): { [106 bytes data] * TLSv1.2 (IN), TLS handshake, Certificate (11): { [2754 bytes data] * TLSv1.2 (IN), TLS handshake, Server key exchange (12): { [556 bytes data] * TLSv1.2 (IN), TLS handshake, Server finished (14): { [4 bytes data] * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): } [37 bytes data] * TLSv1.2 (OUT), TLS change cipher, Client hello (1): } [1 bytes data] * TLSv1.2 (OUT), TLS handshake, Finished (20): } [16 bytes data] * TLSv1.2 (IN), TLS handshake, Finished (20): { [16 bytes data] * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305 * ALPN, server accepted to use h2 * Server certificate: * subject: CN=example.com * start date: Dec 4 10:54:54 2017 GMT * expire date: Mar 4 10:54:54 2018 GMT * subjectAltName: host "example.com" matched cert's "example.com" * issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3 * SSL certificate verify ok. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 } [5 bytes data] * Using Stream ID: 1 (easy handle 0x55e8df551160) } [5 bytes data] > GET /2018/php/index.php?function=Photo::getArchive&photoID=123&password= HTTP/2 > Host: example.com > User-Agent: curl/7.57.0 > Accept: */* >  { [5 bytes data] * Connection state changed (MAX_CONCURRENT_STREAMS updated)! } [5 bytes data] < HTTP/2 200  < server: nginx/1.13.8 < date: Mon, 15 Jan 2018 15:37:34 GMT < content-type: application/octet-stream < content-length: 530149 < x-powered-by: PHP/7.1.2 < set-cookie: PHPSESSID=123; path=/2018/ < expires: Thu, 19 Nov 1981 08:52:00 GMT < cache-control: no-store, no-cache, must-revalidate < pragma: no-cache < content-disposition: attachment; filename="IMG_4872.jpg" < strict-transport-security: max-age=31536000 <  { [3691 bytes data] * HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1) * Closing connection 0 } [5 bytes data] * TLSv1.2 (OUT), TLS alert, Client hello (1): } [2 bytes data] 

При загрузке с HTTP / 1.1 все работает нормально:

* Trying 1.2.3.4... * TCP_NODELAY set * Connected to example.com (1.2.3.4) port 443 (#0) * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/certs/ca-certificates.crt CApath: none } [5 bytes data] * TLSv1.2 (OUT), TLS handshake, Client hello (1): } [223 bytes data] * TLSv1.2 (IN), TLS handshake, Server hello (2): { [112 bytes data] * TLSv1.2 (IN), TLS handshake, Certificate (11): { [2754 bytes data] * TLSv1.2 (IN), TLS handshake, Server key exchange (12): { [556 bytes data] * TLSv1.2 (IN), TLS handshake, Server finished (14): { [4 bytes data] * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): } [37 bytes data] * TLSv1.2 (OUT), TLS change cipher, Client hello (1): } [1 bytes data] * TLSv1.2 (OUT), TLS handshake, Finished (20): } [16 bytes data] * TLSv1.2 (IN), TLS handshake, Finished (20): { [16 bytes data] * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305 * ALPN, server accepted to use http/1.1 * Server certificate: * subject: CN=example.com * start date: Dec 4 10:54:54 2017 GMT * expire date: Mar 4 10:54:54 2018 GMT * subjectAltName: host "example.com" matched cert's "example.com" * issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3 * SSL certificate verify ok. } [5 bytes data] > GET /2018/php/index.php?function=Photo::getArchive&photoID=1234&password= HTTP/1.1 > Host: example.com > User-Agent: curl/7.57.0 > Accept: */* >  { [5 bytes data] < HTTP/1.1 200 OK < Server: nginx/1.13.8 < Date: Mon, 15 Jan 2018 15:43:36 GMT < Content-Type: application/octet-stream < Content-Length: 530149 < Connection: keep-alive < X-Powered-By: PHP/7.1.2 < Set-Cookie: PHPSESSID=1234; path=/2018/ < Expires: Thu, 19 Nov 1981 08:52:00 GMT < Cache-Control: no-store, no-cache, must-revalidate < Pragma: no-cache < Content-Disposition: attachment; filename="IMG_4872.jpg" < Strict-Transport-Security: max-age=31536000 <  { [3691 bytes data] * Connection #0 to host example.com left intact 

Наконец, вот вывод при непосредственном доступе к Личи:

* Trying 10.93.1.23... * TCP_NODELAY set * Connected to 10.93.1.23 (10.93.1.23) port 8888 (#0) > GET /php/index.php?function=Photo::getArchive&photoID=1234&password= HTTP/1.1 > Host: 10.93.1.23:8888 > User-Agent: curl/7.56.1 > Accept: */* >  < HTTP/1.1 200 OK < Server: nginx < Date: Mon, 15 Jan 2018 15:46:06 GMT < Content-Type: application/octet-stream < Content-Length: 530149 < Connection: keep-alive < X-Powered-By: PHP/7.1.2 < Set-Cookie: PHPSESSID=1234; path=/ < Expires: Thu, 19 Nov 1981 08:52:00 GMT < Cache-Control: no-store, no-cache, must-revalidate < Pragma: no-cache < Content-Disposition: attachment; filename="IMG_4872.jpg" <  { [14070 bytes data] * Connection #0 to host 10.93.1.23 left intact 

Я не понимаю, почему nginx говорит, что Lychee преждевременно закрыл соединение, когда фактически весь файл был передан (Content-Length также совпадает), и запуск curl вручную также не показывает никаких ошибок. У кого-нибудь есть идея?

1
У меня та же проблема - но с сервером express / nodejs, который обслуживает большие файлы (> 1,5 ГБ), я думаю, что-то не так с nginx (http2) и браузером, имеющим дело с буферизованным вводом / выводом. Мне пришлось отключить http2 на nginx, потому что этого.. :( SoichiH 6 лет назад 0
На самом деле, я думаю, что это связано с неправильной длиной содержимого. Я отправлял длину содержимого, которая меньше, чем фактическое содержимое, которое отправлял мой сервер. Итак, что-то идет не так на стороне клиента - возможно, преждевременное прерывание соединения? SoichiH 6 лет назад 0
@ SoichiH Я уверен, что длина содержимого соответствует моему размеру файла. Я проверю еще раз, хотя. Я смутно помню отчет об ошибке nginx где-то, где что-то подобное сообщалось в связи с sendFile (). Я не могу найти его сейчас, и я даже не уверен, что именно sendFile (), но Личи использует его. Ваше приложение также использует это? cdauth 6 лет назад 0

0 ответов на вопрос