एक RDP सत्र को क्लाइंट पता चाहिए, और स्पष्ट स्रोत सहमत नहीं हैं। CLIENTNAME कंप्यूटर का नाम देता है, रजिस्ट्री दूसरे सत्रों के मान रखती है, और सॉकेट का सामने वाला सिरा क्लाइंट के बजाय गेटवे या NAT पता हो सकता है। Windows हर सत्र के लिए रिपोर्ट किया गया क्लाइंट पता देता है, पर आपको सही सत्र पूछना होगा और जवाब ठीक से डिकोड करना होगा।

खोज को एक ही सत्र पर टिकाएँ

व्यक्ति से नहीं, सत्र से शुरू करें। एक Windows RDP होस्ट एक खाते के लिए कई सत्र रख सकता है, और फिर से जुड़ने से पहले देखा गया पता अब जीवंत लिंक से मेल नहीं खा सकता। सत्र ID, उपयोगकर्ता और अवलोकन का समय साथ लिखें। सत्र ID वही कुंजी है जिसकी API अपेक्षा करता है, और यही वह मान है जो दो सत्रों को उलझने से रोकता है।

होस्ट पर, स्थापित सत्र उपकरण बताते हैं कि क्या मौजूद है; प्रशासनिक दृश्य का उपयोग केवल तब करें जब आप उसके हकदार हों। पूछताछ से ठीक पहले चुने गए ID की पुष्टि करें, क्योंकि पुनः उपयोग किया गया ID दूसरे सत्र का डेटा लौटाता है।

qwinsta

उस ID के लिए WTSQuerySessionInformationW कॉल करें

Terminal Services API सूचना वर्ग 14 के साथ प्रश्न का उत्तर देता है, WTSClientAddress। Windows पर एक छोटा ctypes आवरण पर्याप्त है, और यह किसी दूसरे उपयोगकर्ता की hive पढ़ने से बचाता है। नीचे दिया कोड स्पष्ट सत्र ID लेता है और स्थानीय होस्ट से पूछता है।

import ctypes
import ipaddress
import socket
from ctypes import wintypes

class WTS_CLIENT_ADDRESS(ctypes.Structure):
    _fields_ = [("AddressFamily", wintypes.DWORD),
                ("Address", ctypes.c_ubyte * 20)]

wts = ctypes.WinDLL("Wtsapi32", use_last_error=True)
query = wts.WTSQuerySessionInformationW
query.argtypes = [wintypes.HANDLE, wintypes.DWORD, ctypes.c_int,
                  ctypes.POINTER(ctypes.c_void_p), ctypes.POINTER(wintypes.DWORD)]
query.restype = wintypes.BOOL
free = wts.WTSFreeMemory
free.argtypes = [ctypes.c_void_p]

def client_address(session_id):
    buf = ctypes.c_void_p()
    size = wintypes.DWORD()
    if not query(None, session_id, 14, ctypes.byref(buf), ctypes.byref(size)):
        raise ctypes.WinError(ctypes.get_last_error())
    try:
        if size.value < ctypes.sizeof(WTS_CLIENT_ADDRESS):
            raise RuntimeError("short WTS buffer")
        value = ctypes.cast(buf, ctypes.POINTER(WTS_CLIENT_ADDRESS)).contents
        raw = bytes(value.Address)
        if value.AddressFamily == socket.AF_INET:
            addr = ipaddress.ip_address(raw[2:6])
        elif value.AddressFamily == socket.AF_INET6:
            addr = ipaddress.ip_address(raw[:16])
        else:
            return None
        return None if addr.is_unspecified else str(addr)
    finally:
        free(buf)

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

परिवार को डिकोड करें, फिर बफर मुक्त करें

यह संरचना IP स्ट्रिंग नहीं है। इसका परिवार क्षेत्र तय करता है कि बीस पता बाइट कैसे पढ़े जाएँ: IPv4 दो ऑफ़सेट से शुरू होता है, जबकि IPv6 शून्य ऑफ़सेट से शुरू होता है। अनिर्दिष्ट पता का अर्थ है कि क्लाइंट ने कोई पता नहीं बताया, जो खाली स्ट्रिंग के समान नहीं है। Remote Desktop Gateway कनेक्शन ऐसे मामले के रूप में प्रलेखित हैं जहाँ पता उपलब्ध नहीं है, इसलिए गेटवे से गुजरने वाला सत्र क्लाइंट के वास्तविक पते के बारे में कुछ उपयोगी नहीं बताता। तब सहसंबंध गेटवे के अपने अभिलेखों की ओर जाना चाहिए।

डिबग करते समय परिवार को पते के बगल में छापें, क्योंकि दोनों के बीच असंगति ही विश्वसनीय पर गलत मान का सामान्य कारण है। बफर को finally ब्लॉक में WTSFreeMemory से मुक्त करें ताकि अपवाद उसे लीक न करे।

रिपोर्ट किए गए पते को प्रमाण से अलग करें

रिपोर्ट किया गया क्लाइंट पता क्लाइंट द्वारा दिया गया कथन है, भरोसेमंद अवलोकन नहीं। यह TCP का सामने वाला सिरा नहीं है, VPN गेटवे की लीज़ तालिका नहीं है, और क्लाइंट का सार्वजनिक पता भी नहीं है। जब असली प्रश्न यह हो कि कौन-सी VPN लीज़ किसी व्यक्ति की है, तब उसी समय VPN सर्वर के प्रमाणित सत्र अभिलेख को सहसंबद्ध करें। जब प्रश्न यह हो कि कौन-सा स्रोत श्रोता तक पहुँचा, तब कनेक्शन तालिका या अनुमत सर्वर-पक्ष लॉग पढ़ें।

किसी भी सहायता उपकरण में इन मानों को अलग-अलग लेबल के साथ रखें। छूटा हुआ WTS परिणाम छूटा ही रहना चाहिए, दूसरे सत्र के मनमाने रजिस्ट्री मान पर लौटने के बजाय। पते के बगल में सत्र ID लॉग करें, क्योंकि वही उपयोगकर्ता फिर से जुड़कर नया मान पा सकता है। न क्लाइंट का नाम और न रिपोर्ट किया गया पता—कोई भी पहुँच देने के लिए पर्याप्त प्रमाण नहीं है।

संबंधित लेख