【问题标题】:Access remote IP address in resource server proxied through Zuul and Apache通过 Zuul 和 Apache 访问资源服务器中的远程 IP 地址
【发布时间】:2015-11-22 08:36:00
【问题描述】:

为了进行安全检查,我需要在我的资源服务中访问用户的远程 IP 地址。这个资源服务是一个简单的最近的 Spring Boot 应用程序,它在我的 Eureka 服务器上注册了自己:

@SpringBootApplication
@EnableEurekaClient
public class ServletInitializer extends SpringBootServletInitializer {
    public static void main(final String[] args) {
        SpringApplication.run(ServletInitializer.class, args);
    }
}

在我的 Eureka 服务器上注册的所有服务都是通过我的基于 Angel.SR3 starter-zuulstarter-eureka 的 Zuul 路由代理服务器动态路由的:

@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
public class RoutingProxyServer {
    public static void main(final String[] args) {
        SpringApplication.run(RoutingProxyServer.class, args);
    }
}

Zuul 路由代理服务器还为下一步配置了一个 AJP 连接器:

@Configuration
@ConditionalOnProperty("ajp.port")
public class TomcatAjpConfig extends TomcatWebSocketContainerCustomizer {
    @Value("${ajp.port}")
    private int port;

    @Override
    public void doCustomize(final TomcatEmbeddedServletContainerFactory tomcat) {
        super.doCustomize(tomcat);

        // Listen for AJP requests
        Connector ajp = new Connector("AJP/1.3");
        ajp.setPort(port);
        tomcat.addAdditionalTomcatConnectors(ajp);
    }
}

对动态路由zuul代理的所有请求都通过Apache自己代理,在标准443端口上提供HTTPS:

# Preserve Host when proxying so jar apps return working URLs in JSON responses
RequestHeader           set X-Forwarded-Proto "https"
ProxyPreserveHost   On
# Redirect remaining traffic to routing proxy server
ProxyPass       /       ajp://192.168.x.x:8009/
# Also update Location, Content-Location and URI headers on HTTP redirect responses
ProxyPassReverse    /       ajp://192.168.x.x:8009/

所有这些都到位后,资源服务就可用了,但不幸的是,我从 Spring Security 获得的 remoteAddress 是 Zuul 代理/Apache 服务器的地址,而不是远程客户端 IP 地址。

在过去,我使用org.springframework.security.authentication.AuthenticationDetailsSource 比普通的remoteAddress 更喜欢X-Forwarded-For 标头值来获取正确的IP 地址,但我不知道如何将正确的远程IP 地址传递给我的通过两个代理(Apache + Zuul)时的资源服务。

谁能帮我访问这两个代理背后的正确远程 IP 地址,或者建议一种替代方法来让它工作?

【问题讨论】:

    标签: apache spring-security spring-cloud netflix-zuul


    【解决方案1】:

    通常,您可以使用 servletRequest.getRemoteAddr() 来获取访问 Java Web 应用程序的客户端 IP 地址。

    String ipAddress = request.getRemoteAddr();  
    

    但是,如果用户在代理服务器后面或通过负载均衡器访问您的网络服务器(例如,在云托管中),上述代码将获取代理服务器或负载均衡器服务器的 IP 地址,而不是原始的客户端的 IP 地址。

    要解决这个问题,您应该获取请求的 HTTP 标头“X-Forwarded-For (XFF)”的 IP 地址。

       String ipAddress = request.getHeader("X-FORWARDED-FOR");  
       if (ipAddress == null) {  
           ipAddress = request.getRemoteAddr();  
       }
    

    【讨论】:

    • 这就是我在添加 Zuul 之前所做的,但这种方法不再有效。标头未通过和/或我获得代理服务器地址。见倒数第二段。
    【解决方案2】:

    原来 X-Forwarded-For 标头取自原始请求,输入 Zuul 以填充 HttpServletRequest#getRemoteAddr()。然后必须通过RequestContext#getZuulRequestHeaders().put("X-Forwarded-For", remoteAddr) 将其传递给代理后端服务。下面的 ZuulFilter 完成了这一点,即使它还没有将自己的值附加到 X-Forwarded-For 过滤器。

    @Component
    @Slf4j
    public class XForwardedForFilter extends ZuulFilter {
    private static final String X_FORWARDED_FOR = "X-Forwarded-For";
    
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
    
        // Rely on HttpServletRequest to retrieve the correct remote address from upstream X-Forwarded-For header
        HttpServletRequest request = ctx.getRequest();
        String remoteAddr = request.getRemoteAddr();
    
        // Pass remote address downstream by setting X-Forwarded for header again on Zuul request
        log.debug("Settings X-Forwarded-For to: {}", remoteAddr);
        ctx.getZuulRequestHeaders().put(X_FORWARDED_FOR, remoteAddr);
    
        return null;
    }
    
    @Override
    public boolean shouldFilter() {
        return true;
    }
    
    @Override
    public String filterType() {
        return "pre";
    }
    
    @Override
    public int filterOrder() {
        return 10000;
    }
    }
    

    可能希望在代理到 Zuul 之前清除 Apache 中的标头值,以防止仅接受用户提供的任何值:RequestHeader unset X-Forwarded-For

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-02
      • 2019-12-30
      • 1970-01-01
      • 2019-01-12
      • 1970-01-01
      • 2017-06-16
      • 1970-01-01
      相关资源
      最近更新 更多