0

We are trying to write a C++ DLL that would run on VMWare server and would return the client (terminal user) IP Address and name.

I am using WTSQuerySessionInformation to fetch the IP Address. The problem is when I am running from within the company's network, the DLL returns the exact IP Address which maps to an appropriate HostName.

But when I login from home to the company's VPN and try the same, it gives me a different IP which doesn't have any DNS Name.

LPTSTR ppBuffer = NULL;
DWORD  pBytesReturned = 0;
PWTS_CLIENT_ADDRESS pWTSCA = NULL;

WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSClientAddress, &ppBuffer, &pBytesReturned);

pWTSCA = (PWTS_CLIENT_ADDRESS)ppBuffer;

String^ addrStr = String::Empty;
for (int i = 2; i < 6; i++)
{
    addrStr += Convert::ToString(pWTSCA->Address[i]);
    if (i != 5)
        addrStr += ".";
}

Is there a way to work around this problem? Am I following the right approach, or there is a different way of doing this?

Edit: If I use WTSClientName, it return the IP address separate by hyphen (like W-X-Y-Z). Could you please help me understand if I have done anything wrong here? Here is the code:

LPTSTR szClientName = NULL;
DWORD dwSize = 0;
String^ cliName = String::Empty;

if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, TSClientName, &szClientName, &dwSize))
{
    cliName = gcnew String(szClientName, 0, dwSize);
}

return cliName;
VkG
  • 1
  • 2
  • More importantly, note the following from the [`WTS_CLIENT_ADDRESS`](https://msdn.microsoft.com/en-us/library/aa383857.aspx) documentation: "***The client network address is reported by the RDP client itself when it connects to the server. This could be different than the address that actually connected to the server**. For example, suppose there is a NAT between the client and the server. The client can report its own IP address, but the IP address that actually connects to the server is the NAT address...*" – Remy Lebeau Apr 24 '18 at 02:05
  • *"... **For VPN connections, the IP address might not be discoverable by the client**. If it cannot be discovered, the client can report the only IP address it has, which may be the ISP assigned address. Because the address may not be the actual network address, it should not be used as a form of client authentication.*" – Remy Lebeau Apr 24 '18 at 02:05
  • BTW, you need to check the `pWTSCA->AddressFamily` before interpreting the content of `pWTSCA->Address`. The code you showed would only work if `AddressFamily` were `AF_INET` (IPv4). You are not accounting for `AF_INET6` (IPv6) or any other address family that may come across. – Remy Lebeau Apr 24 '18 at 02:13
  • You're right about AddressFamily. I only added the essential code here. – VkG Apr 24 '18 at 02:20
  • So, there is no way I can ever get the true IP Address of the client if the user logs in from outside network through VPN? – VkG Apr 24 '18 at 02:21
  • That depends on whether the client is able to determine its own VPN IP address when connecting to the TS server so it can report that as its `WTSClientAddress` value. If not, then on Win7+ and WinServer 2010+, you might try querying `WTSSessionAddressV4` instead of `WTSClientAddress`. If that still doesn't work, then no, you probably won't be able to get the client's IP address. – Remy Lebeau Apr 24 '18 at 02:29
  • When I am on VPN and I do ipconfig, the result shows me the VPN IP UNDER LAN address & the actual IP under the Wan address. When I use client address, does WTSQuerySessionInformation fill the WTS_CLIENT_ADDRESS structure with both the addresses or just the VPN IP address? – VkG Apr 24 '18 at 12:24
  • `WTS_CLIENT_ADDRESS` only has room for 1 IP address. Whichever one the client reports when it connects to the server. – Remy Lebeau Apr 24 '18 at 15:21
  • Thanks Remy. In that case, WTSQuerySessionInformation doesn't seem to solve the purpose. Is there a way I can find the ClientName? When I use WTSClientName, it again returns the IP with hyphens (e.g. W-X-Y-Z) instead of the Client Name. – VkG Apr 24 '18 at 19:50
  • There is an undocumented `WinStationQueryInformationW` function in winsta.dll that allows you to pull the remote endpoint (IP & port) of the RDP connection from the server's perspective. However, I don't think this (or anything else) will work for clients on a VPN because of the way that VPNs work - only the VPN server knows what the actual public IP of the client is. It's possible that if your VPN server has an API, you could query that to get the public IP for a particular client, but you'd need to provide additional details of your setup for that. – Dan Ports Apr 27 '18 at 15:48

0 Answers0