
Perwakilan klien kami, yang tumpukan aplikasi tinggal di cloud dari Microsoft (Azure), dihadapkan dengan masalah: baru-baru ini, sebagian permintaan beberapa klien dari Eropa mulai berakhir dengan kesalahan 400 (
Permintaan Buruk ). Semua aplikasi ditulis dalam .NET, digunakan di Kubernetes ...
Satu aplikasi adalah API yang melaluinya semua lalu lintas datang. Lalu lintas ini didengarkan oleh server HTTP
Kestrel yang dikonfigurasi oleh klien .NET dan di-host di pod. Dengan debugging, kami beruntung dalam arti bahwa ada pengguna tertentu yang memiliki masalah yang direproduksi stabil. Namun, semuanya rumit oleh rantai lalu lintas:

Kesalahan dalam Ingress terlihat seperti ini:
{ "number_fields":{ "status":400, "request_time":0.001, "bytes_sent":465, "upstream_response_time":0, "upstream_retries":0, "bytes_received":2328 }, "stream":"stdout", "string_fields":{ "ingress":"app", "protocol":"HTTP/1.1", "request_id":"f9ab8540407208a119463975afda90bc", "path":"/api/sign-in", "nginx_upstream_status":"400", "service":"app", "namespace":"production", "location":"/front", "scheme":"https", "method":"POST", "nginx_upstream_response_time":"0.000", "nginx_upstream_bytes_received":"120", "vhost":"api.app.example.com", "host":"api.app.example.com", "user":"", "address":"83.41.81.250", "nginx_upstream_addr":"10.240.0.110:80", "referrer":"https://api.app.example.com/auth/login?long_encrypted_header", "service_port":"http", "user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36", "time":"2019-03-06T18:29:16+00:00", "content_kind":"cache-headers-not-present", "request_query":"" }, "timestamp":"2019-03-06 18:29:16", "labels":{ "app":"nginx", "pod-template-generation":"6", "controller-revision-hash":"1682636041" }, "namespace":"kube-nginx-ingress", "nsec":6726612, "source":"kubernetes", "host":"k8s-node-55555-0", "pod_name":"nginx-v2hcb", "container_name":"nginx", "boolean_fields":{} }
Pada saat yang sama, Kestrel memberi:
HTTP/1.1 400 Bad Request Connection: close Date: Wed, 06 Mar 2019 12:34:20 GMT Server: Kestrel Content-Length: 0
Bahkan dengan verbositas maksimum, kesalahan Kestrel berisi sangat
sedikit informasi berguna :
{ "number_fields":{"ThreadId":76}, "stream":"stdout", "string_fields":{ "EventId":"{\"Id\"=>17, \"Name\"=>\"ConnectionBadRequest\"}", "SourceContext":"Microsoft.AspNetCore.Server.Kestrel", "ConnectionId":"0HLL2VJSST5KV", "@mt":"Connection id \"{ConnectionId}\" bad request data: \"{message}\"", "@t":"2019-03-07T13:06:48.1449083Z", "@x":"Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Malformed request: invalid headers.\n at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.TryParseRequest(ReadResult result, Boolean& endConnection)\n at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.<ProcessRequestsAsync>d__185`1.MoveNext()", "message":"Malformed request: invalid headers." }, "timestamp":"2019-03-07 13:06:48", "labels":{ "pod-template-hash":"2368795483", "service":"app" }, "namespace":"production", "nsec":145341848, "source":"kubernetes", "host":"k8s-node-55555-1", "pod_name":"app-67bdcf98d7-mhktx", "container_name":"app", "boolean_fields":{} }
Tampaknya hanya tcpdump yang akan membantu menyelesaikan masalah ini ... tapi saya akan mengulangi tentang rantai lalu lintas:

Investigasi
Jelas, lebih baik mendengarkan lalu lintas
di simpul tertentu tempat Kubernet mengerahkan pod: volume dump akan sedemikian rupa sehingga mungkin untuk menemukan setidaknya sesuatu dengan sangat cepat. Memang, ketika mempertimbangkannya, bingkai seperti itu diperhatikan:
GET /back/user HTTP/1.1 Host: api.app.example.com X-Request-ID: 27ceb14972da8c21a8f92904b3eff1e5 X-Real-IP: 83.41.81.250 X-Forwarded-For: 83.41.81.250 X-Forwarded-Host: api.app.example.com X-Forwarded-Port: 443 X-Forwarded-Proto: https X-Original-URI: /front/back/user X-Scheme: https X-Original-Forwarded-For: 83.41.81.250 X-Nginx-Geo-Client-Country: Spain X-Nginx-Geo-Client-City: M.laga Accept-Encoding: gzip CF-IPCountry: ES CF-RAY: 4b345cfd1c4ac691-MAD CF-Visitor: {"scheme":"https"} pragma: no-cache cache-control: no-cache accept: application/json, text/plain, */* origin: https://app.example.com user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36 referer: https://app.example.com/auth/login accept-language: en-US,en;q=0.9,en-GB;q=0.8,pl;q=0.7 cookie: many_encrypted_cookies; .AspNetCore.Identity.Application=something_encrypted; CF-Connecting-IP: 83.41.81.250 True-Client-IP: 83.41.81.250 CDN-Loop: cloudflare HTTP/1.1 400 Bad Request Connection: close Date: Wed, 06 Mar 2019 12:34:20 GMT Server: Kestrel Content-Length: 0
Setelah memeriksa dump dengan hati-hati, kata
M.laga
diperhatikan. Sangat mudah untuk menebak bahwa di Spanyol tidak ada kota M. laga (tetapi ada
Mรกlaga ). Memahami gagasan ini, kami melihat konfigurasi Ingress, tempat kami melihat
cuplikan "tidak berbahaya" dimasukkan sebulan yang lalu (atas permintaan klien):
ingress.kubernetes.io/configuration-snippet: | proxy_set_header X-Nginx-Geo-Client-Country $geoip_country_name; proxy_set_header X-Nginx-Geo-Client-City $geoip_city;
Saat Anda menonaktifkan penerusan tajuk ini, semuanya menjadi baik! (Segera menjadi jelas bahwa aplikasi itu sendiri tidak lagi membutuhkan tajuk ini.)
Sekarang mari kita lihat masalahnya
secara lebih umum . Itu dapat dengan mudah direproduksi di dalam aplikasi jika Anda membuat permintaan telnet ke
localhost:80
:
GET /back/user HTTP/1.1 Host: api.app.example.com cache-control: no-cache accept: application/json, text/plain, */* origin: https://app.example.com Cookie: test=Desiree
...
401 Unauthorized
, seperti yang diharapkan. Dan apa yang terjadi jika kita lakukan:
GET /back/user HTTP/1.1 Host: api.app.example.com cache-control: no-cache accept: application/json, text/plain, */* origin: https://app.example.com Cookie: test=Dรฉsirรฉe
?
400 Bad request
kembali - dalam log aplikasi kita akan mendapatkan kesalahan yang sudah kita ketahui:
{ "@t":"2019-03-31T12:59:54.3746446Z", "@mt":"Connection id \"{ConnectionId}\" bad request data: \"{message}\"", "@x":"Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Malformed request: invalid headers.\n at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.TryParseRequest(ReadResult result, Boolean& endConnection)\n at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.<ProcessRequestsAsync>d__185`1.MoveNext()", "ConnectionId":"0HLLLR1J974L9", "message":"Malformed request: invalid headers.", "EventId":{ "Id":17, "Name":"ConnectionBadRequest" }, "SourceContext":"Microsoft.AspNetCore.Server.Kestrel", "ThreadId":71 }
Ringkasan
Secara khusus, Kestrel
tidak dapat menangani header HTTP dengan karakter yang benar di UTF-8, yang terkandung dalam nama-nama sejumlah besar kota.
Faktor tambahan dalam kasus kami adalah bahwa klien saat ini tidak berencana untuk mengubah implementasi Kestrel dalam aplikasi. Namun, masalah di AspNetCore sendiri (
No. 4318 ,
No. 7707 ) mengatakan bahwa ini tidak akan membantu ...
Untuk meringkas: catatan tidak lagi tentang masalah spesifik Kestrel atau UTF-8 (pada tahun 2019, tahun?!), Tetapi bahwa
perhatian dan studi yang konsisten dari setiap langkah selama pencarian masalah akan cepat atau lambat membuahkan hasil. Semoga beruntung
PS
Baca juga di blog kami: