using System.Net;
using Microsoft.AspNetCore.Http;
using MoShiro.Backend.Api;
using MoShiro.Backend.Application;
namespace MoShiro.Backend.Tests;
/// 真实来源地址:只有从可信代理连进来的请求才采信转发头,而且取最右边第一个不可信的地址。
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(() => new ClientAddressResolver(new BackendOptions { TrustedProxies = "banana" }));
}