60 lines
2.5 KiB
C#
60 lines
2.5 KiB
C#
using System.Net;
|
|
using Microsoft.AspNetCore.Http;
|
|
using MoShiro.Backend.Api;
|
|
using MoShiro.Backend.Application;
|
|
|
|
namespace MoShiro.Backend.Tests;
|
|
|
|
/// <summary>真实来源地址:只有从可信代理连进来的请求才采信转发头,而且取最右边第一个不可信的地址。</summary>
|
|
public sealed class ClientAddressTests
|
|
{
|
|
private static string Resolve(string? trusted, string remote, string? forwarded, string? header = null)
|
|
{
|
|
var resolver = new ClientAddressResolver(new BackendOptions { TrustedProxies = trusted, TrustedProxyHeader = header });
|
|
var http = new DefaultHttpContext();
|
|
http.Connection.RemoteIpAddress = IPAddress.Parse(remote);
|
|
if (forwarded is not null)
|
|
{
|
|
http.Request.Headers[header ?? "X-Forwarded-For"] = forwarded;
|
|
}
|
|
|
|
return resolver.Resolve(http);
|
|
}
|
|
|
|
[Fact]
|
|
public void WithoutTrustedProxies_TheSocketAddressIsUsed_AndTheHeaderIsIgnored() =>
|
|
Assert.Equal("203.0.113.9", Resolve(null, "203.0.113.9", "1.2.3.4"));
|
|
|
|
[Fact]
|
|
public void FromATrustedProxy_TheForwardedClientIsUsed() =>
|
|
Assert.Equal("198.51.100.7", Resolve("10.0.0.0/8", "10.1.2.3", "198.51.100.7"));
|
|
|
|
[Fact]
|
|
public void FromAnUntrustedPeer_TheHeaderIsIgnored() =>
|
|
Assert.Equal("203.0.113.9", Resolve("10.0.0.0/8", "203.0.113.9", "1.2.3.4"));
|
|
|
|
[Fact]
|
|
public void TheChainIsWalkedFromTheRight_SoAClientCannotForgeItsAddress() =>
|
|
Assert.Equal("198.51.100.7", Resolve("10.0.0.0/8,127.0.0.1", "10.1.2.3", "6.6.6.6, 198.51.100.7, 10.9.9.9"));
|
|
|
|
[Fact]
|
|
public void AGarbageHeader_FallsBackToTheSocketAddress() =>
|
|
Assert.Equal("10.1.2.3", Resolve("10.0.0.0/8", "10.1.2.3", "not-an-ip"));
|
|
|
|
[Fact]
|
|
public void ASingleAddressAndACustomHeaderWork() =>
|
|
Assert.Equal("198.51.100.7", Resolve("127.0.0.1", "127.0.0.1", "198.51.100.7", "CF-Connecting-IP"));
|
|
|
|
[Fact]
|
|
public void AMalformedTrustedProxyEntry_FailsAtStartup() =>
|
|
Assert.Throws<InvalidOperationException>(() => new ClientAddressResolver(new BackendOptions { TrustedProxies = "banana" }));
|
|
|
|
[Fact]
|
|
public void TheFleetLinkAsksTheSameResolver_SoANodeBehindAProxyKeepsItsRealAddress()
|
|
{
|
|
Fleet.Server.IClientAddressSource source = new ClientAddressResolver(new BackendOptions { TrustedProxies = "127.0.0.1" });
|
|
Assert.Equal("198.51.100.7", source.Resolve(IPAddress.Parse("127.0.0.1"), _ => ["198.51.100.7"]));
|
|
Assert.Equal("203.0.113.9", source.Resolve(IPAddress.Parse("203.0.113.9"), _ => ["198.51.100.7"]));
|
|
}
|
|
}
|