Windows একটি RDP সেশনের জন্য কোন ঠিকানা রিপোর্ট করে?
WTS API একটি RDP সেশনের জন্য রিপোর্ট করা ক্লায়েন্ট ঠিকানা ফেরত দেয়, রেজিস্ট্রি দেয় না। সঠিক সেশন ID জিজ্ঞাসা করুন এবং IPv4 বা IPv6 সঠিকভাবে ডিকোড করুন।
একটি 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 লগ করুন, কারণ একই ব্যবহারকারী আবার সংযোগ করে নতুন মান পেতে পারেন। ক্লায়েন্টের নাম বা রিপোর্ট করা ঠিকানা—কোনোটিই অ্যাক্সেস দেওয়ার জন্য যথেষ্ট প্রমাণ নয়।