continuous-integration/drone/pr Build is passing
Один LoginGuard на все проверки пароля (SMTP AUTH, IMAP LOGIN/AUTHENTICATE, вход в веб, смена пароля): 10 неверных с IP за 15 мин → блок 15 мин, дальше вдвое дольше до суток; 20 неверных на ящик с разных IP → ящик закрыт, кроме IP, с которых в него уже входили. Во время блока пароль не проверяется (SMTP 421, IMAP BYE + NO [UNAVAILABLE], веб 429 + Retry-After); неверный пароль — ответ через 1 с; 3 неверных в соединении — обрыв. X-Forwarded-For веб-входа — только от прокси в частной сети, иначе заголовок отбрасывается (подменой IP лимит не обойти). Попутно: IMAP терял тегированный ответ после "* BYE" (LOGOUT, обрыв после неудачных входов) — takeUntil теперь после тегированной строки. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
47 lines
1.9 KiB
Java
47 lines
1.9 KiB
Java
package com.mailserver.config;
|
|
|
|
import org.junit.jupiter.api.Test;
|
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
|
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
|
|
|
import java.net.InetSocketAddress;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
class LoginGuardConfigTest {
|
|
|
|
private final LoginGuardConfig.TrustedProxyHeaderTransformer transformer = new LoginGuardConfig.TrustedProxyHeaderTransformer();
|
|
|
|
private ServerHttpRequest from(String peer) {
|
|
return MockServerHttpRequest.post("/api/login")
|
|
.remoteAddress(new InetSocketAddress(peer, 40000))
|
|
.header("X-Forwarded-For", "198.51.100.9")
|
|
.header("X-Forwarded-Proto", "https")
|
|
.build();
|
|
}
|
|
|
|
@Test
|
|
void forwardedForIsBelievedFromAPrivateProxy() {
|
|
ServerHttpRequest request = transformer.apply(from("172.18.0.5"));
|
|
assertThat(request.getRemoteAddress().getHostString()).isEqualTo("198.51.100.9");
|
|
assertThat(request.getURI().getScheme()).isEqualTo("https");
|
|
}
|
|
|
|
@Test
|
|
void forwardedForFromTheInternetIsDropped() {
|
|
ServerHttpRequest request = transformer.apply(from("203.0.113.7"));
|
|
assertThat(request.getRemoteAddress().getAddress().getHostAddress()).isEqualTo("203.0.113.7");
|
|
assertThat(request.getHeaders().containsKey("X-Forwarded-For")).isFalse();
|
|
}
|
|
|
|
@Test
|
|
void privateRanges() {
|
|
for (String ip : new String[]{"127.0.0.1", "10.30.0.13", "172.16.0.1", "192.168.1.1", "fd00::1", "::1", "fe80::1"}) {
|
|
assertThat(LoginGuardConfig.privatePeer(new InetSocketAddress(ip, 1))).as(ip).isTrue();
|
|
}
|
|
for (String ip : new String[]{"103.109.235.154", "172.32.0.1", "2001:db8::1", "8.8.8.8"}) {
|
|
assertThat(LoginGuardConfig.privatePeer(new InetSocketAddress(ip, 1))).as(ip).isFalse();
|
|
}
|
|
}
|
|
}
|