ApplicationInsights-dotnet icon indicating copy to clipboard operation
ApplicationInsights-dotnet copied to clipboard

How to specify Proxy Settings

Open epignosisx opened this issue 7 years ago • 48 comments

We were trying out Application Insights at work and we are not getting any telemetry in the Azure portal other than Page Views. We are pretty sure it is related to our Corporate proxy (it has caused us high levels of pain in the past).

How can I specify the proxy settings? The default proxy will not cut it for us. We have to specify url, port, username and password for our proxy.

For our .NET Core we have to set it to the HttpClientHandler like this:

var httpClientHandler = new HttpClientHandler {
    Proxy = new MyProxy(), //our implementation of IWebProxy
};

I couldn't find the code in this repo in charge of sending the telemetry but if you are using HttpClient then it would be something similar.

Note that we are planning to use Application Insights in house, not in Azure, so we have the proxy restriction in all our environments.

epignosisx avatar May 11 '17 19:05 epignosisx

Transmission is handled by the base SDK. Which specific class depends on whether you are using the InMemoryChannel or the ServerTelemetryChannel.

dnduffy avatar May 11 '17 22:05 dnduffy

Thanks for pointing me in the right direction. I'm using the ServerTelemetryChannel. Looks like the issue is in this line.

Ideally, I would like to be able to provide Application Insights with an HttpClient to use or at least be able to participate in the creation of the HttpClient so I can set the Proxy of the HttpClientHandler.

Should I move this issue to the ApplicationInsights-dotnet repo?

epignosisx avatar May 12 '17 15:05 epignosisx

@epignosisx Yes, please feel free to move it there, and if you want to submit a pull request that would be awesome!

dnduffy avatar May 12 '17 15:05 dnduffy

@dnduffy | @epignosisx

What is the status of this issue? Is there a new code that can handle proxy configurations? We are also governed by a proxy, though we use .NET 4.5 and then it seems like CreateRequest (https://github.com/Microsoft/ApplicationInsights-dotnet/blob/develop/src/Core/Managed/Shared/Channel/Transmission.cs#L374) is used today.

If no one had the opportunity to do something, can/should I make the changes and add a pull request?

In order to simplify, there should be something like:

if (this.UseProxy)
{
    request.Proxy = new WebProxy (this.ProxyAddress, this.ProxyBypassOnLocal);
}

crippe avatar Jun 05 '17 14:06 crippe

@crippe Are you able to get the channel from dependency injection and modify it? If not then please feel free to submit a pull request in that repo and we'll plan to take it in the next version.

dnduffy avatar Jun 05 '17 15:06 dnduffy

Hi @dnduffy, any update on this issue? Is not it still possible to handle proxy configuration? We are governed by a proxy too. We are using the ServerTelemetryChannel.

caretro avatar Jul 30 '18 10:07 caretro

Shortly after my comment, it was decided centrally to use technology other than Application Insights. I'm sorry for the decision, but I could not do anything about it. Therefore, I did not make a request.

crippe avatar Aug 03 '18 15:08 crippe

Hi, any update on this issue. Seems that the milestone is moved forward continuously...

caretro avatar Mar 11 '19 08:03 caretro

Since HttpClient uses system proxy, I think it's possible to use a tool like cntlm to store the proxy credentials and configure a system proxy without a username/password.

tremblaysimon avatar Mar 11 '19 14:03 tremblaysimon

Any update on this issue, or an alternative example to use AI with a proxy on-prem?

wernerb90 avatar May 07 '19 20:05 wernerb90

@wernerbarnard If you are configuring a system wide proxy, then SDK would just pick it up. If you'd like to configure proxy settings to applicationinsights channel - that is not supported today. I'll tag this as an enhancement.

cijothomas avatar May 13 '19 15:05 cijothomas

I too am hitting this issue using AI on .Net Core behind proxy. Im not convinced that HttpClient in .NET Core does use the system proxy either so need to be able to set the proxy explicitly on AI to resolve.

davebally avatar May 17 '19 09:05 davebally

@davebally Please run the following in a .NET Core Console app, and check if it respects system proxy. If it does, then it'll print the AppId for the given ikey.

class Program
    {
        static void Main(string[] args)
        {
            HttpClient client = new HttpClient();
            var res = client.GetStringAsync("https://dc.services.visualstudio.com/api/profiles/your_instrumentationkey/appId").Result;
            Console.WriteLine(res);
        }       
    }

cijothomas avatar May 17 '19 17:05 cijothomas

@cijothomas Thanks, i retract that statement. Looks like all is well, i can see the call coming through in fiddler without an explicit proxy being set.

davebally avatar May 20 '19 14:05 davebally

@cijothomas Unfortunately, this doesn't seem to work in all cases.

Running this code in our corporate environment raises a 407 error.

image

In our case, to make this pass, we have to define a HttpHandler, value the Proxy and UseProxy properties, and build the HttpClient from it. From a dev environment standpoint, that relies on running a local cntlm proxy, and configuring the Proxy property so that it points to it.

Teaching AppInsights to accept a HttpHandler would be very helpful for us.

nulltoken avatar May 21 '19 03:05 nulltoken

@nulltoken Yes we are tracking this as an enhancement - to modify to accept httpclient settings.

cijothomas avatar May 21 '19 03:05 cijothomas

@cijothomas Can you confirm that the HttpClient that is returned by default from IHttpClientFactory should be using the proxy ? When i set the proxy with the below code i see the call come through in fiddler, if i dont , i dont

Thanks.

in startup ....

 services.AddHttpClient("external", c => { c.DefaultRequestHeaders.CacheControl = GetCacheControlHeader(); })
                .ConfigureHttpMessageHandlerBuilder(c => c.PrimaryHandler = GetHttpClientHandler(true));

  private static HttpClientHandler GetHttpClientHandler(bool isExternal = false)
        {
            var handler = new HttpClientHandler
            {
                AutomaticDecompression = System.Net.DecompressionMethods.GZip,
                SslProtocols = SslProtocols.Tls12,
                ClientCertificateOptions = ClientCertificateOption.Manual
            };

            if (isExternal)
            {

                var proxy = GetConfigProperty("Config", "Proxy", "Uri");
                if (!string.IsNullOrEmpty(proxy.Value))
                {
                    handler.Proxy = new WebProxy()
                    {
                        Address = new Uri(proxy.Value)
                    };
                }
            }
            else { 

                handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
            }
            return handler;
        }

davebally avatar May 22 '19 11:05 davebally

@davebally Sorry, i dont have any expertise in that area :( Its best to ask this in HttpClient github repo.

cijothomas avatar May 23 '19 21:05 cijothomas

@davebally - for me running inside docker with HTTP_PROXY and HTTPS_PROXY set as env variables, new HttpClient did NOT respect the proxy (default settings - not using your sample), but a HttpClient created from IHttpClientFactory did.

wernerb90 avatar May 29 '19 12:05 wernerb90

This is not planned for the next release 2.8.

cijothomas avatar May 31 '19 17:05 cijothomas

Is it planned at all? Having exactly the same problem here...

ArchonMegalon avatar Jun 05 '19 12:06 ArchonMegalon

It is, and tagged with Future milestone. This means its not likely to land in next 2 stable releases. Please upvote the issues here so we promote items from Future to nearer milestones.

cijothomas avatar Jun 05 '19 14:06 cijothomas

The following worked for us. Run it in the StartUp of your application:

private static void ConfigureProxyForApplicationInsightsHack(IWebProxy proxy)
{
    System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Transmission).TypeHandle);
    var field = typeof(Transmission).GetField("client", BindingFlags.Static | BindingFlags.NonPublic);
    field.SetValue(null, new HttpClient(new HttpClientHandler { Proxy = proxy, UseProxy = true }));
}

mvdburght avatar Jun 06 '19 07:06 mvdburght

@mvdburght thanks for sharing. The enhancement we are tracking here is to allow users to supply HttpClient for the channel/transmission.

cijothomas avatar Jun 06 '19 18:06 cijothomas

I was getting a 407 Proxy Authorisation Required type message. (which by the way I had to use WireShark to discover) I got it to work using @mvdburght 's workaround. My code is using a console app so I have this at the start of my main method:

 var proxy = Settings.GetSection("Proxy").Get<WebProxy>();

            if (!string.IsNullOrWhiteSpace(proxy.Address.ToString()))
            {
                var handler = new HttpClientHandler
                {
                    Proxy = proxy
                };

                System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Transmission).TypeHandle);
                var field = typeof(Transmission).GetField("client", BindingFlags.Static | BindingFlags.NonPublic);
                field.SetValue(null, new HttpClient(handler));
            }

and in my config:

  "Proxy": {
    "Address": "http://[Url]:[Port]",
    "UseDefaultCredentials": true
  },

Hope that helps someone. Would be good to have an official way of doing it.

Swellenator avatar Jul 30 '19 04:07 Swellenator

Hi guys.

We're using App Insights in our .NET Core services and these services are running on premises in an Azure Service Fabric backend cluster. This cluster does not have internet/azure direct access.

Right now we're doing a bunch of infrastructure "hacks" using Squid in intercept mode and DNS configs so that the App Insights requests can get to Azure, without affecting the service. It works but it's ugly and it's having unintended consequences, because of the way it's set up.

It would be much easier to be able to specify a proxy exclusive to the App Insights telemetry, without changing the rest of the service.

Do you think we could use @mvdburght suggestion in this scenario?

funnay avatar Jan 29 '20 12:01 funnay

Instead of reflection, can't you set the default proxy globally for the app via System.Net.WebRequest.DefaultWebProxy ? i.e.

using System.Net;
...
// in Startup
WebRequest.DefaultWebProxy = new WebProxy(proxyUri);

Or do you want to set the value differently for App Insights?

pharring avatar Jan 29 '20 18:01 pharring

Oh, sorry; that doesn't work for HttpClient. In .NET Core 3.0 and 3.1, there's an HttpClient.DefaultProxy static property: https://docs.microsoft.com/dotnet/api/system.net.http.httpclient.defaultproxy

pharring avatar Jan 29 '20 18:01 pharring

Or do you want to set the value differently for App Insights?

This. Do you think it's possible?

funnay avatar Jan 29 '20 22:01 funnay

Hello.

Can someone please confirm if it's possible to specify a proxy only/different for App Insights using the @mvdburght suggestion?

funnay avatar Feb 04 '20 10:02 funnay