Ի՞նչ հասցե է հայտնում Windows-ը RDP նստաշրջանի համար
WTS API-ն վերադարձնում է հայտնված հաճախորդի հասցեն մեկ RDP նստաշրջանի համար, իսկ ռեեստրը՝ ոչ։ Հարցրեք ճիշտ նստաշրջանի ID-ն և ճիշտ վերծանեք IPv4-ը կամ IPv6-ը։
RDP նստաշրջանին հաճախորդի հասցե է պետք, և ակնհայտ աղբյուրները համաձայն չեն։ CLIENTNAME-ը տալիս է համակարգչի անուն, ռեեստրը պահում է այլ նստաշրջանների արժեքներ, և սոքեթի հակառակ կողմը կարող է լինել դարպասի կամ NAT-ի հասցե, այլ ոչ թե հաճախորդը։ Windows-ը իրոք տրամադրում է հայտնված հաճախորդի հասցե յուրաքանչյուր նստաշրջանի համար, բայց պետք է հարցնել ճիշտ նստաշրջանը և ճիշտ վերծանել պատասխանը։
Ամրացրեք որոնումը մեկ նստաշրջանին
Սկսեք նստաշրջանից, ոչ թե մարդուց։ Windows RDP հոսթը կարող է կրել մի քանի նստաշրջան մեկ հաշվի համար, և վերամիացումից առաջ տեսած հասցեն կարող է այլևս չհամապատասխանել կենդանի կապին։ Գրանցեք նստաշրջանի ID-ն, օգտատերը և դիտարկման ժամանակը միասին։ Նստաշրջանի ID-ն այն բանալին է, որ սպասում է API-ն, և հենց այդ արժեքն է, որ թույլ չի տալիս շփոթել երկու նստաշրջան։
Հոսթի վրա տեղադրված նստաշրջանի գործիքները թվարկում են, թե ինչ կա. օգտվեք վարչական տեսքից միայն այն ժամանակ, երբ իրավունք ունեք դրան։ Հաստատեք ընտրված ID-ն անմիջապես հարցումից առաջ, որովհետև վերամշակված ID-ն վերադարձնում է այլ նստաշրջանի տվյալներ։
qwinsta
Կանչեք WTSQuerySessionInformationW-ն այդ ID-ի համար
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 թույլտվություն, այնպես որ գործիքը գործարկեք այն հաշվով, որին այն տրվել է, այլ ոչ թե ad hoc բարձրացնեք արտոնությունները։ Վերադարձված բուֆերը պատկանում է API-ին և պետք է ազատվի նույնիսկ երբ վերծանումը ձախողվում է։
Վերծանեք ընտանիքը, ապա ազատեք բուֆերը
Կառուցվածքը IP տող չէ։ Նրա ընտանիք դաշտը որոշում է, թե ինչպես կարդալ հասցեի քսան բայթը. IPv4-ը սկսվում է երկու շեղումից, իսկ IPv6-ը՝ զրո շեղումից։ Չսահմանված հասցեն նշանակում է, որ հաճախորդը ոչ մեկը չի հայտնել, ինչը նույնը չէ, ինչ դատարկ տողը։ Remote Desktop Gateway-ի միացումները փաստաթղթավորված են որպես դեպք, երբ հասցեն հասանելի չէ, ուստի դարպասով անցնող նստաշրջանը ոչ մի օգտակար բան չի հայտնում հաճախորդի իրական հասցեի մասին։ Այնուհետև հարաբերակցությունը պետք է տեղափոխվի հենց դարպասի գրառումներին։
Վրիպազերծման ընթացքում տպեք ընտանիքը հասցեի կողքին, որովհետև երկուսի միջև անհամապատասխանությունը հավանական, բայց սխալ արժեքի սովորական պատճառն է։ Ազատեք բուֆերը WTSFreeMemory-ով finally բլոկում, որպեսզի բացառությունը այն չհոսեցնի։
Առանձնացրեք հայտնված հասցեն ապացույցից
Հայտնված հաճախորդի հասցեն հաճախորդի տրամադրած հայտարարություն է, ոչ թե վստահելի դիտարկում։ Այն TCP-ի հակառակ կողմը չէ, VPN դարպասի վարձակալության աղյուսակը չէ և հաճախորդի հանրային հասցեն չէ։ Երբ իրական հարցն այն է, թե որ VPN վարձակալությունն է պատկանում մարդուն, միաժամանակ համադրեք VPN սերվերի նույնականացված նստաշրջանի գրառումը։ Երբ հարցն այն է, թե որ աղբյուրն է հասել լսողին, կարդացեք միացումների աղյուսակը կամ թույլատրված սերվերային մատյանները։
Պահեք այս արժեքները առանձին պիտակավորված ցանկացած աջակցության գործիքում։ Բացակայող WTS արդյունքը պետք է մնա բացակայող, այլ ոչ թե վերադառնա այլ նստաշրջանի կամայական ռեեստրի արժեքի։ Գրանցեք նստաշրջանի ID-ն հասցեի կողքին, որովհետև նույն օգտատերը կարող է նորից միանալ և նոր արժեք ստանալ։ Ոչ հաճախորդի անունը, ոչ հայտնված հասցեն բավարար ապացույց չեն մուտք տրամադրելու համար։