Reputation: 549
I'm writing a function in C# using Azure Functions and need to get the ip address of the client that called the function, is this possible?
Upvotes: 25
Views: 22869
Reputation: 1
In a .NET 8 isolated worker Azure Function, you can find the client IP in a header called "CLIENT-IP". I logged all the headers to App Insights for each request, and this contained the correct values with the port number.
[Function(nameof(HttpFunction))]
public IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req, FunctionContext context, CancellationToken ct)
{
_logger.LogInformation("C# HTTP trigger function received a request.");
var clientIp = req.Headers["CLIENT-IP"];
if (!string.IsNullOrEmpty(clientIp)) _logger.LogInformation($"Client IP: {clientIp}");
return new OkObjectResult("");
}
Upvotes: 0
Reputation: 6933
Here is an extension method based on what I am seeing in
public static IPAddress GetClientIpn(this HttpRequest request)
{
IPAddress result = null;
if (request.Headers.TryGetValue("X-Forwarded-For", out StringValues values))
{
var ipn = values.FirstOrDefault().Split(new char[] { ',' }).FirstOrDefault().Split(new char[] { ':' }).FirstOrDefault();
IPAddress.TryParse(ipn, out result);
}
if (result == null)
{
result = request.HttpContext.Connection.RemoteIpAddress;
}
return result;
}
public static IPAddress GetClientIpn(this HttpRequestMessage request)
{
IPAddress result = null;
if (request.Headers.TryGetValues("X-Forwarded-For", out IEnumerable<string> values))
{
var ipn = values.FirstOrDefault().Split(new char[] { ',' }).FirstOrDefault().Split(new char[] { ':' }).FirstOrDefault();
IPAddress.TryParse(ipn, out result);
}
return result;
}
Upvotes: 8
Reputation: 147
In a .NET 6.0 function, within the Run()
function of the operation, this can be accessed of the HttpRequest req
object:
public static class PingOperation
{
[FunctionName("ping")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
log.LogInformation($"PingOperation requested from: {req.HttpContext.Connection.RemoteIpAddress}:{req.HttpContext.Connection.RemotePort}");
string responseMessage = "This HTTP triggered function executed successfully.";
return new OkObjectResult(responseMessage);
}
}
Upvotes: -2
Reputation: 514
As mentioned already by others, the old method of looking at MS_HttpContext
no longer works. Further, while the method of looking at the headers for X-Forwarded-For
does work, it only works after being published in Azure - it doesn't return a value when you're running locally. That may matter if you prefer testing locally to minimize any potential cost-impact, but still want to be able to see that everything works correctly.
To see the IP address even when running locally, try this instead:
using Microsoft.AspNetCore.Http;
And then:
String RemoteIP = ((DefaultHttpContext)req.Properties["HttpContext"])?.Connection?.RemoteIpAddress?.ToString();
This is working for me currently in Azure Functions V3.0.
Upvotes: 2
Reputation: 51
Update 18-Oct-2019:
The solution I tried is much easier and quicker and is mentioned below stepwise. But some more lengthy/tricky alternates are available @ https://learn.microsoft.com/en-us/azure/azure-monitor/app/ip-collection:
Upvotes: 5
Reputation: 81
Now that Azure functions get an HttpRequest parameter, and they're behind a load balancer, this function to get the IP address works for me:
private static string GetIpFromRequestHeaders(HttpRequest request)
{
return (request.Headers["X-Forwarded-For"].FirstOrDefault() ?? "").Split(new char[] { ':' }).FirstOrDefault();
}
Upvotes: 5
Reputation: 269
you should use these function Get the IP address of the remote host
request.Properties["MS_HttpContext"] is not available if you debug precompiled functions local request.Properties[RemoteEndpointMessageProperty.Name] is not available on azure
private string GetClientIp(HttpRequestMessage request)
{
if (request.Properties.ContainsKey("MS_HttpContext"))
{
return ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
}
if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
{
RemoteEndpointMessageProperty prop;
prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
return prop.Address;
}
return null;
}
Update 21.08.2018: Now Azure Functions are behind a LoadBalancer --> we have to inspect Request-Headers to determine the correct Client IP
private static string GetIpFromRequestHeaders(HttpRequestMessage request)
{
IEnumerable<string> values;
if (request.Headers.TryGetValues("X-Forwarded-For", out values))
{
return values.FirstOrDefault().Split(new char[] { ',' }).FirstOrDefault().Split(new char[] { ':' }).FirstOrDefault();
}
return "";
}
Upvotes: 18
Reputation: 43203
Here is an answer based on the one here.
#r "System.Web"
using System.Net;
using System.Web;
public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
{
string clientIP = ((HttpContextWrapper)req.Properties["MS_HttpContext"]).Request.UserHostAddress;
return req.CreateResponse(HttpStatusCode.OK, $"The client IP is {clientIP}");
}
Upvotes: 19