summaryrefslogtreecommitdiff
path: root/source/net
diff options
context:
space:
mode:
authorMichael Peter Christen <mc@yacy.net>2026-07-12 17:16:24 +0200
committerMichael Peter Christen <mc@yacy.net>2026-07-12 17:16:24 +0200
commitece7985d9435843989c36395c6dd2db2f0b9e933 (patch)
treeb54c2eb1f273a4c716470b5aa90ab67b83b35a4b /source/net
parent92e0b111a0ce98964e4de3600d1a81643313ed7e (diff)
proper IP recognition using header X-Real-IP when YaCy is behind a
reverse proxy
Diffstat (limited to 'source/net')
-rw-r--r--source/net/yacy/http/Jetty12HttpServer.java26
-rw-r--r--source/net/yacy/search/SwitchboardConstants.java4
2 files changed, 27 insertions, 3 deletions
diff --git a/source/net/yacy/http/Jetty12HttpServer.java b/source/net/yacy/http/Jetty12HttpServer.java
index f38a1a8d0..cc72eab49 100644
--- a/source/net/yacy/http/Jetty12HttpServer.java
+++ b/source/net/yacy/http/Jetty12HttpServer.java
@@ -65,6 +65,8 @@ import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.security.Credential;
import org.eclipse.jetty.util.ssl.SslContextFactory;
+import com.google.common.net.InetAddresses;
+
import net.yacy.cora.protocol.ConnectionInfo;
import net.yacy.cora.protocol.RequestHeader;
import net.yacy.cora.util.ConcurrentLog;
@@ -490,8 +492,11 @@ public class Jetty12HttpServer implements YaCyHttpServer {
protected RoleInfo prepareConstraintInfo(final String pathInContext,
final org.eclipse.jetty.ee8.nested.Request request) {
final Switchboard switchboard = Switchboard.getSwitchboard();
- final String remoteIp = request.getRemoteAddr();
- serverAccessTracker.track(remoteIp, pathInContext);
+ final String socketRemoteIp = request.getRemoteAddr();
+ final String trackingRemoteIp = resolveTrackingClientIp(request,
+ switchboard.getConfig(SwitchboardConstants.SERVER_REVERSE_PROXY_TRUSTED,
+ SwitchboardConstants.SERVER_REVERSE_PROXY_TRUSTED_DEFAULT));
+ serverAccessTracker.track(trackingRemoteIp, pathInContext);
final AdminSecurity.AccessPolicy policy = new AdminSecurity.AccessPolicy(
switchboard.getConfigBool(SwitchboardConstants.ADMIN_ACCOUNT_All_PAGES, false),
switchboard.isRobinsonMode() && !switchboard.isPublicRobinson(),
@@ -499,7 +504,7 @@ public class Jetty12HttpServer implements YaCyHttpServer {
switchboard.getConfigBool(SwitchboardConstants.ADMIN_ACCOUNT_FOR_LOCALHOST, false),
switchboard.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin"),
switchboard.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_B64MD5, ""));
- final AdminSecurity.AccessPolicy.Decision decision = policy.decide(pathInContext, remoteIp,
+ final AdminSecurity.AccessPolicy.Decision decision = policy.decide(pathInContext, socketRemoteIp,
request.getHeader(RequestHeader.REFERER),
request.getHeader(RequestHeader.AUTHORIZATION));
if (decision == AdminSecurity.AccessPolicy.Decision.PUBLIC) {
@@ -513,6 +518,21 @@ public class Jetty12HttpServer implements YaCyHttpServer {
roleInfo.addRole(SwitchboardConstants.ADMIN_ACCOUNT_ROLE);
return roleInfo;
}
+
+ /** Resolve the client address for display and tracking, never for access control. */
+ static String resolveTrackingClientIp(final HttpServletRequest request,
+ final String trustedProxyPatterns) {
+ final String socketRemoteIp = request.getRemoteAddr();
+ if (!ProxyAccessPolicy.isClientAllowed(trustedProxyPatterns, socketRemoteIp)) {
+ return socketRemoteIp;
+ }
+ final String forwardedRemoteIp = request.getHeader(RequestHeader.X_Real_IP);
+ if (forwardedRemoteIp == null) {
+ return socketRemoteIp;
+ }
+ final String candidate = forwardedRemoteIp.trim();
+ return InetAddresses.isInetAddress(candidate) ? candidate : socketRemoteIp;
+ }
}
/** Jetty 12 login-service adapter for YaCy's single built-in administrator. */
diff --git a/source/net/yacy/search/SwitchboardConstants.java b/source/net/yacy/search/SwitchboardConstants.java
index 8692c2759..405fbcab8 100644
--- a/source/net/yacy/search/SwitchboardConstants.java
+++ b/source/net/yacy/search/SwitchboardConstants.java
@@ -66,6 +66,10 @@ public final class SwitchboardConstants {
public static final String SERVER_SHUTDOWNPORT = "port.shutdown"; // local port to listen for a shutdown signal (0 <= disabled)
public static final String SERVER_STATICIP = "staticIP"; // static IP of http server
public static final String SERVER_PUBLICPORT = "publicPort";
+ /** Socket peers whose X-Real-IP header may be used for request tracking. */
+ public static final String SERVER_REVERSE_PROXY_TRUSTED = "server.reverseProxy.trusted";
+ public static final String SERVER_REVERSE_PROXY_TRUSTED_DEFAULT =
+ "127[.]0[.]0[.]1,0:0:0:0:0:0:0:1,::1";
public static final String PUBLIC_SEARCHPAGE = "publicSearchpage";