Set up dummy proxy server on a dev environment - asp.net

There is a proxy server on the clients site that all external request must go through. I am calling an external web service that needs the proxy settings.
The code I am using to set up the proxy for the web request can be seen below.
How would I go about setting up a test proxy server on my developer environment to verify that my code works?
string url = String.Format("http://currencyconverter.kowabunga.net/converter.asmx/GetConversionAmount?CurrencyFrom={0}&CurrencyTo={1}&RateDate={2}&Amount={3}", CurrencyFrom.Text, CurrencyTo.Text, formattedDate, amount);
WebRequest request = WebRequest.Create(url);
if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["proxyLogin"]))
{
WebProxy proxy = new WebProxy();
string proxyUrl = ConfigurationManager.AppSettings["proxyUrl"];
if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["proxyPort"]))
{
proxyUrl += ":" +ConfigurationManager.AppSettings["proxyPort"];
}
// Associate the newUri object to 'myProxy' object so that new myProxy settings can be set.
proxy.Address = new Uri(proxyUrl);
// Create a NetworkCredential object and associate it with the
// Proxy property of request object.
proxy.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["proxyLogin"], ConfigurationManager.AppSettings["proxyPassword"]);
request.Proxy = proxy;
}
WebResponse response = request.GetResponse();

You can install a proxy server in your development environment and configure the machines in such a way that the service is deployed beyond the firewall and you need to connect to the service through the proxy server only.

Related

GRPC call for a service which is inside a subdirectory? (Android grpc client)

This question is similar to below but my issue is with Android grpc client
How can I make a GRPC call for a service which is inside a subdirectory? (in .Net Framework)
I am getting 404 error while accessing the grpc streaming api :
UNIMPLEMENTED: HTTP status code 404
invalid content-type: text/html
headers: Metadata(:status=404,content-length=1245,content-type=text/html,server=Microsoft-IIS/10.0,request-id=5154500d-fb58-7903-65d6-3d3711129101,strict-transport-security=max-age=31536000; includeSubDomains; preload,alt-svc=h3=":443",h3-29=":443",x-preferredroutingkeydiagnostics=1,x-calculatedfetarget=PS2PR02CU003.internal.outlook.com,x-backendhttpstatus=404,x-calculatedbetarget=PUZP153MB0788.APCP153.PROD.OUTLOOK.COM,x-backendhttpstatus=404,x-rum-validated=1,x-proxy-routingcorrectness=1,x-proxy-backendserverstatus=404,x-feproxyinfo=MA0PR01CA0051.INDPRD01.PROD.OUTLOOK.COM,x-feefzinfo=MAA,ms-cv=DVBUUVj7A3ll1j03ERKRAQ.1.1,x-feserver=PS2PR02CA0054,x-firsthopcafeefz=MAA,x-powered-by=ASP.NET,x-feserver=MA0PR01CA0051,date=Tue, 11 Oct 2022 06:24:18 GMT)
The issue is that the /subdirectory_path is getting ignored by the service in the final outgoing call.
Here's the code I am using to create the grpc channel in android (gives 404)
val uri = Uri.parse("https://examplegrpcserver.com/subdirectory_path")
private val channel = let {
val builder = ManagedChannelBuilder.forTarget(uri.host+uri.path)
if (uri.scheme == "https") {
builder.useTransportSecurity()
} else {
builder.usePlaintext()
}
builder.executor(Dispatchers.IO.asExecutor()).build()
}
The uri is correct since it works with web client.
For web client the channel is defined like this (working)
var handler = new SubdirectoryHandler(httpHandler, "/subdirectory_path");
var userToken = "<token string>";
var grpcWebHandler = new GrpcWebHandler(handler);
using var channel = GrpcChannel.ForAddress("https://examplegrpcserver.com", new GrpcChannelOptions { HttpHandler = grpcWebHandler,
Credentials = ChannelCredentials.Create(new SslCredentials(), CallCredentials.FromInterceptor((context, metadata) =>
{
metadata.Add("Authorization", $"Bearer {userToken}");
return Task.CompletedTask;
}))
});
I tried to inject the subdirectory_path in the uri for my android client but unable to find appropriate api. grpc-kotlin doesn't expose the underlying http-client used in the channel.
Could someone please help me with this issue, how can I specify the subdirectory_path? (before the service and method name)
The path for an RPC is fixed by the .proto definition. Adding prefixes to the path is unsupported.
The URI passed to forTarget() points to the resource containing the addresses to connect to. So the fully-qualified form is normally of the form dns:///example.com. If you specified a host in the URI like dns://1.1.1.1/example.com, then that would mean "look up example.com at the DNS server 1.1.1.1." But there's no place to put a path prefix in the target string, as that path would only be used for address lookup, not actual RPCs.
If the web client supports path prefixes, that is a feature specific to it. It would also be using a tweaked grpc protocol that requires translation to normal backends.

SQL Server Report Server (SSRS) via WCF: HTTP request is unauthorized with client authentication scheme 'Ntlm'

I have a .Net Core 3.1 application which is trying to connect to a SQL Server Report Server via WCF, in order to programmatically generate reports on demand.
But the program is not able to authenticate against the Report Server.
Here is the relevant program code:
var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
binding.MaxReceivedMessageSize = 10485760; //10MB limit
// Create the execution service SOAP Client
var rsExec = new ReportExecutionServiceSoapClient(
binding,
new EndpointAddress("http://my-ssrs/ReportServer")
);
// Setup access credentials.
var clientCredentials = new NetworkCredential(
"MyReportServerUserName",
"MyReportServerPassword",
"."
);
if (rsExec.ClientCredentials != null)
{
rsExec.ClientCredentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Impersonation;
rsExec.ClientCredentials.Windows.ClientCredential = clientCredentials;
}
// ************************************************
// Get following Exception when next line executes.
// ************************************************
await rsExec.LoadReportAsync(null, "/path-to/my-report", null);
When the last line ("rsExec.LoadReportAsync") is executed, I get the following exception:
The HTTP request is unauthorized with client authentication scheme 'Ntlm'. The authentication header received from the server was 'NTLM'.
The Report Server is on the same Windows Domain.
After some research, I've tried changing the ClientCredentialType = HttpClientCredentialType.Windows but this generated a different exception, as follows:
The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'NTLM'.
Does anyone have any suggestions about what I might try?
Had the same problem. Solved it by additionally setting the proxy credential type:
binding.Security.Transport.ProxyCredentialType = System.ServiceModel.HttpProxyCredentialType.Ntlm;

Load balance with thrift and nginx

I have the following thrift server (socket), listening for connections on a specific host/port.
final TProtocolFactory factory = new TBinaryProtocol.Factory();
TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(serverPort);
final SignatureService.Processor theProcessor = new SignatureService.Processor(new SignatureServiceFacade());
TServer server = new THsHaServer(new THsHaServer.Args(serverTransport).processor(theProcessor).
protocolFactory(factory).
minWorkerThreads(minThreads).
maxWorkerThreads(maxThreads));
And following client connection:
clientTransport = new TFramedTransport(new TSocket(signatureHost, signaturePort));
final TProtocol theProtocol = new TBinaryProtocol(clientTransport);
client = new SignatureService.Client(theProtocol);
clientTransport.open();
//call the business specific method
client.doStuff(param1, param2, param3);
As we can see in the code above I need to provide the host and port in order to open a connection with the server.
But I want to use a service discovery with load balance support, because I'll have multiple instances of my service running.
Anybody has an example of this using nginx? All the examples is using regular http rest based applications.
Tks in advance.

ASHX sends HttpWebRequest with Impersonation On, which works to URLs on same server but not on Remote ArcGIS server

This is a complicated issue, so bear with me.
Scenario: using a ASHX proxy to relay request to an ArcGIS server.
Trying to use ASP.NET impersonation, so that the logged in ASP.NET user credentials are used by the proxy, when sending request to the ArcGIS server.
Issue: the proxy request to ArcGIS server is refused 401, even though I know the impersonated account (sean.ryan-B + sean.ryan) does have access.
There are 4 machines:
1. machine hosting proxy page. I am logged in as: sean.ryan-B
2. a test machine. I am logged in as sean.ryan-B
3. my laptop. I am logged in as sean.ryan
4. the arcgis server.
All 4 machines are on the same domain.
web.config:
<authentication mode="Windows"/>
<identity impersonate="true" /> <!-- userName="EUROPE\sean.ryan-B" password="xxx" -->
<authorization>
<deny users="?"/>
</authorization>
Test-1. Opening a test page, in same web app as proxy, via the proxy:
http://myHost.com/sean/ProxyAsp.Net/ArcGisProxy.ashx?http://myHost.com/sean/ProxyAsp.Net
[ok on all boxes 1-3]
This looks OK - the impersonation seems look OK,
since with impersonation OFF: WindowsIdentity.GetCurrent().Name = the AppPool account
with impersonation ON: WindowsIdentity.GetCurrent().Name = EUROPE\sean.ryan or EUROPE\sean.ryan-B
Test-2. opening an image that is hosted on the same IIS (but a different site), via the proxy:
http://myHost.com/sean/ProxyAsp.Net/ArcGisProxy.ashx?http://myHost.com:10400/sites/CaSPER/SiteAssets/CaSPER.jpg
[ok on boxes 1-3]
Test-3. opening the ArcGIS map URL, via the proxy:
http://myHost.com/sean/ProxyAsp.Net/ArcGisProxy.ashx?http://mapserver1.com/ArcGIS/rest/services/Global/2D_BaseMap_SurfaceGeology/MapServer?f=json&callback=dojo.io.script.jsonp_dojoIoScript1._jsonpCallback
[fails on boxes 2,3 but succeeds on the proxy host (box 1)!]
code for the ASHX code-behind:
public partial class ArcGisProxy : IHttpHandler, IReadOnlySessionState //ASHX implements IReadOnlySessionState in order to be able to read from session
{
public void ProcessRequest(HttpContext context)
{
try
{
HttpResponse response = context.Response;
// Get the URL requested by the client (take the entire querystring at once
// to handle the case of the URL itself containing querystring parameters)
string uri = context.Request.Url.Query;
uri = uri.Substring(1); //the Substring(1) is to skip the ?, in order to get the request URL.
System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)WebRequest.Create(uri);
{
req.Credentials = CredentialCache.DefaultCredentials; //this works on local box, with -B account. this is the account the web browser is running under (rather than the account logged into CaSPER with, as ASHX has separate server session).
req.ImpersonationLevel = TokenImpersonationLevel.Impersonation;
}
//to turn off caching: req.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
req.Method = context.Request.HttpMethod;
req.ServicePoint.Expect100Continue = false;
req.Referer = context.Request.Headers["referer"];
// Set body of request for POST requests
req.Method = "GET";
// Send the request to the server
System.Net.WebResponse serverResponse = null;
try
{
serverResponse = req.GetResponse();
}
catch (System.Net.WebException webExc)
{
//logger.Log(GetMyUrl(), webExc, context.Request);
response.StatusCode = 500;
response.StatusDescription = webExc.Status.ToString();
response.Write(webExc.ToString());
response.Write(webExc.Response);
response.Write("Username = " + context.User.Identity.Name + " " + context.User.Identity.IsAuthenticated + " " + context.User.Identity.AuthenticationType);
response.End();
return;
}
// Set up the response to the client
....
......
response.End();
}
catch (Exception ex)
{
throw;
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
note: the following changes, meant proxy request to the map server DOES succeed:
a) set the identity in the web.config to explicitly set username, password to the sean.ryan-B account:
-OR-
b) set the App Pool account to be sean.ryan-B and turn OFF impersonation in the web.config file.
however these changes are not acceptable for Production.
The problem seems to be that:
- ASP.NET impersonation works well enough for test page + image hosted on same IIS (tests 1 and 2)
but NOT well enough for the map server.
as far as I know, the ArcGIS map server is using Negotiate, and then Kerberos authentication.
With WireShark, I monitored a successful proxy request, and found:
after 401, proxy sends GET with AUTH using SPNEGO (Kerberos)
Has anyone had similar issue with ArcGIS proxy ?
My theory is, that the impersonation on box 1 'works better', because browser is running on same box as the proxy.
Could the ArcGIS Server (or the IIS site it is using) be restricted to prevent accepting impersonation ?
Any suggestions welcome ...
p.s. had a hard time getting this post through - had to format most of it as code, as s-o is detecting it as source code !

How to host duplex wcf service on a VPS

i am trying to host a wcf service which has a following attribute;
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
and i am creating host class like this;
var uri = new Uri("net.tcp://localhost:7951");
var binding = new NetTcpBinding();
host = new ServiceHost(typeof(ChatService), uri);
ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null) host.Description.Behaviors.Add(new ServiceMetadataBehavior());
host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
host.AddServiceEndpoint(typeof(IChat), new NetTcpBinding(), "");
host.Open();
So, on developer computer and dedicated server this is working. However, what i need to do is, host this on a VPS (vitual private server).
I thought making a web project and adding this code block to global.asax application start method. but this failed. I suspect problem that the port is closed from firewall maybe.
What solution should I follow?

Resources