Home > database >  Citrix virtual loopback doesn't work with our .NET C# app
Citrix virtual loopback doesn't work with our .NET C# app

Time:06-03

Overview

Our company is about to distribute a C# .NET / WPF app to customers who use Citrix XenApp (or whatever it has been renamed to).   This app runs multiple times on one Citrix server, once for each user, as part of their Citrix session.   Each instance of the app must respond to browser JavaScript that is fetching from localhost:xxxx, with xxxx always being the same port number.

Citrix supplies something called Virtual Loopback for this, and also discusses Windows' Virtual IP for it.   For the moment we are trying Virtual Loopback.   Virtual Loopback basically allows a different "local host" for each session, in the form 127.0.0.1, 127.0.0.2, 127.0.0.3, and so on.   Citrix describes both at length here: https://docs.citrix.com/en-us/xenapp-and-xendesktop/7-15-ltsr/manage-deployment/virtual-ip-virtual-loopback.html.

And basically, it doesn't work for us with .NET.   In contrast, a colleague worked with the Citrix approach using a Python test app as an experiment, and that worked fine.

This is a two-part policy in Citrix (setting it up in general, and naming the apps that can use the redirection), and both were set up properly. This isn't a problem of the browser not finding the right address either; that would be set up with the Citrix policy, but the fail is occurring when our app starts and only the first instance can bind to the socket (naturally).

History and latest steps

In our code, using localhost as a literal resolves to 0:0:0:0, which isn't part of the 127.x.x.x series and so that fails.   That part makes sense to me now, basically.   However, when I tried using 127.0.0.1 in the code, thinking the settings might redirect transparently despite it being spelled out, that didn't work at all.

So now I am trying workarounds now that might help or not, such as using IPAddress.Loopback and ensuring that the IP address is IPv4 (which was found to make a difference for the similar Java problem years ago, seen in this StackOverflow Q/A: Java get REAL loopback address programmatically).

BTW, the local port can't just be changed programmatically for each instance because the REST call is used to get the session's specific app instance, and so if ports were varied, the JavaScript would have to know the right one in advance, defeating the purpose.

Speculations

My colleague speculates that the problem is that the app we created runs as System, but as far as I can tell, that is a byproduct of using the .NET web stack, since the test app is actually running under my user name.   It's also apparently impossible to change, since it's a byproduct.   Perhaps I've missed something there though?

Has anyone seen this problem, and what was the answer you found for it?

CodePudding user response:

Sigh, I end up answering my own question.   But for the future person who finds this problem in their work...

One of the two Citrix virtual loopback policies required needs a list of names of apps that will get the redirected addresses, each on their own lines, for example

SomeApp.exe
OtherApp.exe

and those must match exactly to the names of the processes that are using TCP/IP.

However, when you use handy types like HttpListener in C#, you're actually using Windows' built-in HTTP.sys subsystem (the same one IIS uses, apparently), and that sub-system is in kernel mode, so it always runs as System.   And there's no way to add either System or HTTP.sys to that Citrix list.

So in order to make Citrix and your own .NET HTTP listening play nicely with each other, you can't use HttpListener or similar objects (which I suspect includes similar things like TcpListener).   Instead, you have to either roll your own HTTP using Socket in System.Net.Sockets, which doesn't involve HTTP.sys at all, or else use a NuGet package that doesn't make use of HTTP.sys as a dependency.

For most purposes, using a NuGet package is definitely better.   In my case, I'm rolling my own, at least for the moment, because the listening approach that I inherited from others responds to only one request and only with one thing.

Finding an answer to this problem has been impossible in a single search in Google till now.   However, there are lots of references on the web for individual pieces of the puzzle.

To put it all together:   Use the two Citrix policies for virtual loopback, and don't use HttpListener or anything else in .NET that ends up utilizing HTTP.sys internally.   You can tell if something in .NET or from NuGet does use that by looking in Microsoft's TCPView (or other tooling) and seeing if your chosen port comes up with System as its process (even if your app shows up in Task Manager under your user name).

And finally, whatever app is calling your .NET app must also be in that Citrix list, for instance

chrome.exe

.

I hope this helps someone else someday!

  • Related