मेरे पास एक कस्टम टीसीपी सर्वर है जिसे पायथन 3.5 की एसिंक्सियो लाइब्रेरी के साथ लागू किया गया है। मैं सर्वर के साथ संचार के एसएसएल एन्क्रिप्शन के लिए लेट्स एनक्रिप्ट सर्टिफिकेट का भी उपयोग करता हूं। लेट्स एनक्रिप्ट केवल 90 दिनों के लिए वैध प्रमाण पत्र जारी करता है और एक अच्छा मौका है कि मेरा सर्वर इससे अधिक समय तक पुनरारंभ नहीं होगा।

मैं इस तरह SSLContext उत्पन्न कर रहा हूं:

ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
ssl_context.load_cert_chain(certfile='path/to/cert', keyfile='path/to/key')

और सर्वर इस तरह है:

server = asyncio.streams.start_server(self._accept_client, ip, port, loop=self.loop, ssl=ssl_context)

जब प्रमाणपत्र समाप्त हो जाता है, तो मौजूदा कनेक्शन कार्य करना जारी रखते हैं लेकिन नए कनेक्शन (सही ढंग से) विफल हो जाएंगे। जाहिर तौर पर SSLContext या सर्वर ही सर्टिफिकेट और की फाइलों को मेमोरी में लोड रखता है क्योंकि डिस्क पर फाइलों को अपडेट करने से समस्या का समाधान नहीं होता है।

मैंने पायथन प्रलेखन को काफी कुछ पढ़ा है और कोई समाधान नहीं मिला है। मेरे पास एक विचार है कि ssl_context.load_cert_chain() को नियमित अंतराल पर इस उम्मीद के साथ कॉल करने का प्रयास करें कि यह प्रमाणपत्र और कुंजी को अपडेट कर देगा। मैं इसके व्यवहार को निर्धारित करने के लिए load_cert_chain फ़ंक्शन के स्रोत को नहीं देख सकता क्योंकि यह स्पष्ट रूप से सी में लिखा गया है, और दस्तावेज़ीकरण सर्वर पर संदर्भ पारित होने के बाद इस फ़ंक्शन को कॉल करने के व्यवहार को निर्दिष्ट नहीं करता है .

क्या सर्वर को पूरी तरह से रोके और फिर से शुरू किए बिना रनटाइम पर SSLContext में लोड किए गए प्रमाणपत्र और कीफाइल को अपडेट करने का कोई तरीका है?

1
Icode4food 9 मई 2017, 06:15

2 जवाब

सबसे बढ़िया उत्तर

मुझे पूरा यकीन है कि आपके द्वारा उपयोग किए जाने वाले संदर्भ की एक प्रति रखना और प्रमाणित श्रृंखला को पुनः लोड करने के लिए विधि को कॉल करना ठीक काम करेगा। कम से कम सी ओपनएसएल एपीआई स्तर पर ऐसा करना उचित है और ऐसा नहीं लगता कि पाइथन इसे तोड़ने के लिए कुछ भी करता है।

1
Sam Hartman 16 मई 2017, 06:18

जहां तक ​​​​मुझे पता है, सर्वर के लाइव होने पर एसएसएल प्रमाणपत्र को अपडेट करने के लिए asyncio.Server में कोई एपीआई नहीं है, आपके पास दो समाधान हैं:

एसएसएल हैंडशेक के दौरान प्रमाणपत्र को अपडेट करने के लिए आप एसएनआई कॉलबैक का उपयोग कर सकते हैं, लेकिन यह केवल एसएनआई का समर्थन करने वाले क्लाइंट के साथ काम करेगा। इसका मतलब यह है कि इस सुविधा का समर्थन करने वाले प्रत्येक क्लाइंट के लिए, आपकी पसंद का कॉलबैक कहा जाएगा और एक SSLContext ऑब्जेक्ट वापस कर सकता है जिसका उपयोग क्लाइंट के साथ कनेक्शन स्थापित करने के लिए किया जाएगा। आप यह कॉलबैक कर सकते हैं ताकि यह प्रत्येक कॉल पर प्रमाणपत्र/कुंजी फाइलों को पढ़ सके, या आपकी पसंद के ट्रिगर द्वारा आवश्यक होने पर पुनः लोड किया जा सके।

कॉलबैक सेटअप करने के लिए, देखें: https://docs.python .org/3/library/ssl.html#ssl.SSLContext.set_servername_callback

अन्य समाधान asyncio API की वर्तमान स्थिति के साथ सही होने के लिए अधिक जटिल है: यदि asyncio के आंतरिक कार्यान्वयन में परिवर्तन होता है, तो यह टूट सकता है, और मैंने यह नहीं देखा कि यह प्रोएक्टर लूप के साथ कैसे काम करेगा। हालांकि, यह किसी भी तरह के क्लाइंट के साथ काम करेगा।

आप नए संदर्भ के साथ एक नया सर्वर बना सकते हैं, लेकिन पहले सर्वर के सॉकेट का उपयोग कर सकते हैं:

# This will create a new server with the current socket, and setup what's required to use the new callback.
new_server = await asyncio.create_server(callback, None, None,
                   sock=old_server.sockets[0], ssl=new_context)

# Ensure that when cleaning the old_server, it doesn't try to close the socket we kept
old_server.sockets = []
old_server.close()
await old_server.wait_closed()

Create_server () के दौरान एक बिंदु पर, asyncio नए ssl संदर्भ के साथ नए कनेक्शन का जवाब देना शुरू कर देगा। ध्यान दें कि एक बार कनेक्शन शुरू हो जाने के बाद और आपके कॉलबैक (_accept_client) को पास कर दिया जाता है, यह व्यवहार में उस सर्वर से स्वतंत्र होता है जिसे इसे कहा जाता है, इसलिए यह किसी भी मौजूदा कनेक्शन को अछूता छोड़ देगा।

1
Martin Richard 9 मई 2017, 19:42