Remove x-fowarded-for and x-forwarded-proto.
This commit is contained in:
parent
aaea8bdf05
commit
f8ff2cd6d1
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:25334/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNET_ENVIRONMENT": "Development"
|
||||
},
|
||||
"weblistener": {
|
||||
"commandName": "weblistener",
|
||||
"environmentVariables": {
|
||||
"ASPNET_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"web": {
|
||||
"commandName": "web",
|
||||
"environmentVariables": {
|
||||
"ASPNET_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +1,19 @@
|
|||
{
|
||||
"webroot": "wwwroot",
|
||||
"version": "1.0.0-*",
|
||||
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-*",
|
||||
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*",
|
||||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0-*"
|
||||
},
|
||||
|
||||
"commands": {
|
||||
"weblistener": "Microsoft.AspNet.Server.WebListener",
|
||||
"web": "Microsoft.AspNet.Server.Kestrel"
|
||||
"web": "Microsoft.AspNet.Server.Kestrel",
|
||||
"weblistener": "Microsoft.AspNet.Server.WebListener"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"dnx451": { },
|
||||
"dnxcore50": { }
|
||||
},
|
||||
|
||||
"publishExclude": [
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
|
|
|
|||
|
|
@ -3,29 +3,20 @@
|
|||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
using Microsoft.AspNet.Http.Features.Authentication;
|
||||
using Microsoft.AspNet.Http.Features.Authentication.Internal;
|
||||
using Microsoft.Extensions.Internal;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNet.IISPlatformHandler
|
||||
{
|
||||
public class IISPlatformHandlerMiddleware
|
||||
{
|
||||
private const string XForwardedForHeaderName = "X-Forwarded-For";
|
||||
private const string XForwardedProtoHeaderName = "X-Forwarded-Proto";
|
||||
private const string XIISWindowsAuthToken = "X-IIS-WindowsAuthToken";
|
||||
private const string XOriginalPortName = "X-Original-Port";
|
||||
private const string XOriginalProtoName = "X-Original-Proto";
|
||||
private const string XOriginalIPName = "X-Original-IP";
|
||||
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IISPlatformHandlerOptions _options;
|
||||
|
|
@ -46,9 +37,6 @@ namespace Microsoft.AspNet.IISPlatformHandler
|
|||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
UpdateScheme(httpContext);
|
||||
|
||||
UpdateRemoteIp(httpContext);
|
||||
if (_options.FlowWindowsAuthentication)
|
||||
{
|
||||
var winPrincipal = UpdateUser(httpContext);
|
||||
|
|
@ -69,47 +57,6 @@ namespace Microsoft.AspNet.IISPlatformHandler
|
|||
}
|
||||
}
|
||||
|
||||
private static void UpdateScheme(HttpContext httpContext)
|
||||
{
|
||||
var xForwardProtoHeaderValue = httpContext.Request.Headers[XForwardedProtoHeaderName];
|
||||
if (!string.IsNullOrEmpty(xForwardProtoHeaderValue))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(httpContext.Request.Scheme))
|
||||
{
|
||||
httpContext.Request.Headers[XOriginalProtoName] = httpContext.Request.Scheme;
|
||||
}
|
||||
httpContext.Request.Scheme = xForwardProtoHeaderValue;
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateRemoteIp(HttpContext httpContext)
|
||||
{
|
||||
var xForwardedForHeaderValue = httpContext.Request.Headers.GetCommaSeparatedValues(XForwardedForHeaderName);
|
||||
if (xForwardedForHeaderValue != null && xForwardedForHeaderValue.Length > 0)
|
||||
{
|
||||
IPAddress ipFromHeader;
|
||||
int? port;
|
||||
if (IPAddressWithPortParser.TryParse(xForwardedForHeaderValue[0], out ipFromHeader, out port))
|
||||
{
|
||||
var connection = httpContext.Connection;
|
||||
var remoteIPString = connection.RemoteIpAddress?.ToString();
|
||||
if (!string.IsNullOrEmpty(remoteIPString))
|
||||
{
|
||||
httpContext.Request.Headers[XOriginalIPName] = remoteIPString;
|
||||
}
|
||||
if (port.HasValue)
|
||||
{
|
||||
if (connection.RemotePort != 0)
|
||||
{
|
||||
httpContext.Request.Headers[XOriginalPortName] = connection.RemotePort.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
connection.RemotePort = port.Value;
|
||||
}
|
||||
connection.RemoteIpAddress = ipFromHeader;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private WindowsPrincipal UpdateUser(HttpContext httpContext)
|
||||
{
|
||||
var xIISWindowsAuthToken = httpContext.Request.Headers[XIISWindowsAuthToken];
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Net;
|
||||
|
||||
namespace Microsoft.AspNet.IISPlatformHandler
|
||||
{
|
||||
public static class IPAddressWithPortParser
|
||||
{
|
||||
public static bool TryParse(string addressWithPort, out IPAddress address, out int? port)
|
||||
{
|
||||
port = null;
|
||||
|
||||
string addressPart = null;
|
||||
string portPart = null;
|
||||
|
||||
var lastColonIndex = addressWithPort.LastIndexOf(':');
|
||||
if (lastColonIndex > 0)
|
||||
{
|
||||
// IPv4 with port or IPv6
|
||||
var closingIndex = addressWithPort.LastIndexOf(']');
|
||||
if (closingIndex > 0)
|
||||
{
|
||||
// IPv6 with brackets
|
||||
addressPart = addressWithPort.Substring(1, closingIndex - 1);
|
||||
if (closingIndex < lastColonIndex)
|
||||
{
|
||||
// IPv6 with port [::1]:80
|
||||
portPart = addressWithPort.Substring(lastColonIndex + 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// IPv6 without port or IPv4
|
||||
var firstColonIndex = addressWithPort.IndexOf(':');
|
||||
if (firstColonIndex != lastColonIndex)
|
||||
{
|
||||
// IPv6 ::1
|
||||
addressPart = addressWithPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
// IPv4 with port 127.0.0.1:123
|
||||
addressPart = addressWithPort.Substring(0, firstColonIndex);
|
||||
portPart = addressWithPort.Substring(firstColonIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// IPv4 without port
|
||||
addressPart = addressWithPort;
|
||||
}
|
||||
|
||||
var success = IPAddress.TryParse(addressPart, out address);
|
||||
if (success && portPart != null)
|
||||
{
|
||||
int portValue;
|
||||
success &= int.TryParse(portPart, out portValue);
|
||||
if (success)
|
||||
{
|
||||
port = portValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we cannot parse port, reset address
|
||||
address = null;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNet.IISPlatformHandler.FunctionalTests
|
|||
var responseText = await response.Content.ReadAsStringAsync();
|
||||
try
|
||||
{
|
||||
Assert.Equal("https Hello World", responseText);
|
||||
Assert.Equal("Scheme:http; Forwarded:https", responseText);
|
||||
}
|
||||
catch (XunitException)
|
||||
{
|
||||
|
|
@ -138,11 +138,11 @@ namespace Microsoft.AspNet.IISPlatformHandler.FunctionalTests
|
|||
{
|
||||
if (sendClientCert)
|
||||
{
|
||||
Assert.Equal("https Hello World, has cert? True", responseText);
|
||||
Assert.Equal("Scheme:http; Forwarded:https; has cert? True", responseText);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Equal("https Hello World, has cert? False", responseText);
|
||||
Assert.Equal("Scheme:http; Forwarded:https; has cert? False", responseText);
|
||||
}
|
||||
}
|
||||
catch (XunitException)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http.Features.Authentication;
|
||||
using Microsoft.AspNet.Http.Internal;
|
||||
using Microsoft.AspNet.IISPlatformHandler;
|
||||
using Microsoft.AspNet.TestHost;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -15,103 +12,6 @@ namespace Microsoft.AspNet.IISPlatformHandler
|
|||
{
|
||||
public class HttpPlatformHandlerMiddlewareTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task XForwardedForOverrideChangesRemoteIpAndPort()
|
||||
{
|
||||
var assertsExecuted = false;
|
||||
|
||||
var server = TestServer.Create(app =>
|
||||
{
|
||||
app.UseIISPlatformHandler();
|
||||
app.Run(context =>
|
||||
{
|
||||
Assert.Equal("11.111.111.11", context.Connection.RemoteIpAddress.ToString());
|
||||
Assert.Equal(123, context.Connection.RemotePort);
|
||||
assertsExecuted = true;
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
var req = new HttpRequestMessage(HttpMethod.Get, "");
|
||||
req.Headers.Add("X-Forwarded-For", "11.111.111.11:123");
|
||||
await server.CreateClient().SendAsync(req);
|
||||
Assert.True(assertsExecuted);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task XForwardedForStoresOriginalIpAndPort()
|
||||
{
|
||||
var assertsExecuted = false;
|
||||
|
||||
var server = TestServer.Create(app =>
|
||||
{
|
||||
app.Use((context, next) =>
|
||||
{
|
||||
context.Connection.RemoteIpAddress = IPAddress.Loopback;
|
||||
context.Connection.RemotePort = 1;
|
||||
return next();
|
||||
});
|
||||
app.UseIISPlatformHandler();
|
||||
app.Run(context =>
|
||||
{
|
||||
Assert.Equal("127.0.0.1", context.Request.Headers["X-Original-IP"]);
|
||||
Assert.Equal("1", context.Request.Headers["X-Original-Port"]);
|
||||
assertsExecuted = true;
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
var req = new HttpRequestMessage(HttpMethod.Get, "");
|
||||
req.Headers.Add("X-Forwarded-For", "11.111.111.11:123");
|
||||
await server.CreateClient().SendAsync(req);
|
||||
Assert.True(assertsExecuted);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task XForwardedForOverrideBadIpDoesntChangeRemoteIp()
|
||||
{
|
||||
var assertsExecuted = false;
|
||||
|
||||
var server = TestServer.Create(app =>
|
||||
{
|
||||
app.UseIISPlatformHandler();
|
||||
app.Run(context =>
|
||||
{
|
||||
Assert.Null(context.Connection.RemoteIpAddress);
|
||||
Assert.Equal(0, context.Connection.RemotePort);
|
||||
assertsExecuted = true;
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
var req = new HttpRequestMessage(HttpMethod.Get, "");
|
||||
req.Headers.Add("X-Forwarded-For", "BAD-IP");
|
||||
await server.CreateClient().SendAsync(req);
|
||||
Assert.True(assertsExecuted);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task XForwardedProtoOverrideChangesRequestProtocol()
|
||||
{
|
||||
var assertsExecuted = false;
|
||||
|
||||
var server = TestServer.Create(app =>
|
||||
{
|
||||
app.UseIISPlatformHandler();
|
||||
app.Run(context =>
|
||||
{
|
||||
Assert.Equal("TestProtocol", context.Request.Scheme);
|
||||
assertsExecuted = true;
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
|
||||
var req = new HttpRequestMessage(HttpMethod.Get, "");
|
||||
req.Headers.Add("X-Forwarded-Proto", "TestProtocol");
|
||||
await server.CreateClient().SendAsync(req);
|
||||
Assert.True(assertsExecuted);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddsAuthenticationHandlerByDefault()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Net;
|
||||
using Microsoft.AspNet.IISPlatformHandler;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.PipelineHandler.Tests
|
||||
{
|
||||
public class IPAddressWithPortParserTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("127.0.0.1", "127.0.0.1", null)]
|
||||
[InlineData("127.0.0.1:1", "127.0.0.1", 1)]
|
||||
[InlineData("1", "0.0.0.1", null)]
|
||||
[InlineData("1:1", "0.0.0.1", 1)]
|
||||
[InlineData("::1", "::1", null)]
|
||||
[InlineData("[::1]", "::1", null)]
|
||||
[InlineData("[::1]:1", "::1", 1)]
|
||||
public void ParsesCorrectly(string input, string expectedAddress, int? expectedPort)
|
||||
{
|
||||
IPAddress address;
|
||||
int? port;
|
||||
var success = IPAddressWithPortParser.TryParse(input, out address, out port);
|
||||
Assert.True(success);
|
||||
Assert.Equal(expectedAddress, address?.ToString());
|
||||
Assert.Equal(expectedPort, port);
|
||||
}
|
||||
|
||||
[InlineData("[::1]:")]
|
||||
[InlineData("[::1:")]
|
||||
[InlineData("::1:")]
|
||||
[InlineData("127:")]
|
||||
[InlineData("127.0.0.1:")]
|
||||
[InlineData("")]
|
||||
[InlineData("[]")]
|
||||
[InlineData("]")]
|
||||
[InlineData("]:1")]
|
||||
public void ShouldNotParse(string input)
|
||||
{
|
||||
IPAddress address;
|
||||
int? port;
|
||||
var success = IPAddressWithPortParser.TryParse(input, out address, out port);
|
||||
Assert.False(success);
|
||||
Assert.Equal(null, address);
|
||||
Assert.Equal(null, port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,12 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:25334/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
|
|
@ -6,6 +14,12 @@
|
|||
"environmentVariables": {
|
||||
"ASPNET_ENV": "HelloWorld"
|
||||
}
|
||||
},
|
||||
"web": {
|
||||
"commandName": "web",
|
||||
"environmentVariables": {
|
||||
"Hosting:Environment": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,9 +17,10 @@ namespace TestSites
|
|||
{
|
||||
if (ctx.Request.Path.Equals(new PathString("/checkclientcert")))
|
||||
{
|
||||
return ctx.Response.WriteAsync(ctx.Request.Scheme + " Hello World, has cert? " + (ctx.Connection.ClientCertificate != null));
|
||||
return ctx.Response.WriteAsync("Scheme:" + ctx.Request.Scheme + "; Forwarded:" + ctx.Request.Headers["x-forwarded-proto"]
|
||||
+ "; has cert? " + (ctx.Connection.ClientCertificate != null));
|
||||
}
|
||||
return ctx.Response.WriteAsync(ctx.Request.Scheme + " Hello World");
|
||||
return ctx.Response.WriteAsync("Scheme:" + ctx.Request.Scheme + "; Forwarded:" + ctx.Request.Headers["x-forwarded-proto"]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ namespace TestSites
|
|||
{
|
||||
loggerFactory.AddConsole();
|
||||
|
||||
// Simple error page without depending on Diagnostics.
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
try
|
||||
|
|
@ -66,7 +67,7 @@ namespace TestSites
|
|||
|
||||
if (context.Request.Path.Equals("/RestrictedNegotiate"))
|
||||
{
|
||||
if (string.Equals("Negotiate", context.User.Identity.AuthenticationType, System.StringComparison.Ordinal))
|
||||
if (string.Equals("Negotiate", context.User.Identity.AuthenticationType, StringComparison.Ordinal))
|
||||
{
|
||||
return context.Response.WriteAsync("Negotiate");
|
||||
}
|
||||
|
|
@ -78,7 +79,7 @@ namespace TestSites
|
|||
|
||||
if (context.Request.Path.Equals("/RestrictedNTLM"))
|
||||
{
|
||||
if (string.Equals("NTLM", context.User.Identity.AuthenticationType, System.StringComparison.Ordinal))
|
||||
if (string.Equals("NTLM", context.User.Identity.AuthenticationType, StringComparison.Ordinal))
|
||||
{
|
||||
return context.Response.WriteAsync("NTLM");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue