Open marcBalta opened 5 years ago
I got the same issue (with an nginx reverse proxy).
In my opionion the problem is that BaGet doesnt configure the Forward Header Engine to use also XForwardedHost:
var fordwardedHeaderOptions = new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost
};
app.UseForwardedHeaders(fordwardedHeaderOptions);
Pitty. Is there any workaround possible? This is pretty much a blocker as it is not possible to use a nginx to forward to baget in a docker container.
The workaround could be maybe to rewrite the domain in the http repsonses. But I didnt try that. If you got that working im keen to hear about your solution.
It seems that those headers were once added, see https://github.com/loic-sharma/BaGet/pull/65/files I guess they were missed while some migration took place and now they're gone. I am currently testing if that would fix that issue.
Ok interesting. But the important header is missing, which is XForwardedHost. This contains contains the reverse proxy domain.
yes, basically
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
is missing.
Ah, ForwardedHeaders.XForwardedHost
should probably be added as well.
Well that part seems to work now. Now I also need to figure out how to change the base-path (I am running it in /nuget/ subfolder) when running from a docker container.
There is a app.UsePathBase(options.PathBase);
in Startup.cs
but I cannot figure out how that options object is filled.
Cool. Will it be part of the next release? In IIS I used a rewrite rule to solve this problem. It seemed that this made the nuget protocol working. But I didnt came so far to say that for sure. If not the following could help:
if (Configuration["URL_BASE_PATH"] != null)
{
app.Use(async (ctx, next) =>
{
ctx.Request.PathBase = Configuration["URL_BASE_PATH"];// "/schlemihl";
await next.Invoke();
});
}
URL_BASE_PATH is than an environment variable which has to be set from outside.
For the angular UI, however, there has to be done some more work:
Well actually for my asp.net core apps UseBapthBase didnt work.
Adding
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost;
});
to IServiceCollectionExtensions.cs and
string basePath = Environment.GetEnvironmentVariable("ASPNETCORE_BASEPATH");
if (!string.IsNullOrEmpty(basePath))
{
app.Use(async (context, next) =>
{
context.Request.PathBase = basePath;
await next.Invoke();
});
app.UsePathBase(options.PathBase);
}
to Startup.cs
Seems to fix the api entirely when I then provide the environment variable ASPNETCORE_BASEPATH
in the docker container. The React UI still does not work.
Yeah I know. Please mind https://github.com/loic-sharma/BaGet/issues/276#issuecomment-499067303
Yup but I don't know React. It is easy to hardcode the base path into it but it should be something dynamic so it can be controlled when running the docker container.
And will your changes be part of the next release?
That you need to ask the author of this project ;) I could create a PR for it. I pushed a docker container with my changes here: https://hub.docker.com/r/roemer/baget In case you want to test it as well.
A PR would be great. Thx!
Would be great to have the frontend fixed as well. Let's see if @loic-sharma has some hints / comments.
Just for your info, I switched over to Nexus as that one works seamlessly with subdomains and reverse proxies.
Thx for the hint. I already switched to Nuget.Server but didnt had the time to put it into docker and behind a reverse proxy. I think I will have a look at nexus.
@roman, @marcBalta thanks for the hints! Probably we should solve the root problem here.
Yes that would be great. The code discussed above fix the issue that the headers passed from the reverse proxy are not handled correctly. With that, it generally works behind a reverse proxy. The second issue is that the application should be able to run in a subfolder. It seems to be easy to add a hardcoded subpath on build time but I have no idea how to do that on runtime. That needs some investigation.
Hello, I apologize for the long response time! It seems like there's two problems:
To fix the first problem, it seems that ForwardedHeaders.XForwardedHost
option should be added to this line. Adding this option has security implications (see CVE-2018-0787), so we should add configs to BaGet to lock down forwarding. I suggest we add the following configs:
{
...
"ForwardHeaders": {
"Include": ["XForwardedFor", "XForwardedProto", "XForwardedHost" ],
"AllowedHosts": [ "*.contoso.com" ],
"KnownNetworks": [ "10.0.0.1" ],
"KnownProxies": [ "10.0.0.1" ],
},
...
}
These would map to their equivalent ASP.NET Core configurations. Does this seem like a good approach?
/cc @marcBalta @Roemer @DoCode
@loic-sharma Yes you're right, these are two separate issues. The ForwardedHeaders.XForwardedHost
should fix the first issue.
The second is (in my opinion) not only just a nice to have. Usually when using a reverse proxy, you want to redirect multiple applications to different servers. For example:
nginx/app1 => appserver/app1
nginx/jenkins => buildserver/jenkins
nginx/nexus => nexusserver/nexus
Without the possibility to host an application under a subpath, it is (as far as I know) not possible to use it in a normal reverse proxy scenario.
I see, that makes sense. Thanks for the information
Hi
If the topic is still up to anyone I added full PathBase support. Refer to basePathSupport in my fork.
It basically adds a new option to BaGetOptions called HostUrl
which allows to specify the AllowedHosts value.
As second part it rewrites all values in react to match the PathBase
. This is done with a placeholder as homepage value in package.json and in config.tsx. For development use you have to specify the values by manually.
For proxying with nginx keep in mind to set X-Forwarded-Host
to $host:$server_port
@loic-sharma I will create a pull request for that.
This is an IIS configuration issue not a BaGet issue. The first setting you need to check on your re-write server is the server level setting: system.webServer/proxy: preserveHostHeader. If this is set "True" then the request "Host" header will be passed through to the destination server. And you don't need to worry about X-Forwarded or any of that confusing misdirection. If it is set to "False" then ARR will rewrite the Host header to reflect the host hame of the server is is redirecting the request to. i.e. 192.168.etc. Usually not what you want. One way to fix this is clearly at this level but as the system.webServer/proxy preserverHostHeader setting applies server wide that might have unintended side effects if the server is hosting other loads making use of the proxy. In which case, a simple rewrite of the rewrite rules has you covered:
So, first add "HTTP_HOST" to the list of Allowed Server Variables, then ammend your rewrite rule to have a condition and server variable rule like this :-
<rules>
<rule name="test" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="(.*)" />
</conditions>
<serverVariables>
<set name="HTTP_HOST" value="{C:1}" />
</serverVariables>
<action type="Rewrite" url="http://example.com/{R:1}" />
</rule>
As conditions are always processed before the rules are triggered, they captures the "Host" header as {C:1}, and then serverVariables are applied hopefully after ARR and Rewrite have done their other modifications, where we set it back to the original - passed in - value.
Again. No need to mess around with non standard X-Forwarded etc. headers.
This is an IIS configuration issue not a BaGet issue.
This is the BaGet issue.
When you run a push command from CLI, nuget.exe
will request for a config json file that contains all necessaries urls.
It then cache that config file at \AppData\Local\NuGet\v3-cache\<some random string>$_nuget.devmoba.com_v3_index.json
and use the settings in that file to continue the process (of pushing packages). Changing some IIS config will definitely not help you to change this file 's content.
So, my work around is manually change all the URLs in that file to http://my.company.name
instead of http://locahost:xxxx
Hopefully the next release will let us change this by a setting line.
+1
Found a WA: Use outbound rule rewrite:
<outboundRules>
<rule name="Rewire internal host IP" preCondition="" patternSyntax="ECMAScript">
<match filterByTags="None" pattern="https:\/\/IP:PORT\/" negate="false" />
<action type="Rewrite" value="https://example.com/" />
</rule>
</outboundRules>
This is the BaGet issue. ... Changing some IIS config will definitely not help you to change this file 's content.
You are correct in that, if an api is returning fully qualified urls, then it does take on the task of supporting different base urls itself.
However, "some IIS config" defiantly will help you change that files content. Response rewrite rules perform regex based replacements on outgoing content for specifically the purpose of fixing urls in response documents.
Describe the bug
I'm using BaGet inside a windows docker image. IIS 10 is used as a reverse proxy. This is the web.config file used to proxy queries with the pattern domain.de/nuget/ to the BaGet server which is running in a Windows Docher container on another machine with the IP 192.168.178.2.
This is my baget.env :
When Im running however the nuget push command it uses the internal IP address (the url of docker container) and not the one of the proxy.
The angular UI isnt running at all. Thats seems to be however the typical problem with the base element not set correctly.