Connect to SOCKS proxy that requires authentication - c#

I'm using Fiddler Core in my project and have had success routing requests through a SOCKS proxy that does not require authentication.
oS["x-OverrideGateway"] = string.Format("socks={0}:{1}", ProxyHost, ProxyPort);
Now I'm trying to connect to a SOCKS proxy that requires authentication. I've tried adding the below, per this non-SOCKS guide: Authenticate With CBT.
oS["X-AutoAuth"] = Auth;
Where Auth is a string containing the credentials in the form username:password. But the connection always fails with a Bad Gateway exception. I've been successful connecting to the same SOCKS proxy using curl and following it's guidelines for an authenticated SOCKS proxy.
After X-AutoAuth didn't work I reflected some of the code and found that this authentication mechanism is not used for SOCKS.

Rather unfortunately, Fiddler (and FiddlerCore) does not support SOCKS5 as of yet.
You could, however, request this at https://fiddler.ideas.aha.io/.

We faced a similar issue and created a NuGet library which helps you "transform" SOCKS v4 traffic to SOCKS v5, and we added authentication support as well.
This small example shows how can you hook up FiddlerCore and a SOCKS5 proxy with username and password:
var localEndpoint = new IPEndPoint(IPAddress.Loopback, 4321);
var remoteEndpoint = new IPEndPoint(IPAddress.Parse("remote proxy IP"), 8080);
ISocksRelayServer relay = new SocksRelayServer.SocksRelayServer(localEndpoint, remoteEndpoint)
{
Username = "...",
Password = "..."
};
// Debug to console
relay.OnLogMessage += (sender, s) => Console.WriteLine($"OnLogMessage: {s}");
relay.OnLocalConnect += (sender, endpoint) => Console.WriteLine($"OnLocalConnect: {endpoint}");
relay.OnRemoteConnect += (sender, endpoint) => Console.WriteLine($"OnRemoteConnect: {endpoint}");
// Start relay server
relay.Start();
// Start FiddlerCore
FiddlerApplication.Startup(...);
// Set upstream gateway before requests
FiddlerApplication.BeforeRequest += session =>
{
session["x-OverrideGateway"] = relay.LocalEndPoint.ToString();
}

Related

How it works the security in gRPC?

I have a service that I am configurating in this way:
options.Listen(miAddress, 5001, l =>
{
l.Protocols = HttpProtocols.Http2;
System.Security.Cryptography.X509Certificates.X509Certificate2 miCertificado = new System.Security.Cryptography.X509Certificates.X509Certificate2(#"certificados\service.crt");
l.UseHttps(miCertificado);
});
But if I realized that I can configure the client to avoid the authentication, with this code:
var httpClientHandler = new System.Net.Http.HttpClientHandler();
httpClientHandler.ServerCertificateCustomValidationCallback =
System.Net.Http.HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new System.Net.Http.HttpClient(httpClientHandler);
var channel = GrpcChannel.ForAddress(_serviceAddress,
new GrpcChannelOptions { HttpClient = httpClient });
var client = new Gestor.GestorClient(channel);
In this case, the authentications is ignored and I can use call to the service.
I know that this ignore the authentication because if I try to use the client to use a certificate, I get an error that tells that the connection couldn't be stablish because of the SSL.
So my doubt is, there is some way to set the service to don't allow this kind of connections? If not, anyone could create a client that igonres this authentication and the security has no sense.
Thanks.
Using HTTPS is not the same as using authentication. All you're doing is encrypting the traffic between client and server, so that eavesdroppers can't read your plaintext traffic.
If you configure your client to accept any server certificate, whether that certificate is valid up till its root or not, does not "ignore authentication" - there was no authentication to begin with.

Calling WCF Service with basic auth and client certificate

We are writing a client to a WCF service that uses both a CSR certificate and basic authentication.
Our C# client is generated via Visual Studio and we can programmatically set the certificate and the username/password. However, we have to manually send the Basic Auth header otherwise we receive the error:
'The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Basic realm="HttpBasicAuthentication"'.'
Our code is:
var myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Transport;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
myBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
var ea = new EndpointAddress("https://example.org/myservice");
var client = new MandateWebServiceClient(myBinding, ea);
client.ClientCredentials.UserName.UserName = "wally";
client.ClientCredentials.UserName.Password = "walliesWorld";
client.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2("C:\\some\\path\\to\\csr.pfx", "password");
using (var scope = new OperationContextScope(client.InnerChannel))
{
var httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers[HttpRequestHeader.Authorization] =
"Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(client.ClientCredentials.UserName.UserName + ":" + client.ClientCredentials.UserName.Password));
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
client.create();
}
With the above code, we can successfully talk to the service. If we remove the lines in the using block, the authentication scheme changes to Anonymous, and we get the error above.
The above arrangement seems a little hackey. We have tried all the SecurityMode settings possible and SecurityMode.Transport with HttpClientCredentialType.Certificate is the only combination that allows the certificate to be accepted. Setting or not setting MessageCredentialType.UserName appears to have no effect on the system.
Is there any .Net Framework way of providing both the certificate and the basic authentication header rather than manually adding the header?
How does the server use both Certificate authentication and Basic authentication? This seems superfluous. Because it is secure to authenticate the client with a certificate (issue the certificate and establish the relationship between the server and client), why do we need to authenticate the client with Basic Authentication? Thereby, are you sure that the client needs to provide a certificate? In my opinion, the server may have used Transport Security mode, and set up a Basic authentication, so the client may need not to provide a certificate.
Here is the server side configuration I thought.
Server.
Uri uri = new Uri("https://localhost:9900");
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
Client (invocation by adding service reference, the client proxy class/binding type is auto-generated via the service MEX endpoint, https://localhost:9900/mex)
ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();
client.ClientCredentials.UserName.UserName = "administrator";
client.ClientCredentials.UserName.Password = "abcd1234!";
Based on this, I have a question, what is the auto-generated binding type on the client side when calling the service by adding service reference?
Look forward to your reply.

'No such device or address' returned from FirebaseAdmin SDK on .Net Core

I am sending push notifications to devices from Firebase cloud messaging service. For doing so I used FirebaseAdmin SDK on .Net Core. I have followed the exact instructions from Firebase documentation to initialize FirebaseApp and send messages. Since this code needed to run from behind a firewall, i was given a tested proxy server from our infra team to set on Firebase admin's HttpClientFactory which i therefore implemented to serve the purpose.
Here's my code...
Init part
FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.FromJson("")// service account json content,
HttpClientFactory = new ProxyHttpClientFactory(new WebProxy()
{
Address = new Uri("") //anonymous proxy address
})
});
HttpClientFactory Implementation
public sealed class ProxyHttpClientFactory : HttpClientFactory
{
private readonly IWebProxy _proxy;
public ProxyHttpClientFactory(IWebProxy proxy)
{
_proxy = proxy;
}
protected override HttpMessageHandler CreateHandler(CreateHttpClientArgs args)
{
return new HttpClientHandler
{
Proxy = _proxy,
UseProxy = true,
};
}
}
Sending the Firebase Message
var _fcm = FirebaseMessaging.DefaultInstance;
var message = new Message()
{
Notification = new Notification()
{
Title = "title",
Body = "body"
},
Token = "" //valid device token
};
_fcm.SendAsync(message);
Upon calling the SendAsync from FCM i will receive an http exception saying:
'No such device or address'
Which most probably means the proxy has not worked as expected and i am still stuck behind the Firewall. I have managed to send message via proxy from Curl command but cannot seem to make it work from dot net side. I have tampered with WebProxy properties, sending empty credentials, enabling and disabling proxy for local, sending null for baypass list, etc, all to no avail. Service account content is fine and is being set as it should, even proxy settings in client factory seems to be in place but not working.
Any workaround/solutions would be immensely appreciated!
Ok, after trying out almost everything finally got to fix this problem by passing the proxy-enabled HttpClientFactory to GoogleCredentials as well. Apparently setting the HttpClientFactory on Firebase options is not enough, which is an obvious bug in FirebaseAdmin in my opinion. Anyhow, this is how I patched the thing:
ServiceAccountCredential serviceAccountCredential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer("---client email---")
{
ProjectId = "---project id----",
HttpClientFactory = new ProxyHttpClientFactory(new WebProxy()
{
Address = new Uri("---anonymous proxy address---")
})
}.FromPrivateKey("---private key---"));
GoogleCredential googleCredential = GoogleCredential.FromServiceAccountCredential(serviceAccountCredential);
ServiceAccountCredential is the underlying type for GoogleCredentials type. Firebase admin will take care of composing this from the high-level GoogleCredentials property. Yet in this special case, it wouldn't inject the HttpClientFactory to the credentials, causing the code not to be able to reach the token endpoint.
So yes, the cooked GoogleCredentials object will later be passed to FirebaseApp's Create method.

The SSL connection could not be established

I am using a third party library (Splunk c# SDK ) in my ASP.NET core application. I am trying to connect to my localhost Splunk service via this SDK, but I get an exception saying:
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
And The inner exception says:
The remote certificate is invalid according to the validation procedure.
This SDK uses HTTP client under the hood, but I don't have access to this object to configure HttpClientHandler.
All my search on google ends up using ServicePointManager to bypass the SSL validation, but this solution doesn't work in Asp.Net core.
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
Is there any way to bypass this validation in asp.Net core?
Yes, you can Bypass the certificate using below code...
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
// Pass the handler to httpclient(from you are calling api)
HttpClient client = new HttpClient(clientHandler);
As I worked with the identity server (.net core) and a web api (.net core) on my developer machine, I realized, that I need to trust the ssl certification of localhost. That command does the job for me:
dotnet dev-certs https --trust
If you are adding an IHttpClient and injecting through DI, u can add the configuration on the Startup.cs class.
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient("yourServerName").ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }
});
}
And then call it from your dependency injected class.
public class MyServiceClass
{
private readonly IHttpClientFactory _clientFactory;
public MyServiceClass (IConfiguration configuration, IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
public async Task<int> DoSomething()
{
var url = "yoururl.com";
var client = _clientFactory.CreateClient("yourServerName");
var result = await client.GetAsync(url);
}
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) =>
{
// local dev, just approve all certs
if (development) return true;
return errors == SslPolicyErrors.None ;
};
This blog helped me
https://www.khalidabuhakmeh.com/validate-ssl-certificate-with-servicepointmanager
This worked for me,
Create a Splunk.Client.Context by providing custom HttpClientHandler, that will bypass SSL invalid cert errors.
HttpClientHandler handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
// Create Context
Context context = new Context(Scheme.Https, "localhost", 8089, default(TimeSpan), handler);
// Create Service
service = new Service(context);
You get this error because your app isn't able to validate the certificate of the connection, and it's especially common to use this for the API that creates the session/login tokens. You can bypass it in a dangerous way as shown above, but obviously that's not a good solution unless you're just testing.
The best and easiest solution is to use the "modernhttpclient-updated" Nuget package, whose code is shared in this GitHub repo where there's also a lot of documentation.
As soon as you add the Nuget package, pass in a NativeMessageHandler into you HttpClient() as shown and build:
var httpClient = new HttpClient(new NativeMessageHandler());
Now you will notice that you got rid of that error and will get a different error message like this Certificate pinning failure: chain error. ---> Javax.Net.Ssl.SSLPeerUnverifiedException: Hostname abcdef.ghij.kl.mn not verified: certificate: sha256/9+L...C4Dw=
To get rid of this new error message, you have to do add the hostname and certificate key from the error to a Pin and add that to the TLSConfig of your NativeMessageHandler as shown:
var pin = new Pin();
pin.Hostname = "abcdef.ghij.kl.mn";
pin.PublicKeys = new string[] { "sha256/9+L...C4Dw=" };
var config = new TLSConfig();
config.Pins = new List<Pin>();
config.Pins.Add(pin);
httpClient = new HttpClient(new NativeMessageHandler(true, config)
Keep in mind that your other (non token generating) API calls may not implement certificate pinning so they may not need this, and frequently they may use a different Hostname. In that case you will need to register them as pins too, or just use a different HttpClient for them!
Installing the .NET Core SDK installs the ASP.NET Core HTTPS development certificate to the local user certificate store. The certificate has been installed, but it's not trusted. To trust the certificate, perform the one-time step to run the dotnet dev-certs tool:
dotnet dev-certs https --trust
for more information visit this link
I had to turn off my vpn to get rid off this error

Reuse EWS connection and negotiate authentication for Exchange

I am writing a program to dump the contents of numerous mailboxes from an Exchange server using EWS in C#. Using fiddler I noticed that each request I send makes a new connection (tunnel), with a new authentication process being undertaken (using negotiate). My ServerCertificateValidationCallback gets called for every request.
If I enable the option in Fiddler to "reuse server connections" than the connection is only created during handshaking, and is re-used for all requests (saving lots of time).
By getting the EWS source and modifying the requests I found if I enable "UnsafeAuthenticatedConnectionSharing" on the request objects than the connection is re-used (extra tunnels & ServerCertificateValidationCallbacks disappear), but each request still requires the full handshake authentication. This is because the server sends back a 401 when ever I try and use the exchange cookie.
Is there any way I can re-use my server connection & authentication?
public class EwsExchange
{
static int Main(string[] args)
{
sslCertCheckCount = 0;
ServicePointManager.ServerCertificateValidationCallback = ServerCertificateValidation;
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
service.Credentials = new NetworkCredential(args[1], args[2]);
service.Url = new Uri(args[0] + #"/EWS/exchange.asmx");
service.KeepAlive = true;
service.PreAuthenticate = true;
//service.UnsafeAuthenticatedConnectionSharing = true;
Folder folder = Folder.Bind(service, WellKnownFolderName.Inbox, new PropertySet(FolderSchema.Id, FolderSchema.DisplayName));
FindItemsResults<Item> res = folder.FindItems(new ItemView(int.MaxValue));
return 0;
}
public static bool ServerCertificateValidation(Object obj, X509Certificate certificate, X509Chain chain, System.Net.Security.SslPolicyErrors errors)
{
Console.WriteLine(String.Format(" ****************** ServerCertificateValidation - count: {0}. ****************** ", ++sslCertCheckCount));
return true;
}
static int sslCertCheckCount;
}
Thanks!
So it turns out that after I modified the EWS API to allow me to enable UnsafeAuthenticatedConnectionSharing on the HttpRequests, that my connection and authentication were actually being re-used.
Fiddler was the one dropping my connections after I disabled the option "Tools -> Fiddler Options -> Connections -> Reuse server connections". Running wireshark on the exchange server machine showed that when fiddler was capturing with this option disabled the FIN TCP flag was being set, ending the session. But without fiddler capturing the connection & session were both re-used.

Categories

Resources