Named Pipes व्यवहार में — डिज़ाइन से सुरक्षा तक, Windows की मानक IPC

· · Windows, IPC, Windows विकास, C#, C++, सुरक्षा, Win32 API

“मैं चाहता हूँ कि एक रेज़िडेंट सेवा और सेटिंग्स UI कमांड आपस में बदलें।” “मैं केवल एडमिनिस्ट्रेटर विशेषाधिकार चाहिए वाले काम को अलग प्रोसेस में अलग करना चाहता हूँ।” “मैं चाहता हूँ कि एक ही PC पर उपकरण एक-दूसरे को डेटा दें।” — Windows पर जब इस तरह की इंटर-प्रोसेस कम्युनिकेशन (IPC) ज़रूरी हो जाती है, तो सबसे पहले विचार करने योग्य मानक named pipe है।

Windows इंटर-प्रोसेस कम्युनिकेशन चुनने वाला लेख named pipes को “एक ही मशीन की IPC के लिए पहला उम्मीदवार” बताता है। यह लेख उसका विस्तृत उपचार है। वे पहला उम्मीदवार क्यों हैं, मोड और सर्वर रूप कैसे चुनें, और विशेषाधिकार वाली सेवा जब उन्हें उपयोग करे तो क्या सुरक्षित रखना चाहिए — Windows पर व्यावसायिक ऐप और सेवाएँ लिखने वाले डेवलपरों के लिए, ये डिज़ाइन निर्णय प्राथमिक स्रोतों से व्यवस्थित हैं।

1. निष्कर्ष पहले

  • Named pipe \\.\pipe\name रूप के नेमस्पेस वाला द्विदिश इंटर-प्रोसेस चैनल है। एक ही नाम के नीचे कई इंस्टेंस बना सकते हैं और एक साथ कई क्लाइंट स्वीकार कर सकते हैं।1
  • एक ही मशीन की IPC के लिए वे पहला उम्मीदवार इसलिए हैं कि सुरक्षा मॉडल मज़बूत है। ACL से कौन कनेक्ट करे नियंत्रित कर सकते हैं, और सर्वर क्लाइंट के Windows खाते को देख और उधार (impersonate) ले सकता है। Localhost TCP में इनमें से कुछ नहीं।2
  • यदि “एक लेखन = एक संदेश” मानना हो तो मैसेज मोड; यदि अपनी फ़्रेमिंग पहले से हो तो बाइट मोड। मैसेज मोड में भी छोटे बफ़र पर विभाजित रीड (ERROR_MORE_DATA) सँभालनी पड़ती है।3
  • कई क्लाइंट “कई इंस्टेंस + overlapped I/O” या “.NET async/await” से सँभालें। आधिकारिक नमूना एक थ्रेड पर कई इंस्टेंस संसाधित करने वाला रूप दिखाता है।4
  • सुरक्षा का न्यूनतम चार बिंदु है: रिमोट अस्वीकार (PIPE_REJECT_REMOTE_CLIENTS), ACL स्पष्ट करें, FILE_FLAG_FIRST_PIPE_INSTANCE से हाईजैक पकड़ें, और क्लाइंट पक्ष पर impersonation स्तर न्यूनतम रखें।56
  • ImpersonateNamedPipeClient के लिए रिटर्न वैल्यू जाँचना जीवनरेखा है। विफलता अनदेखी करें तो प्रोसेसिंग सर्वर के विशेषाधिकारों पर चलती रहती है।6

2. Named Pipe क्या है — नेमस्पेस, इंस्टेंस, और कनेक्शन कैसे काम करते हैं

Named pipe \\.\pipe\MyCompany.MyApp.Control जैसे नाम से पहचाना जाने वाला चैनल है। सर्वर इसे CreateNamedPipe से बनाता है, और क्लाइंट उसी नाम को CreateFile से खोलता है। खुलने के बाद दोनों पक्ष ReadFile / WriteFile से पढ़ते-लिखते हैं — विशिष्ट बात यह है कि फ़ाइल I/O जैसा ही रूप उपयोग कर सकते हैं।1

महत्त्वपूर्ण अवधारणा इंस्टेंस है। एक ही नाम की पाइप के कई इंस्टेंस बना सकते हैं, और एक इंस्टेंस एक क्लाइंट के साथ एक चैनल है। पहली CreateNamedPipe कॉल अधिकतम इंस्टेंस संख्या (या असीमित) तय करती है।3

क्लाइंट-पक्ष कनेक्शन का मानक नुस्खा है। जब हर इंस्टेंस व्यस्त हो, CreateFile ERROR_PIPE_BUSY से विफल होता है, इसलिए WaitNamedPipe से खाली का इंतज़ार करें और फिर पुनः प्रयास करें। साथ ही, खोलते समय निर्दिष्ट पहुँच उस दिशा से मेल खानी चाहिए जो सर्वर ने बनाई — द्विदिश पाइप पढ़ने या लिखने किसी से भी खोली जा सकती है, पर आउटबाउंड पाइप जिसे सर्वर केवल लिखता है केवल-पढ़ने के लिए खोलनी पड़ती है, और इनबाउंड पाइप जिसे सर्वर केवल पढ़ता है केवल-लिखने के लिए, वरना CreateFile विफल होता है।7

पाइप दिशा और क्लाइंट की पहुँचक्लाइंट द्विदिश पाइप को पढ़ने या लिखने किसी से खोल सकता है, पर सर्वर की केवल-लेखन आउटबाउंड पाइप केवल-पढ़ने, और केवल-पठन इनबाउंड पाइप केवल-लिखने के रूप में खोलनी चाहिएद्विदिशआउटबाउंडइनबाउंडसर्वर ने बनाई दिशा?पढ़ना या लिखना दोनों ठीककेवल-पढ़ना खोलेंकेवल-लिखना खोलें

चित्र 1: दिशा और पहुँच-विनिर्देश का बेमेल CreateFile विफलता बन जाता है। कनेक्शन त्रुटि जाँचते समय पहले यहाँ देखें।

Named pipe की बुनियादी संरचनासर्वर एक ही नाम के कई पाइप इंस्टेंस बनाता है और ConnectNamedPipe से कनेक्शन का इंतज़ार करता है; हर क्लाइंट CreateFile से नाम खोलता है और एक इंस्टेंस के साथ एक-से-एक द्विदिश चैनल पाता हैसर्वरइंस्टेंस 1इंस्टेंस 2इंस्टेंस 3क्लाइंट Aक्लाइंट Bक्लाइंट C

चित्र 2: एक ही नाम के कई इंस्टेंस रखकर एक सर्वर एक साथ कई क्लाइंट से एक-से-एक बात कर सकता है।

Named pipes SMB (\\server\pipe\name) से रिमोट भी खोली जा सकती हैं, पर आधुनिक डिज़ाइन में उसे सक्रिय उपयोग करने का लगभग कोई कारण नहीं; मुद्दा यह है कि जब उपयोग न कर रहे हों तो खुला न छोड़ें (अध्याय 5)।

3. बाइट मोड और मैसेज मोड

पाइप के दो ट्रांसफ़र मोड हैं।3

  • बाइट मोड (PIPE_TYPE_BYTE): TCP जैसा “अटूट बाइट स्ट्रीम”। एक संदेश कहाँ खत्म होता है यह आप तय करते हैं (लंबाई-उपसर्ग जैसी फ़्रेमिंग डिज़ाइन करते हैं)।
  • मैसेज मोड (PIPE_TYPE_MESSAGE + PIPE_READMODE_MESSAGE): एक लेखन एक संदेश माना जाता है, और पाठक उसे उसी इकाई में पाता है। अनुरोध/प्रतिक्रिया आदान-प्रदान के लिए यह आसान है।

मैसेज मोड का सुविधाजनक साथी TransactNamedPipe भी है, जो एक कॉल में अनुरोध भेजता और प्रतिक्रिया पाता है।8 पर एक जाल है। यदि रिसीव बफ़र पूरे संदेश से छोटा हो, तो रीड ERROR_MORE_DATA लौटाती है और विभाजित रीड बन जाती है। यह न मानें कि मैसेज मोड का अर्थ है “एक Read हमेशा पूरा ले आता है”; शेष पढ़ने वाला लूप फिर भी लिखना पड़ता है। ध्यान दें कि रीड मोड प्रति-हैंडल सेटिंग है, और CreateNamedPipe इसे केवल सर्वर पक्ष पर तय करता है। क्लाइंट CreateFile के बाद SetNamedPipeHandleState से निर्दिष्ट करता है (.NET में, कनेक्ट के बाद ReadMode)।7

मैसेज मोड में विभाजित-रीड लूपयदि ReadFile सफल हो तो संदेश पूरा है; यदि ERROR_MORE_DATA आए तो बफ़र में न समाए शेष को पढ़कर जोड़ें; कोई अन्य त्रुटि विच्छेद मानी जाती हैसफलताERROR_MORE_DATAकोई अन्य त्रुटिReadFile से पढ़ेंपरिणाम?संदेश पूराशेष पढ़ें और जोड़ेंविच्छेद मानें

चित्र 3: मैसेज मोड में भी “शेष-पढ़ने का लूप” चाहिए; उसके बिना केवल बड़े संदेश टूटते हैं।

बाइट मोड और मैसेज मोड का अंतरबाइट मोड में तीन लेखन अटूट बाइट स्ट्रीम बन जाते हैं और रिसीवर को काटना पड़ता है; मैसेज मोड में हर लेखन की इकाई सुरक्षित रहती है और रिसीवर तक वैसी ही पहुँचती हैबाइट मोड: AAA, BB, CCCC लिखेंस्ट्रीम AAABBCCCC के रूप में मिलाफ़्रेमिंग खुद डिज़ाइन करेंमैसेज मोड: वही तीन लेखनतीन संदेश: AAA, BB, CCCCलेखन इकाइयाँ सुरक्षित

चित्र 4: मैसेज मोड “लेखन की इकाई” सुरक्षित रखकर पहुँचाता है। फ़्रेमिंग डिज़ाइन अनावश्यक हो जाती है; केवल विभाजित रीड न भूलें।

चुनने का व्यावहारिक नियम सरल है। यदि आदान-प्रदान “अनुरोध और प्रतिक्रिया” रूप का हो, तो मैसेज मोडयदि ऐसा रूप ढो रहे हों जिसमें फ़्रेमिंग पहले से बनी हो (लंबाई-उपसर्ग सीरियलाइज़्ड डेटा या स्ट्रीम ट्रांसफ़र), तो बाइट मोड। .NET में PipeTransmissionMode.Message निर्दिष्ट करना पहले वाले से मेल खाता है।9

4. सर्वर डिज़ाइन — प्रति क्लाइंट एक थ्रेड, या Overlapped?

सर्वर का बुनियादी ऑपरेशन लूप है “इंस्टेंस बनाएँ → ConnectNamedPipe से क्लाइंट का इंतज़ार → पढ़ें और लिखें → विच्छेद करें और अगले क्लाइंट पर जाएँ”। एक साथ कई क्लाइंट से बात के दो रूप हैं।

सिंक्रोनस, प्रति इंस्टेंस एक थ्रेड। हर इंस्टेंस को एक थ्रेड देते हैं, और प्रत्येक अपने क्लाइंट से सिंक्रोनस I/O से बात करता है। कोड सीधा है, पर प्रति क्लाइंट एक थ्रेड खर्च होता है, और पूरा बंद करते समय ब्लॉकिंग I/O से निकलने का तरीका भी चाहिए।

Overlapped (असिंक्रोनस)। इंस्टेंस FILE_FLAG_OVERLAPPED से बनाते हैं, ConnectNamedPipe / ReadFile / WriteFile असिंक्रोनस जारी करते हैं, और थोड़े थ्रेड हर इंस्टेंस की पूर्णता सँभालते हैं। Microsoft का आधिकारिक नमूना WaitForMultipleObjects से इवेंट सरणी पर प्रतीक्षा करने वाला सर्वर दिखाता है जो एक थ्रेड पर कई इंस्टेंस संसाधित करता है4 असिंक्रोनस I/O का सामान्य विवरण I/O श्रृंखला लेख में है, और बड़े पैमाने पर IOCP या थ्रेड-पूल I/O भी जोड़ सकते हैं।

Overlapped सर्वर की संरचनाहर इंस्टेंस के असिंक्रोनस ऑपरेशन की पूर्णता इवेंट सरणी पर आती है, और थोड़े थ्रेड WaitForMultipleObjects से प्रतीक्षा कर पूर्ण इंस्टेंस आगे बढ़ाते हैं, जिससे थ्रेड संख्या क्लाइंट संख्या से अलग हो जाती हैइंस्टेंस 1 असिंक ऑपरेशनइवेंट सरणीइंस्टेंस 2 असिंक ऑपरेशनइंस्टेंस 3 असिंक ऑपरेशनWaitForMultipleObjects से प्रतीक्षापूर्ण इंस्टेंस आगे बढ़ाएँ

चित्र 5: Overlapped रूप थ्रेड संख्या को क्लाइंट संख्या से अलग करता है। आधिकारिक नमूना यह चक्र एक थ्रेड पर चलाता है।

.NET यह चुनाव लगभग हटा देता है। NamedPipeServerStream के WaitForConnectionAsync / ReadAsync / WriteAsync को async/await के साथ उपयोग करके, overlapped दक्षता सिंक्रोनस रूप जितने सीधे कोड में मिलती है।9

// C#: कई क्लाइंट स्वीकार करने वाले सर्वर का कंकाल
while (!token.IsCancellationRequested)
{
    var server = new NamedPipeServerStream(
        "MyCompany.MyApp.Control",
        PipeDirection.InOut,
        NamedPipeServerStream.MaxAllowedServerInstances,
        PipeTransmissionMode.Message,
        PipeOptions.Asynchronous | PipeOptions.CurrentUserOnly);

    try
    {
        await server.WaitForConnectionAsync(token);
    }
    catch
    {
        await server.DisposeAsync();        // dispose yourself when leaving before a connection
        throw;
    }
    _ = HandleClientAsync(server, token);   // ownership after connect goes to the handler
}

PipeOptions.CurrentUserOnly यह विनिर्देश है कि “केवल उसी उपयोगकर्ता के प्रोसेस से कनेक्शन अनुमति दें” — सुविधाजनक और सुरक्षित डिफ़ॉल्ट जो ACL खुद लिखने से बचाता है।10 उपयोगकर्ताओं को पार करने वाले सेटअप (सेवा ↔ यूज़र सेशन का ऐप, आदि) में यह उपयोग नहीं हो सकता, इसलिए उस स्थिति में अगले अध्याय के ACL डिज़ाइन पर जाएँ।

.NET असिंक्रोनस सर्वर का स्वीकार लूपस्वीकार लूप NamedPipeServerStream बनाता है, WaitForConnectionAsync से कनेक्शन का इंतज़ार करता है, आने पर क्लाइंट हैंडलिंग असिंक्रोनस अलग कर तुरंत अगले स्वीकार पर लौटता है, इसलिए समवर्ती कनेक्शन सीधे कोड में सँभलते हैंसर्वर स्ट्रीम बनाएँWaitForConnectionAsync से प्रतीक्षाकनेक्शन आता हैक्लाइंट हैंडलिंग असिंक अलग करें

चित्र 6: स्वीकार लूप “प्रतीक्षा → अलग करें → अगला” चक्र पर टिका रहता है, और हर क्लाइंट की प्रोसेसिंग समानांतर चलती है।

5. सुरक्षा — विशेषाधिकार वाली सेवा जब पाइप उपयोग करे तो चार अनिवार्य

Named pipes एक ही मशीन की IPC के लिए पहला उम्मीदवार इसलिए हैं कि सुरक्षा मॉडल है, पर वह केवल सही कॉन्फ़िगर करने पर। विशेषकर ब्रोकर डिज़ाइन में “एडमिनिस्ट्रेटर-विशेषाधिकार सेवा + कम-विशेषाधिकार UI ऐप”, पाइप स्वयं विशेषाधिकार सीमा है। चार बिंदु पक्के करें।

(1) रिमोट अस्वीकार करें। स्थानीय IPC के इरादे वाली पाइप नेटवर्क से खुल सकना अपने आप हमला-सतह है। CreateNamedPipe पर PIPE_REJECT_REMOTE_CLIENTS निर्दिष्ट करें तो रिमोट-क्लाइंट कनेक्शन स्वतः अस्वीकार होते हैं।5

(2) ACL स्पष्ट करें। SECURITY_ATTRIBUTES में सुरक्षा डिस्क्रिप्टर दें और कनेक्ट करने की अनुमति वाले उपयोगकर्ता व समूह संकीर्ण करें। क्लाइंट को GENERIC_WRITE न दें — उसमें शामिल FILE_CREATE_PIPE_INSTANCE अधिकार अधिकृत क्लाइंट को स्वयं उसी नाम का सर्वर इंस्टेंस बनाने और बाद के कनेक्शन चुराने देगा। पढ़ना और लिखना अलग अधिकारों के रूप में दें, और इंस्टेंस-निर्माण अधिकार न दें।11

(3) नाम हाईजैक रोकें। पाइप नाम पहले-आओ-पहले-पाओ हैं। यदि दुर्भावनापूर्ण प्रोसेस उसी नाम की पाइप पहले बनाए और प्रतीक्षा करे, तो क्लाइंट नकली सर्वर से जुड़ जाते हैं। सर्वर पहला इंस्टेंस बनाते समय FILE_FLAG_FIRST_PIPE_INSTANCE निर्दिष्ट करता है, जिससे “मैं पहले हूँ” की गारंटी मिलती है, और यदि वह विफल हो तो हाईजैक संदेह कर रुक जाता है। यह फ़्लैग केवल नाम दावे वाले पहले इंस्टेंस के लिए है; दूसरे और बाद के इंस्टेंस पर लगाने से निर्माण विफल होता है।3

(4) क्लाइंट impersonation स्तर ज़रूरत तक न्यूनतम रखे। यह उस स्थिति की तैयारी है जब साथी नकली सर्वर हो। यदि क्लाइंट CreateFile पर **SECURITY_SQOS_PRESENT SECURITY_IDENTIFICATION** निर्दिष्ट करे, तो सर्वर क्लाइंट पहचान सकता है पर वे विशेषाधिकार उधार लेकर काम नहीं कर सकता2 यह impersonation वर्कफ़्लो से ट्रेड-ऑफ़ है — ब्रोकर डिज़ाइन में जहाँ सर्वर क्लाइंट के विशेषाधिकारों के अधीन वास्तविक पहुँच करता है, identification स्तर impersonation सफल होने के लिए पर्याप्त नहीं, और SECURITY_IMPERSONATION की अनुमति देनी पड़ती है। वह अनुमति इस शर्त पर है कि आप पक्के हों कि असली सर्वर से जुड़े हैं। सर्वर-पक्ष एंटी-हाईजैक केवल वह तंत्र है जो विफल प्रारंभ से नोटिस करता है; यदि असली सेवा अनुपस्थित हो और हमलावर उसी नाम की पाइप पहले बनाए, तो क्लाइंट फिर भी नकली सर्वर से जुड़ सकता है। अनुमति केवल तब दें जब गारंटीशुदा सेवा प्रारंभ या कनेक्ट के बाद आपसी प्रमाणीकरण से साथी की पुष्टि हो सके।

सर्वर-पक्ष पहचान जाँच और विशेषाधिकार उधार ImpersonateNamedPipeClient है। पाइप से अनुरोध पढ़ने के बाद इसे कॉल करें तो कॉलिंग थ्रेड पढ़े गए अंतिम संदेश के भेजने वाले के सुरक्षा संदर्भ में चलने लगता है। क्लाइंट के विशेषाधिकारों से फ़ाइल खोलें तो पहुँच जाँच क्लाइंट के विरुद्ध होती है — वह तंत्र जिससे विशेषाधिकार वाली सेवा “अनुरोधित ऑपरेशन, अनुरोधकर्ता के विशेषाधिकारों से” निष्पादित करती है।6 उपयोग की पूर्ण शर्त रिटर्न वैल्यू जाँचना है। Impersonation विफल होने के बाद आगे बढ़ें तो बाद के ऑपरेशन सर्वर के अपने ऊँचे विशेषाधिकारों से चलते हैं। आधिकारिक दस्तावेज़ स्पष्ट कहता है कि “विफलता पर क्लाइंट का अनुरोध निष्पादित न करें”। काम के बाद RevertToSelf के साथ, impersonation टोकन वाले लेख की प्रथाएँ ज्यों की त्यों लागू होती हैं।

Impersonation उपयोग करने वाले अनुरोध हैंडलिंग का प्रवाहसर्वर पाइप से अनुरोध पढ़ता है, ImpersonateNamedPipeClient की सफलता पुष्टि करता है, फिर क्लाइंट के विशेषाधिकारों से ऑपरेशन करता है और RevertToSelf से अपने संदर्भ पर लौटता है। Impersonation विफल हो तो अनुरोध निष्पादित किए बिना अस्वीकार करता हैServerClientServerClientOn failure, refuse without executing the requestSend a requestRead the requestImpersonateNamedPipeClientPerform the operation with the client's privilegesRevertToSelf to restore the original contextReply with the result

चित्र 7: Impersonation की सफलता की पुष्टि और विश्वसनीय RevertToSelf एक पैकेज हैं। विफलता पर आगे बढ़ें तो सर्वर के विशेषाधिकारों से चलता है।

विशेषाधिकार सेवा की पाइप बचाने वाले चार बिंदुसर्वर पक्ष रिमोट अस्वीकार, स्पष्ट ACL और प्रथम-इंस्टेंस गारंटी से प्रवेश मज़बूत करता है; क्लाइंट पक्ष न्यूनतम impersonation स्तर निर्दिष्ट करता है ताकि नकली सर्वर विशेषाधिकार न उधार ले सके(यदि डिज़ाइन सर्वर को उधार न देता हो तो identification स्तर तक संकीर्ण करें)क्लाइंट पक्षन्यूनतम impersonation स्तरसर्वर पक्षPIPE_REJECT_REMOTE_CLIENTSACL से कनेक्टर सीमित करेंFIRST_PIPE_INSTANCE(केवल पहला)विशेषाधिकार सीमा के रूप में पाइप

चित्र 8: जिस डिज़ाइन में पाइप विशेषाधिकार सीमा है, सर्वर-पक्ष के तीन बिंदु और क्लाइंट-पक्ष का एक बिंदु एक सेट के रूप में लागू करें।

6. व्यावहारिक जाल

प्रारंभ क्रम की दौड़। यदि सर्वर ने पाइप बनाने से पहले क्लाइंट कनेक्ट आने लगे, तो “पाइप मौजूद नहीं” त्रुटि मिलती है। क्लाइंट पक्ष में “मौजूद नहीं → थोड़ा रुककर पुनः प्रयास” बनाएँ। इसके विपरीत, सर्वर पक्ष का सिद्धांत है क्लाइंट शुरू होने से पहले ConnectNamedPipe से सुनना शुरू करना।8

क्लाइंट कनेक्शन पुनः-प्रयास प्रवाहCreateFile से पाइप खोलें; यदि पाइप मौजूद न हो तो थोड़ी प्रतीक्षा कर पुनः प्रयास करें; यदि हर इंस्टेंस व्यस्त हो(ERROR_PIPE_BUSY)तो WaitNamedPipe से खाली का इंतज़ार कर पुनः प्रयास करें; सफलता पर संचार में प्रवेश करेंसफलतापाइप मौजूद नहींERROR_PIPE_BUSYCreateFile से खोलेंपरिणाम?संचार शुरू करेंथोड़ी प्रतीक्षा(सर्वर नहीं चला)WaitNamedPipe से खाली इंस्टेंस

चित्र 9: क्लाइंट कनेक्शन हैंडलिंग “मौजूद नहीं” और “भरा” दो विफलताओं को अलग करती है और दोनों को पुनः-प्रयास में जोड़ती है।

विच्छेद पकड़ना। साथी निकलने पर Read/Write ERROR_BROKEN_PIPE आदि से विफल होते हैं। वह विसंगति नहीं; रोज़ का संचार है। सर्वर विच्छेद पकड़ता है, इंस्टेंस पर DisconnectNamedPipe करता है, और अगले कनेक्शन की तैयारी करता है; क्लाइंट पुनः जुड़ता है — sleep/resume वाले लेख में वर्णित “इडेम्पोटेंट पुनः-कनेक्शन” का विचार यहाँ भी लागू होता है।

संदेश आकार की धारणाएँ। मैसेज मोड की विभाजित रीड (अध्याय 3) के ऊपर, यदि प्रोटोकॉल के भाग के रूप में “एक संदेश के अधिकतम बाइट क्या हैं” न तय करें, तो दुर्भावनापूर्ण (या बगी) साथी विशाल संदेश से मेमोरी बर्बाद कर सकता है। ऊपरी सीमा तय करें, और पार होने पर विच्छेद करें; यही सुरक्षित तरीका है।

लेखन पूर्णता और साथी का प्राप्त करना अलग बातें हैं। WriteFile की सफलता का अर्थ यह नहीं कि साथी के ऐप ने डेटा संसाधित कर लिया। निश्चितता चाहिए वाले ऑपरेशन प्रतिक्रिया संदेश से पुष्टि, और प्रोटोकॉल में अनुरोध-प्रतिक्रिया का मेल शामिल करने जैसे डिज़ाइन से समर्थित होते हैं।

7. सारांश

  • Named pipes एक ही मशीन की IPC के लिए पहला उम्मीदवार हैं। कारण फ़ाइल I/O जैसी सहजता, और ACL व impersonation के Windows सुरक्षा मॉडल से एकीकरण है।
  • मोड चुनाव है “अनुरोध और प्रतिक्रिया के लिए मैसेज मोड, अपनी फ़्रेमिंग पहले से हो तो बाइट मोड”। मैसेज मोड में भी विभाजित रीड (ERROR_MORE_DATA) सँभालनी पड़ती है।
  • कई क्लाइंट कई इंस्टेंस + overlapped, या .NET async/await। नए काम के लिए .NET असिंक्रोनस रूप सीधा है।
  • विशेषाधिकार सीमा वाली पाइप पर रिमोट अस्वीकार, स्पष्ट ACL, FIRST_PIPE_INSTANCE (केवल पहला इंस्टेंस), और क्लाइंट-पक्ष impersonation स्तर न्यूनतम — इन्हें एक सेट के रूप में लें।
  • ImpersonateNamedPipeClient के लिए रिटर्न वैल्यू जाँचना और RevertToSelf जीवनरेखा हैं।
  • “संचार का रोज़” — प्रारंभ क्रम, विच्छेद, संदेश ऊपरी सीमा, प्रतिक्रिया पुष्टि — को प्रोटोकॉल डिज़ाइन में बुनें।

Named pipes पुरानी API हैं, पर “एक ही मशीन पर प्रोसेस को Windows खाता सीमाओं का सम्मान करते हुए बात करवाने” के उपयोग के लिए वे अभी भी सबसे स्वाभाविक उपकरण हैं। डिज़ाइन-निर्णय बिंदु लगभग इस लेख की सीमा में समाप्त हो जाते हैं। उसके बाद, इम्प्लीमेंटेशन शुरू करने से पहले अपना प्रोटोकॉल एक पन्ने पर लिख लें।

संबंधित लेख

संबंधित परामर्श क्षेत्र

KomuraSoft LLC इंटर-प्रोसेस कम्युनिकेशन वाले डिज़ाइन और इम्प्लीमेंटेशन सँभालता है — सेवा को UI ऐप से अलग करना, एडमिनिस्ट्रेटर विशेषाधिकार अलग करना, आदि — मौजूदा IPC (शेयर्ड मेमोरी, घर का बना सॉकेट, COM, आदि) को named pipes से बदलना, और विशेषाधिकार वाली सेवा की पाइप कम्युनिकेशन की सुरक्षा समीक्षा। प्रोटोकॉल डिज़ाइन पर राय माँगने से परामर्श स्वागत योग्य है।

संदर्भ लिंक

  1. Microsoft Learn, Named Pipes. Named pipe पाइप सर्वर और एक या अधिक पाइप क्लाइंट के बीच एकदिश या द्विदिश चैनल होने पर; हर इंस्टेंस एक ही नाम साझा करते हुए स्वतंत्र बफ़र और हैंडल रखने पर; और स्थानीय व रिमोट प्रोसेस से उपयोग योग्य होने पर।  2

  2. Microsoft Learn, Impersonating a Named Pipe Client. Impersonation सर्वर थ्रेड को क्लाइंट के विशेषाधिकारों के भीतर काम देने पर; डिफ़ॉल्ट impersonation स्तर SecurityImpersonation होने पर; और क्लाइंट के CreateFile समय SECURITY_SQOS_PRESENT फ़्लैग से impersonation स्तर नियंत्रित कर सकने पर (SECURITY_IDENTIFICATION केवल पहचान अनुमति देता है)।  2

  3. Microsoft Learn, CreateNamedPipeW function (namedpipeapi.h). पाइप दिशा (इनबाउंड, आउटबाउंड, द्विदिश), बाइट प्रकार और मैसेज प्रकार (PIPE_TYPE_BYTE / PIPE_TYPE_MESSAGE) तथा रीड मोड (PIPE_READMODE_MESSAGE), अधिकतम इंस्टेंस संख्या (PIPE_UNLIMITED_INSTANCES), FILE_FLAG_OVERLAPPED से असिंक्रोनस मोड, FILE_FLAG_FIRST_PIPE_INSTANCE से प्रथम-इंस्टेंस गारंटी, और WaitNamedPipe का डिफ़ॉल्ट टाइमआउट।  2 3 4

  4. Microsoft Learn, Named Pipe Server Using Overlapped I/O. Overlapped ऑपरेशन से कई क्लाइंट के समकालिक कनेक्शन संसाधित करने वाले एकल-थ्रेड सर्वर के आधिकारिक नमूने पर। हर इंस्टेंस की OVERLAPPED संरचना और इवेंट पर WaitForMultipleObjects से प्रतीक्षा कर पूर्ण इंस्टेंस की स्टेट मशीन आगे बढ़ाने वाले रूप पर, और GetOverlappedResult से लंबित I/O की पूर्णता पुष्टि पर।  2

  5. Microsoft Learn, CreateNamedPipeW function (namedpipeapi.h). दो रिमोट-क्लाइंट मोड पर, PIPE_ACCEPT_REMOTE_CLIENTS (रिमोट कनेक्शन स्वीकार कर सुरक्षा डिस्क्रिप्टर के विरुद्ध जाँचना) और PIPE_REJECT_REMOTE_CLIENTS (रिमोट-क्लाइंट कनेक्शन स्वतः अस्वीकार)।  2

  6. Microsoft Learn, ImpersonateNamedPipeClient function (namedpipeapi.h). सर्वर-पक्ष थ्रेड के पाइप से पढ़े गए अंतिम संदेश के क्लाइंट के सुरक्षा संदर्भ में impersonation शुरू करने पर; पूर्णता के बाद RevertToSelf से लौटने पर; और impersonation विफल होने के बाद आगे बढ़ने से सर्वर प्रोसेस के अपने (विशेषाधिकार वाले) संदर्भ में निष्पादन होने पर, इसलिए रिटर्न वैल्यू हमेशा जाँचें और विफलता पर क्लाइंट का अनुरोध निष्पादित न करें।  2 3

  7. Microsoft Learn, Named Pipe Client. क्लाइंट के CreateFile से पाइप खोलने पर; हर इंस्टेंस व्यस्त होने पर ERROR_PIPE_BUSY, WaitNamedPipe से खाली का इंतज़ार; और खुले हैंडल के डिफ़ॉल्ट बाइट-रीड, ब्लॉकिंग, और गैर-overlapped होने पर, जिसे SetNamedPipeHandleState मैसेज-रीड मोड में बदल सकता है।  2

  8. Microsoft Learn, Named Pipe Operations. ReadFileEx / WriteFileEx से overlapped ऑपरेशन, PeekNamedPipe से गैर-उपभोग रीड, मैसेज-प्रकार द्विदिश पाइप पर TransactNamedPipe का एक कॉल में अनुरोध भेजना और प्रतिक्रिया पाना, और क्लाइंट शुरू होने से पहले ब्लॉकिंग रीड दौड़ पैदा कर सकने पर।  2

  9. Microsoft Learn, How to: Use Named Pipes for Network Interprocess Communication (.NET). NamedPipeServerStream / NamedPipeClientStream से कनेक्ट और पढ़ना/लिखना, PipeTransmissionMode.Message से मैसेज-इकाई ट्रांसफ़र, और असिंक्रोनस विधियों से कई क्लाइंट सँभालने पर।  2

  10. Microsoft Learn, PipeOptions Enum (System.IO.Pipes). Asynchronous से असिंक्रोनस I/O सक्षम करने पर, और CurrentUserOnly के केवल उसी उपयोगकर्ता (और उसी elevation स्तर) के प्रोसेस से कनेक्शन अनुमति दे सकने पर। 

  11. Microsoft Learn, Named Pipe Security and Access Rights. Named-pipe पहुँच अधिकारों की संरचना पर; GENERIC_WRITE में FILE_CREATE_PIPE_INSTANCE शामिल होने पर, जिससे क्लाइंट को सामान्य लेखन देने से सर्वर इंस्टेंस बनाना भी अनुमति हो जाता है; और डेटा का पढ़ना-लिखना अलग पहुँच अधिकारों के रूप में दिए जाने पर। 

निकटवर्ती विषयों में गहराई से जाने के लिए समान टैग वाले नवीनतम लेख।

Windows वर्चुअलाइज़ेशन की गहराई (भाग 2) — वह मेमोरी जिसे कर्नेल भी नहीं देख सकता: VBS, HVCI और Credential Guard कैसे काम करते हैं

संगत हार्डवेयर पर क्लीन इंस्टॉल पर VBS डिफ़ॉल्ट से सक्षम होता है और हाइपरवाइज़र तथा SLAT से कर्नेल से मज़बूत अलगाव बनाता है। यह लेख VTL, ...

Windows वर्चुअलाइज़ेशन की गहराई (भाग 3) — सेकंडों में बूट होने वाली वर्चुअल मशीनें: WSL2, Windows Sandbox और कंटेनर इतने हल्के क्यों हैं

WSL2 और Windows Sandbox सेकंडों में शुरू होकर इतने हल्के क्यों लगते हैं? यह लेख डायनामिक बेस इमेज और डायरेक्ट मैप से डायनामिक मेमोरी आवंट...

Windows वर्चुअलाइज़ेशन की गहराई (भाग 1) — आपका Windows वास्तव में कहाँ चल रहा है? हाइपरवाइज़र और पार्टीशन

जब आप Hyper-V सक्षम करते हैं, तो होस्ट Windows स्वयं रूट पार्टीशन के रूप में हाइपरवाइज़र के ऊपर चलता है। यह लेख VT-x, SLAT और VMBus की भू...

क्षेत्र के नाम वाली खोजों में दिखें — छोटे-मझोले उद्यमों के लिए लोकल SEO की व्यावहारिक मार्गदर्शिका (क्षेत्र पृष्ठ और Google Business Profile)

उन छोटे-मझोले उद्यमों के लिए जिनकी साइट "क्षेत्र का नाम + उद्योग" खोजने पर नहीं दिखती। यह लेख लोकल SEO सुधारने का क्रम बताता है: Google B...

ये पृष्ठ विषय को सेवाओं और निर्णयों के व्यापक संदर्भ में रखते हैं।

यह लेख निम्नलिखित सेवाओं से सीधे जुड़ा है।

अक्सर पूछे जाने वाले प्रश्न

इस लेख के विषय पर परामर्श में अक्सर पूछे जाने वाले प्रश्न।

Named pipes और TCP (localhost सॉकेट) में चुनाव कैसे करें?
एक ही मशीन पर इंटर-प्रोसेस कम्युनिकेशन के लिए named pipe पहला उम्मीदवार है। कारण सुरक्षा मॉडल है। पाइप Windows सुरक्षा डिस्क्रिप्टर (ACL) से OS स्तर पर नियंत्रित कर सकती है कि "कौन कनेक्ट कर सकता है", और सर्वर ImpersonateNamedPipeClient से कनेक्ट करने वाले साथी के Windows खाते को देख और उधार ले सकता है। इसके विपरीत localhost TCP पोर्ट से कोई भी कनेक्ट कर सकता है, इसलिए साथी कौन है यह अपनी प्रमाणीकरण से स्थापित करना पड़ता है। दूसरी ओर, जब बाद में रिमोट कम्युनिकेशन बनने की संभावना हो, जब दूसरे OS के प्रोसेस से भी बात करनी हो, या जब gRPC जैसी मौजूदा प्रोटोकॉल संपत्ति दोहरानी हो, तब TCP-आधारित विकल्प लाभदायक हैं। यह निर्णय Windows इंटर-प्रोसेस कम्युनिकेशन चुनने वाले लेख में भी रखा गया है।
बाइट मोड उपयोग करें या मैसेज मोड?
यदि आप "एक लेखन = अर्थ की एक इकाई" मानना चाहते हैं, तो मैसेज मोड (PIPE_TYPE_MESSAGE + PIPE_READMODE_MESSAGE) सुविधाजनक है। रिसीवर उसी इकाइयों में पढ़ सकता है जिनमें भेजने वाले ने लिखा, इसलिए सीमाएँ खुद सँभालनी नहीं पड़तीं। बाइट मोड TCP जैसा "अटूट बाइट स्ट्रीम" है, और फ़्रेमिंग खुद डिज़ाइन करनी पड़ती है — उदाहरण के लिए लंबाई-उपसर्ग। यदि आप ऐसा प्रोटोकॉल ढो रहे हैं जिसमें फ़्रेमिंग पहले से है (जैसे लंबाई-उपसर्ग वाला सीरियलाइज़्ड रूप), तो बाइट मोड ठीक है। सावधानी: मैसेज मोड में भी यदि रिसीव बफ़र मैसेज से छोटा हो तो विभाजित रीड मिलती है (ERROR_MORE_DATA), इसलिए उसे भी सँभालना पड़ता है। साथ ही, रीड मोड प्रति-हैंडल सेटिंग है, और CreateNamedPipe इसे केवल सर्वर पक्ष पर सेट करता है। क्लाइंट को CreateFile के बाद SetNamedPipeHandleState से PIPE_READMODE_MESSAGE निर्दिष्ट करना होता है। .NET में सर्वर PipeTransmissionMode.Message निर्दिष्ट करता है, और क्लाइंट कनेक्ट के बाद NamedPipeClientStream.ReadMode को Message सेट करता है।
एक साथ कई क्लाइंट से बात करने वाला सर्वर कैसे बनाएँ?
Named pipe एक ही नाम के नीचे कई इंस्टेंस बना सकती है, और एक इंस्टेंस एक क्लाइंट सँभालता है। दो रूप हैं। एक सिंक्रोनस डिज़ाइन जो प्रति क्लाइंट एक थ्रेड देता है; इम्प्लीमेंटेशन सीधा है, पर प्रति क्लाइंट एक थ्रेड खर्च होता है। दूसरा FILE_FLAG_OVERLAPPED से असिंक्रोनस I/O उपयोग करना और थोड़े थ्रेड से हर इंस्टेंस के ConnectNamedPipe, ReadFile और WriteFile सँभालना; Microsoft के आधिकारिक नमूने में एक थ्रेड पर कई इंस्टेंस संसाधित करने वाली इम्प्लीमेंटेशन भी दिखती है। .NET में NamedPipeServerStream.WaitForConnectionAsync और async/await से असिंक्रोनस रूप लगभग उतनी ही सरलता से लिखा जा सकता है जितना सिंक्रोनस। विशेष कारण न हो तो नई इम्प्लीमेंटेशन के लिए .NET असिंक्रोनस रूप ही सुझाया जाता है।
Named-pipe सुरक्षा के लिए न्यूनतम क्या करना चाहिए?
चार बिंदु। पहला, यदि रिमोट कनेक्शन की ज़रूरत नहीं, तो PIPE_REJECT_REMOTE_CLIENTS निर्दिष्ट करें और नेटवर्क से कनेक्शन स्पष्ट रूप से अस्वीकार करें। दूसरा, SECURITY_ATTRIBUTES से उपयुक्त ACL सेट करें और कनेक्ट कर सकने वाले उपयोगकर्ता व समूह संकीर्ण करें (डिफ़ॉल्ट ACL कुछ उपयोगों के लिए बहुत ढीला है)। तीसरा, पहला इंस्टेंस बनाते समय FILE_FLAG_FIRST_PIPE_INSTANCE निर्दिष्ट करें, ताकि "नाम हाईजैक" पकड़े जिसमें उसी नाम की पाइप पहले बन जाए (दूसरे और बाद के इंस्टेंस पर यह फ़्लैग न लगाएँ)। चौथा, जो क्लाइंट केवल सर्वर से अपनी पहचान करवाना चाहता है उसे CreateFile पर SECURITY_SQOS_PRESENT|SECURITY_IDENTIFICATION निर्दिष्ट करना चाहिए, ताकि नकली सर्वर उसके विशेषाधिकार उधार (impersonate) न ले सके। ब्रोकर डिज़ाइन में जहाँ सर्वर क्लाइंट के विशेषाधिकारों के अधीन वास्तविक पहुँच करता है, impersonation की अनुमति देनी पड़ती है, इसलिए यह प्रतिबंध डिज़ाइन के अनुसार लगाएँ या न लगाएँ — इस पर निर्भर कि सर्वर को विशेषाधिकार उधार लेने दिए गए हैं या नहीं।
ImpersonateNamedPipeClient उपयोग करते समय क्या सावधानियाँ हैं?
सबसे महत्त्वपूर्ण रिटर्न वैल्यू जाँचना है। यदि impersonation विफल होने के बाद भी आगे बढ़ें, तो बाद के ऑपरेशन सर्वर प्रोसेस के अपने (अक्सर ऊँचे) विशेषाधिकारों से चलते हैं, और जो काम क्लाइंट को नहीं मिलने चाहिए थे वे पास हो जाते हैं। आधिकारिक दस्तावेज़ स्पष्ट कहता है कि विफलता पर क्लाइंट का अनुरोध निष्पादित न करें। इसे केवल कुछ पढ़ने के बाद ही कॉल करें — impersonation "पाइप से पढ़े गए अंतिम संदेश" के संदर्भ में होता है — और काम पूरा होने पर RevertToSelf से मूल संदर्भ पर विश्वसनीय रूप से लौटें। Impersonation के आसपास की मशीनरी (टोकन, impersonation स्तर, SeImpersonatePrivilege) impersonation टोकन वाले लेख में विस्तार से है।

लेखक की प्रोफ़ाइल

लेख के लेखक का परिचय पृष्ठ।

Go Komura

KomuraSoft LLC के प्रतिनिधि

Windows सॉफ़्टवेयर विकास, तकनीकी परामर्श और बग जाँच में विशेषज्ञ, विशेष रूप से मौजूदा सिस्टम वाली परियोजनाओं और पुनरुत्पादन में कठिन बग में।

सार्वजनिक लिंक

ब्लॉग पर लौटें