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" })); }