Alamat apakah yang dilaporkan Windows untuk sesi RDP?
API WTS mengembalikan alamat klien yang dilaporkan untuk satu sesi RDP, dan registri tidak. Tanya ID sesi yang betul dan nyahkod IPv4 atau IPv6 dengan betul.
Sesi RDP memerlukan alamat klien, dan sumber yang jelas tidak bersetuju. CLIENTNAME memberi nama komputer, registri menyimpan nilai daripada sesi lain, dan hujung soket mungkin alamat gateway atau NAT dan bukan klien. Windows memang mendedahkan alamat klien yang dilaporkan bagi setiap sesi, tetapi anda perlu bertanya sesi yang betul dan menyahkod balasan dengan betul.
Ikalkan carian pada satu sesi
Mulakan dengan sesi, bukan orang. Hos RDP Windows boleh membawa beberapa sesi untuk satu akaun, dan alamat yang dilihat sebelum sambungan semula mungkin tidak lagi sepadan dengan pautan aktif. Catat ID sesi, pengguna dan masa pemerhatian bersama-sama. ID sesi ialah kunci yang dijangka oleh API, dan nilai itulah yang menghalang dua sesi daripada dikelirukan.
Pada hos, alat sesi yang dipasang menyenaraikan apa yang wujud; gunakan paparan pentadbiran hanya apabila anda berhak ke atasnya. Sahkan ID yang dipilih sejurus sebelum pertanyaan, kerana ID yang dikitar semula mengembalikan data sesi lain.
qwinsta
Panggil WTSQuerySessionInformationW untuk ID itu
API Terminal Services menjawab soalan itu dengan kelas maklumat 14, WTSClientAddress. Pembalut ctypes kecil sudah memadai pada Windows, dan ia mengelakkan pembacaan hive pengguna lain. Kod di bawah mengambil ID sesi eksplisit dan bertanya kepada hos setempat.
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)
Hantarkan ID sesi integer yang baru anda sahkan, dan kekalkan pengendali pelayan null untuk mesin setempat. Layan panggilan yang gagal sebagai ralat dan bukan sebagai alamat yang tidak ada, kerana kedua-duanya membawa kepada kesimpulan berbeza. Pertanyaan tentang sesi pengguna lain memerlukan kebenaran Query Information yang sesuai, jadi jalankan alat itu di bawah akaun yang telah diberinya dan bukan menaikkan keistimewaan secara ad hoc. Penimbal yang dikembalikan milik API dan mesti dilepaskan walaupun penyahkodan gagal.
Nyahkod keluarga, kemudian lepaskan penimbal
Struktur itu bukan rentetan IP. Medan keluarganya menentukan cara dua puluh bait alamat dibaca: IPv4 bermula pada ofset dua, manakala IPv6 bermula pada ofset sifar. Alamat yang tidak ditentukan bermaksud klien tidak melaporkan satu pun, yang tidak sama dengan rentetan kosong. Sambungan Remote Desktop Gateway didokumenkan sebagai kes di mana alamat tidak tersedia, jadi sesi yang melalui gateway tidak melaporkan apa-apa berguna tentang alamat sebenar klien. Korelasi kemudiannya mesti berpindah ke rekod gateway itu sendiri.
Cetak keluarga di sebelah alamat semasa anda menyahpepijat, kerana ketidakpadanan antara keduanya ialah punca biasa nilai yang munasabah tetapi salah. Lepaskan penimbal dengan WTSFreeMemory dalam blok finally supaya pengecualian tidak membocorkannya.
Asingkan alamat yang dilaporkan daripada bukti
Alamat klien yang dilaporkan ialah kenyataan yang dibekalkan klien, bukan pemerhatian yang boleh dipercayai. Ia bukan rakan TCP, bukan jadual pajakan gateway VPN, dan bukan alamat awam klien. Apabila soalan sebenar ialah pajakan VPN mana milik seseorang, kaitkan rekod sesi yang disahkan pelayan VPN pada masa yang sama. Apabila soalannya ialah sumber mana yang sampai ke pendengar, baca jadual sambungan atau log sisi pelayan yang dibenarkan.
Simpan nilai-nilai ini berlabel berasingan dalam mana-mana alat sokongan. Hasil WTS yang hilang harus kekal hilang dan bukannya kembali kepada nilai registri sewenang-wenangnya daripada sesi lain. Log ID sesi di sebelah alamat, kerana pengguna yang sama boleh bersambung semula dan menerima nilai baharu. Nama klien mahupun alamat yang dilaporkan bukan bukti yang mencukupi untuk memberikan akses.