How to get remote client IP address under SignalR

Take ASP.NET Core 3.1 as an example

LAI TOCA
C# Programming

--

Photo from: https://wateroxconsulting.com/archives/whitelist/

In some scenarios, we would like to create a white list to allow the specific end-user to access the diverse resource(s) under SignalR. So if we could retrieving request information something like IP address, user identity…that we might apply some access controlling logic during data transmission among SignralR server and client(s).

For capturing the client remote address, we could just simply add the below code under EventHub.cs:

using Microsoft.AspNetCore.Http.Features;public class EventHub : Hub<IEventHub> {
public override Task OnConnectedAsync () {
var feature = Context.Features.Get<IHttpConnectionFeature>(); // here you could get your client remote address
var remoteAddress = feature.RemoteIpAddress;
return base.OnConnectedAsync ();
}
}

Please note that the RemoteIpAddress might not reflect the actual(real) client address if your SignalR server was under proxy (for instance nginx server)

IHttpConnectionFeature

So how to do that we could get the real end user’s IP address?

We have two approaches to deal with the case:

One solution was to register the global middleware and acting with correspond control as your wish. Sample code is below:

// Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// register middleware here for sniffer any request in
app.Use(async (context, next) =>
{
// get relative client info from headers
var host = context.Request.Headers["Host"];
var userAgent = context.Request.Headers["User-Agent"];
var realIP = context.Request.Headers["X-Real-IP"];
var forwardeds = context.Request.Headers["X-Forwarded-For"];
var connectedInfo = new Dictionary<string, string>()
{
{"Host", host},
{"UserAgent", userAgent},
{"Real-IP", realIP},
{"Forward-For", forwardeds},
};
Console.WriteLine($"Middleware sniffer: {JsonConvert.SerializeObject(connectedInfo)}");
// for example just passing through,
// you could handle your controlling logic here
await next.Invoke();

});
}

The other solution was more instruction, override the method: OnConnectedAsync on the IEventHub, sample code as below:

// EventHub.cs
public class EventHub : Hub<IEventHub> {
public override Task OnConnectedAsync () {
// get relative client info from headers
var host = Context.GetHttpContext ().Request.Headers["Host"];
var userAgent = Context.GetHttpContext ().Request.Headers["User-Agent"];
var realIP = Context.GetHttpContext ().Request.Headers["X-Real-IP"];
var forwardeds = Context.GetHttpContext ().Request.Headers["X-Forwarded-For"];
var connectedInfo = new Dictionary<string, string> () { { "Host", host }, { "UserAgent", userAgent }, { "Real-IP", realIP }, { "Forward-For", forwardeds },
};
Console.WriteLine($"Info: {JsonConvert.SerializeObject(connectedInfo)}");

// for example just passing through,
// you could handle your controlling logic here
return base.OnConnectedAsync ();
}
}

Finally, please remember to configure your proxy server to passing/forward through the client-side IP address or you will unable to capture the real client’s information behind the proxy.

Reference

--

--

LAI TOCA
C# Programming

Coding for fun. (Either you are running for food or running for being food.)