How to stop sending origin IP with Azure Api Management Gateway - api

I'm fiddling a bit with Azure API Management Gateway to see if it would fit our purpose.
It was quite simple to add an API from our ERP application (Saas app with IP whitelisting our Office locations) and I'm able to call it from within our office.
However, when I call the api from any other location, I get the message from the ERP that the IP is blocked.
I'm currently on a Development tier and (should) have a static IP assigned let's say
VIP public: 20.82.86.xxx
What I've done so far:
added a inboud policy, stripping the x-forwarded-for header, tried both API level and operation level
<inbound>
<base />
<set-header name="X-Forwarded-For" exists-action="delete" />
What I've tested/noticed so far:
When I test the call from within APIM, the IP is blocked. I can see that the header is stripped on inbound
set-header (0.008 ms)
"Header X-Forwarded-For was removed."
I see that APIM is adding a x-forwarded-for header in backend, seems with the IP of the frontend/APIM website
{"name": "X-Forwarded-For","value": "13.91.254.xxx"}
The response I get back is that the ip from my device (84.105.xxx.xxx) is blocked by the ERP
I don't understand why the originating IP is the local IP from my device/location instead of the API Gateway.
Azure API Managemnent gateway seems to be very useful for our purpose and it's not that difficult the work with. However it's important that I can call it from other locations than our office.
Any ideas?

I tested setting an explicit value for the X-Forwarded-For header like this in the inbound policy:
<set-header name="X-Forwarded-For" exists-action="override">
<value>xx.xx.xx.xx</value>
</set-header>
Then the resulting header in the backend request was:
X-Forwarded-For: xx.xx.xx.xx,yy.yy.yy.yy
This might fool your backend to think that xx.xx.xx.xx is your client IP, when it is really yy.yy.yy.yy.

If you have added any such header exclusively before forwarding the request to the backend via policy, it can be removed via policy.
But the X-Forwarded-For header being added by the APIM gateway by default cannot be eliminated since this is by design and is required by the service to accurately forward the request to the backend API.
https://www.geeksforgeeks.org/http-headers-x-forwarded-for/

Related

How to Remove Azure Access-Control-Expose-Headers

Posts to my Azure Web App are being replied to with additional Http Header information, specifically the following:
Access-Control-Expose-Headers: Request-Context
Set-Cookie: ARRAffinity=xxx;Path=/;HttpOnly;Domain=ws.caxxx
Request-Context: appId=cid-v1:xxx
This appears to be due to Custom Domains configured on my site, i.e., the Azure site url is xxx.azurewebsites.net and I have a Custom Domain set ws.xxx.com. I say that because when I'm posting to the Azure url I do not see the Access-Control-Expose-Headers and the Request-Context lines in the headers.
I do not have CORS configured for this site, so I don't know why I am getting the Access-Control-Expose-Headers.
Note that this is the Production site. I have another Testing site where I do not have this problem! So there must be something with my Azure configuration.
On my Testing site, I can remove the ARRAffinity cookie by adding the httpProtocol clause to the web.config. However, when added to the Production site it throws a 500 error.
The posting devices are IoT devices, so I need to reduce the headers sent back to the devices.
Any advice is greatly appreciated!

ASP.NET Core app is behind a ssl proxy server and Reply to URL is http:// not https://

I have an ASP.NET Core Application on an IIS server listening on whatever.domain.com/virtual-dir usings . The outside world accesses it through a ssl accelerator. Its using Microsoft.AspNetCore.Authentication.OpenIdConnect for OpenId authentication through AzureAd.
Because of the SSL proxy the app things its base address scheme is http as opposed to https (http://whatever.domain.com/virtual-dir vs https://whatever.domain.com/virtual-dir. This leads to it sending a reply-to address of http://whatever.domain.com/virtual-dir/signin-oidc as opposed to https://whatever.domain.com/virtual-dir/signin-oidc. I can modify the callback endpoint with OpenIdConnectOptions.CallbackPath, but that is only relative to the base Url. How do I change the base url?
Don't do this. This is a bad idea.
The best way I've figured out how to do this so far is to set OpenIdConnectOptions.Events.OnRedirectToIdentityProvider to a function and in that function you can edit the ProtocolMessage.RedirectUri in the RedirectContext parameter that gets passed.
/// <seealso cref="OpenIdConnectEvents.OnRedirectToIdentityProvider"/>
public async Task OnRedirectToIdentityProvider(RedirectContext redirectContext)
{
redirectContext.ProtocolMessage.RedirectUri =
"https://whatever.domain.com/virtual-dir";
}
Directions for this is here:
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.1#when-it-isnt-possible-to-add-forwarded-headers-and-all-requests-are-secure
Breakdown:
You're proxy needs to set three Http Headers, X-Forwarded-For, X-Forwarded-Proto and X-Forwarded-Host
You need to configure ForardHeaderOptions. In theory IIS should do this for you.
In Startup.Configure() you need to call app.UseForwardedHeaders(); before app.UseAuthentication() so the the Request base is rewritten.

IFTTT Maker Channel - Send POST Request to ipv6 adress

Is ist possible to send POST requests to ipv6 addresses using the ifttt.com service?
I found the maker channel but it doesn't seem to work (with ipv6 addresses).
Here the request I want to send to my openhab system:
POST
http://[xyyx:yxy:yxy:yxyx:yxyx:yxyx:yxyx:yxyx]:8080/rest/items/Kueche
Content-Type: text/plain
Body: TOGGLE
I have the same problem, want to use Maker with IPv6 address. Don't seems to work, neither passing a domain that only resolves to an IPv6 address.
I have done a workaround, using Google App Engine (it has IPv6 support) as a proxy for my IFTTT Maker requests.
The code is pretty ugly, just a POC:
https://gist.github.com/6f9e67fe47c67eca46655b8033bcf862
In the Maker "that" is set the URL like this:
https://miappid.appspot.com/?query=data&ipv6=http://home.duckdns.org
The app deployed in GAE take the parameters of the query (except ipv6), content-type header and body, and create a new request to the addres specified in the ipv6 param.

Getting client ip address in flask

I am trying to get the client ip at the server Y in the following scenario,
client requests server X which forwards the request to server Y.
And the return flow is Y->X->client
'REMOTE_ADDR' in the http header(actually i get it from request.environ['REMOTE_ADDR']) has the ip of server X. From where can i get the ip of the client at server Y ?
UPDATE:
X has a public ip. Y is in a private network and is inaccessible outside. Now i am using a client in the same private network and i request X via the public network.
I just want to know if the header already has what i need without manipulating the header at X to include ip of client.
If your application is behind a proxy then the remote address of the request will appear to your application to be from the proxy, not the actual client.
There is no provision in the http spec to pass on the 'real' address but the de-facto standard for doing this is by having your proxy set an X-Forwarded-For header
Werkzeug provides a fixer to help with this, and there's an example detailed in the Flask docs, request.remote_addr should then be what you expect
Despite your claims, X is basically a proxy, since it makes its own request to Y, based on a request the user makes. So it's perfectly valid that REMOTE_ADDR is the one of X.
You will have to add a custom header to X's requests, like X-Original-User-IP to make the user's IP available to Y. You can use ProxyFix for this if you want, it will rewrite X-Forwarded-For to REMOTE_ADDR
You should make sure Y is only available to X and cannot be accessed directly. Otherwise one could spoof his IP address simply by sending that custom header.

Why is same origin policy kicking in when making request from localhost to localhost?

I'm keeping the backend API as a separate project from the frontend HTML5 app consuming it. I'm using Yeoman for the frontend development. Yeoman runs on localhost:3501 and the backend on localhost:3000. When I make the API request from the browser (using AngularJS's $http), I hit the same origin policy:
XMLHttpRequest cannot load http://localhost:3000/venues. Origin http://localhost:3501 is not allowed by Access-Control-Allow-Origin.
AFAIK, same origin policy should kick in only when making request across different domains. Why is it whining when we do a request from localhost to localhost (albeit to different port)?
How can I make this work and will this cause problems in production?
The ports also count for cross domain requests, therefore http://localhost:3000 and http://localhost:3501 are 2 different domains (from browser's point of view).
If you need both applications (client and backend) to run on different ports, consider using http://enable-cors.org/
According to W3C, "An origin is defined by the scheme, host, and port of a URL", so the different port is causing your problems.
Two possible solutions:
CORS (Cross Origin Resource Sharing)
Using JSONP requests
Both would require changes to your backend (I'm not familiar enough wo. CORS would probably mean the least changes to your frontend (I think AngularJS supports it out-of-the-box).