Seja RDP potrebuje naslov odjemalca, očitni viri pa se ne strinjajo. CLIENTNAME da ime računalnika, register hrani vrednosti iz drugih sej, nasprotni konec vtičnice pa je lahko naslov prehoda ali NAT, ne pa odjemalec. Windows res razkrije sporočeni naslov odjemalca za vsako sejo, vendar morate vprašati za pravo sejo in odgovor pravilno dekodirati.

Zasidrajte iskanje v eno sejo

Začnite s sejo, ne z osebo. Gostitelj RDP v sistemu Windows lahko nosi več sej za en račun, naslov, viden pred ponovno povezavo, pa morda ne ustreza več aktivni povezavi. Zapišite ID seje, uporabnika in čas opazovanja skupaj. ID seje je ključ, ki ga API pričakuje, in prav ta vrednost preprečuje zamenjavo dveh sej.

Na gostitelju nameščena orodja za seje naštejejo, kaj obstaja; uporabniški pogled uporabljajte le, kadar imate zanj pravico. Potrdite izbrani ID tik pred poizvedbo, ker recikliran ID vrne podatke druge seje.

qwinsta

Pokličite WTSQuerySessionInformationW za ta ID

API storitev Terminal odgovori na vprašanje z informacijskim razredom 14, WTSClientAddress. Majhen ovoj ctypes na Windowsu zadostuje in se izogne branju hive drugega uporabnika. Spodnja koda sprejme eksplicitni ID seje in vpraša lokalnega gostitelja.

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)

Posredujte celoštevilski ID seje, ki ste ga pravkar preverili, in obdržite ničelni ročaj strežnika za lokalni stroj. Neuspešen klic obravnavajte kot napako in ne kot manjkajoč naslov, ker oba vodita do različnih sklepov. Poizvedba o seji drugega uporabnika zahteva ustrezno dovoljenje Query Information, zato orodje zaženite pod računom, ki ga je prejel, namesto da ad hoc dvigujete pravice. Vrnjeni medpomnilnik pripada API-ju in ga je treba sprostiti tudi, ko dekodiranje ne uspe.

Dekodirajte družino in nato sprostite medpomnilnik

Struktura ni niz IP. Njeno polje družine odloča, kako se bere dvajset bajtov naslova: IPv4 se začne pri odmiku dva, IPv6 pa pri odmiku nič. Nedoločen naslov pomeni, da ga odjemalec ni sporočil, kar ni isto kot prazen niz. Povezave prek Remote Desktop Gateway so dokumentirane kot primer, ko naslov ni na voljo, zato seja prek prehoda ne poroča nič koristnega o resničnem naslovu odjemalca. Korelacija se mora nato preseliti v lastne evidence prehoda.

Med razhroščevanjem izpišite družino ob naslovu, ker je neskladje med obema običajen vzrok verjetne, a napačne vrednosti. Sprostite medpomnilnik z WTSFreeMemory v bloku finally, da ga izjema ne izpušča.

Ločite sporočeni naslov od dokaza

Sporočeni naslov odjemalca je izjava, ki jo zagotovi odjemalec, ne pa zanesljivo opazovanje. Ni nasprotni konec TCP, ni tabela najema prehoda VPN in ni javni naslov odjemalca. Ko je resnično vprašanje, kateri najem VPN pripada osebi, hkrati korelirajte overjeni zapis seje strežnika VPN. Ko je vprašanje, kateri vir je dosegel poslušalca, berite tabelo povezav ali dovoljene dnevnike na strani strežnika.

Te vrednosti hranite ločeno označene v vsakem orodju za podporo. Manjkajoč rezultat WTS mora ostati manjkajoč, namesto da bi se zatekel k poljubni vrednosti registra iz druge seje. Beležite ID seje ob naslovu, ker se isti uporabnik lahko znova poveže in prejme novo vrednost. Niti ime odjemalca niti sporočeni naslov nista zadosten dokaz za odobritev dostopa.

Sorodni članki