ڪبرنيٽس سان زندگي کان: ڪيئن HTTP سرور اسپيني وارن کي پسند نه ڪيو

ڪبرنيٽس سان زندگي کان: ڪيئن HTTP سرور اسپيني وارن کي پسند نه ڪيو

اسان جي ڪلائنٽ جو هڪ نمائندو، جنهن جي ايپليڪيشن اسٽيڪ Microsoft ڪلائوڊ (Azure) ۾ رهي ٿي، هڪ مسئلي کي حل ڪيو: تازو، يورپ کان ڪجهه گراهڪن کان ڪجهه درخواستون غلطي 400 سان ختم ٿيڻ شروع ٿي ويون (خراب ڳولا). سڀئي ايپليڪيشنون .NET ۾ لکيل آهن، ڪبرنيٽس ۾ ترتيب ڏنل آهن ...

ايپليڪيشنن مان هڪ آهي API، جنهن جي ذريعي سڀ ٽرئفڪ آخرڪار اچي ٿو. هي ٽريفڪ HTTP سرور طرفان ٻڌايل آهي ڪيٿل.NET ڪلائنٽ پاران ترتيب ڏنل ۽ پوڊ ۾ ميزباني ڪئي وئي. ڊيبگنگ سان، اسان ان لحاظ کان خوش قسمت هئاسين ته اتي هڪ مخصوص صارف هو جيڪو مسلسل مسئلو ٻيهر پيدا ڪري ٿو. بهرحال، ٽريفڪ زنجير طرفان هر شي پيچيده هئي:

ڪبرنيٽس سان زندگي کان: ڪيئن HTTP سرور اسپيني وارن کي پسند نه ڪيو

Ingress ۾ غلطي هن طرح نظر آئي:

{
   "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":{}
}

ساڳئي وقت، Kestrel ڏنو:

HTTP/1.1 400 Bad Request
Connection: close
Date: Wed, 06 Mar 2019 12:34:20 GMT
Server: Kestrel
Content-Length: 0

جيتوڻيڪ وڌ ۾ وڌ فعل سان، Kestrel غلطي تي مشتمل آهي انتهائي ٿوري مفيد معلومات:

{
   "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":{}
}

اهو لڳي ٿو ته صرف tcpdump هن مسئلي کي حل ڪرڻ ۾ مدد ڪندو ... پر مان ٽرئفڪ جي زنجير بابت ورجائيندس:

ڪبرنيٽس سان زندگي کان: ڪيئن HTTP سرور اسپيني وارن کي پسند نه ڪيو

تحقيق

ظاهر آهي، اهو بهتر آهي ته ٽرئفڪ کي ٻڌڻ لاء انهي مخصوص نوڊ تي، جتي ڪبرنيٽس هڪ پوڊ لڳايو آهي: ڊمپ جو حجم اهڙو هوندو ته اهو ممڪن ٿيندو ته گهٽ ۾ گهٽ ڪا شيءِ جلدي ڳولڻ ممڪن ٿي سگهي. ۽ حقيقت ۾، جڏهن ان کي جانچيو، هيٺ ڏنل فريم محسوس ڪيو ويو:

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

ڊمپ جي ويجهو معائنو ڪرڻ تي، لفظ نظر آيو M.laga. اهو اندازو لڳائڻ آسان آهي ته اسپين ۾ ڪو M.laga شهر ناهي (پر اتي آهي مالگا). هن خيال تي قبضو ڪندي، اسان Ingress ترتيبن کي ڏٺو، جتي اسان هڪ مهينو اڳ داخل ٿيل ڏٺو (ڪلائنٽ جي درخواست تي) "بي ضرر" ٽڪرا:

    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;

انهن هيڊرز جي فارورڊنگ کي غير فعال ڪرڻ کان پوء، سڀ ڪجهه ٺيڪ ٿي ويو! (اهو جلد ئي واضح ٿي ويو ته ايپليڪيشن پاڻ کي هاڻي انهن هيڊرن جي ضرورت ناهي.)

هاڻي اچو ته مسئلي کي ڏسو وڌيڪ عام طور تي. اهو آساني سان ايپليڪيشن اندر ٻيهر پيدا ڪري سگهجي ٿو telnet جي درخواست ڪندي 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، جيئن توقع ڪئي وئي. ڇا ٿيندو جيڪڏهن اسان ڪندا آهيون:

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 - ايپليڪيشن لاگ ۾ اسان کي هڪ غلطي ملي ويندي جيڪا اسان کي اڳ ۾ ئي واقف آهي:

{
   "@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
}

نتيجو

خاص طور تي Kestrel نه ٿي سگهي UTF-8 ۾ صحيح اکرن سان HTTP هيڊرن کي صحيح طريقي سان عمل ڪريو، جيڪي ڪافي وڏي تعداد ۾ شهرن جي نالن تي مشتمل آهن.

اسان جي صورت ۾ هڪ اضافي عنصر اهو آهي ته ڪلائنٽ في الحال ايپليڪيشن ۾ ڪيسٽريل جي عمل کي تبديل ڪرڻ جو منصوبو ناهي. بهرحال، مسئلا پاڻ ۾ AspNetCore (نمبر4318, نمبر7707) اهي چون ٿا ته هي مدد نه ڪندو ...

اختصار ڪرڻ لاءِ: نوٽ هاڻي ڪاسٽل يا UTF-8 جي مخصوص مسئلن بابت نه آهي (2019 ۾؟!) ، پر حقيقت جي باري ۾ ته ذهني ۽ مسلسل مطالعو ھر قدم جيڪو توھان کڻندا آھيو مشڪلاتن جي ڳولا دوران جلد يا بعد ۾ ميوو کڻندو. سدا خوشقسمت رهو!

پي ايس

اسان جي بلاگ تي پڻ پڙهو:

جو ذريعو: www.habr.com

تبصرو شامل ڪريو