
Përfaqësuesi i klientit tonë, i cili ka një grup aplikacionesh në cloud-in e Microsoft (Azure), na kontaktuara për një problem: që nga kohët e fundit, disa kërkesa nga klientë në Evropë filluan të përfundojnë me një gabim 400 (). Të gjitha aplikacionet janë të shkruara në .NET, të publikuara në Kubernetes...
Një nga aplikacionet është API-ja, përmes së cilës në fund të fundit vjen gjithë trafiku. Ky trafik i dëgjon serveri HTTP , i konfiguruar nga klienti në .NET dhe vendosur në pod. Kemi pasur fat me debugimin në atë kuptim që kishte një përdorues të caktuar, te i cili problemi ishte vazhdimisht i riprodhueshëm. Megjithatë, gjithçka u komplikuar nga zinxhiri i trafikut:

Gabimi në Ingress dukej kështu:
{
"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":{}
}Në të njëjtën kohë, Kestrel po kthehej:
HTTP/1.1 400 Kërkesë e Keqe
Connection: close
Date: Wed, 06 Mar 2019 12:34:20 GMT
Server: Kestrel
Content-Length: 0Edhe me nivelin më të lartë të verbosity, gabimi i Kestrel kishte jashtëzakonisht pak informacion të dobishëm:
{
"number_fields":{"ThreadId":76},
"stream":"stdout",
"string_fields":{
"EventId":"{"Id"=>17, "Name"=>"ConnectionBadRequest"}",
"SourceContext":"Microsoft.AspNetCore.Server.Kestrel",
"ConnectionId":"0HLL2VJSST5KV",
"@mt":"Identiteti i lidhjes "{ConnectionId}" kishte të dhëna të kërkesës të këqija: "{message}"",
"@t":"2019-03-07T13:06:48.1449083Z",
"@x":"Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Kërkesë e gabuar: kapituj të pavlefshëm.n në Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.TryParseRequest(ReadResult result, Boolean& endConnection)n në Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.<ProcessRequestsAsync>d__185`1.MoveNext()",
"message":"Kërkesë e gabuar: kapituj të pavlefshëm."
},
"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":{}
}Duket se vetëm tcpdump do të ndihmojë në zgjidhjen e këtij problemi⊠por e përsëris për rrjedhën e trafikut:

Hulumtimi
Duket qartë se është më mirë të dëgjosh trafikun në atë nyje të veçantë, ku Kubernetes ka vendosur pod-in: volumi i dump-it do të jetë i tillë, saqë do të jetë mjaft e lehtë të gjesh diçka. Dhe në të vërtetë, gjatë shqyrtimit u vërejt një kadër i tillë:
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: Spanjë
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, si 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 Në shqyrtimin e kujdesshëm të dump-it u vërejt fjala M.laga. E lehtë për t'u kuptuar se në Spanjë nuk ka qytet M.laga (përkundrazi ka ). Duke u kapur pas kësaj ideje, ne shqyrtuam konfigurimet e Ingress, ku pamë një snippet "të padëmshëm" të vendosur para një muaji (në kërkesën e klientit) «Snippet i padëmshëm»:
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;Pasi u çaktivizuan këto tituj, gjithçka ishte në rregull! (shpejt u zbulua se këto tituj më nuk ishin të nevojshme për aplikacionin vetë.)
Tani le të shikojmë problemin në një formë më të përgjithshme. E lehtë për tu riprodhuar brenda aplikacionit, nëse bëhet një kërkesë telnet për 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 ⊠kthehet 401 Jo e autorizuar, ashtu siç pritej. Po çfarë do ndodhë nëse bëjmë:
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?
Do tĂ« kthehet 400 KĂ«rkesĂ« e gabuar â nĂ« logun e aplikacionit do tĂ« marrim tashmĂ« njohur kĂ«tĂ« gabim:
{
"@t":"2019-03-31T12:59:54.3746446Z",
"@mt":"ID i lidhjes "{ConnectionId}" të dhëna të kërkesës të gabuar: "{message}"",
"@x":"Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Kërkesë e deformuar: headers të pavlefshëm.n në Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.TryParseRequest(ReadResult result, Boolean& endConnection)n në Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.<ProcessRequestsAsync>d__185`1.MoveNext()",
"ConnectionId":"0HLLLR1J974L9",
"message":"Kërkesë e deformuar: headers të pavlefshëm.",
"EventId":{
"Id":17,
"Name":"ConnectionBadRequest"
},
"SourceContext":"Microsoft.AspNetCore.Server.Kestrel",
"ThreadId":71
}Përfundime
Konkrete Kestrel të përpunojë saktë headers HTTP me karaktere të sakta në UTF-8, të cilat përmbajnë emrat e një numri të madh qytetesh.
NjĂ« faktor shtesĂ« nĂ« rastin tonĂ« â ndryshimi i implementimit tĂ« Kestrel nĂ« aplikacion klienti momentalisht nuk Ă«shtĂ« nĂ« plan. MegjithatĂ«, çështjet nĂ« vetĂ« AspNetCore (, ) flasin pĂ«r faktin se kjo as qĂ« do ndihmojĂ«âŠ
Për t'ia dalë: shënimi nuk është më për probleme specifike të Kestrel ose UTF-8 (në vitin 2019?!), por për faktin se vëmendja dhe studimi i ndjekshëm i çdo hapi gjatë kërkimit të problemit do të japë rezultate në një moment. Për fat të mbarë!
P.S.
Lexoni gjithashtu në blogun tonë:
- «»;
- «»;
- «»;
- «»;
- «».
Burimi: habr.com
