2015-08-27 9 views
6

Per un controllo di sicurezza, è necessario accedere all'indirizzo IP remoto dell'utente nel servizio risorse. Questo servizio risorsa è una recente applicazione Primavera Boot semplice, che si registra con il mio server Eureka:Accedere all'indirizzo IP remoto nel server di risorse inviato tramite Zuul e Apache

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

Tutti i servizi registrati con il mio server Eureka vengono indirizzati in modo dinamico attraverso il mio Zuul server proxy di routing basato su Angel.SR3 starter-zuul e starter-eureka :

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

il server proxy di routing Zuul configura anche un connettore AJP per il passo successivo:

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

Tutte le richieste alla dinamica delega Zuul di routing si stanno proxied attraverso Apache per fornire HTTPS sulla 443 porta standard:

# 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/ 

Con tutto questo in luogo del servizio risorsa è reso disponibile, ma purtroppo la RemoteAddress che ottengo da Spring Security è l'indirizzo del proxy Zuul/server Apache, non l'indirizzo IP del client remoto.

In passato avevo usato un org.springframework.security.authentication.AuthenticationDetailsSource che preferiva il valore X-Forwarded-For intestazione sopra il normale remoteAddress per ottenere l'indirizzo IP corretto, ma non riesco a capire come passare il corretto indirizzo IP remoto al mio servizio risorsa quando passa attraverso due proxy (Apache + Zuul).

Qualcuno può aiutarmi ad accedere all'indirizzo IP remoto corretto dietro a questi due proxy o suggerire un approccio alternativo per farlo funzionare?

risposta

4

Risulta l'intestazione X-Forwarded-For stata ricavata dalla richiesta originale alimentando Zuul per popolare HttpServletRequest#getRemoteAddr(). Ciò dovrebbe quindi essere trasferito ai servizi di back-end proxy attraverso RequestContext#getZuulRequestHeaders().put("X-Forwarded-For", remoteAddr). Il seguente numero ZuulFilter ottiene ciò, anche se non aggiunge ancora il proprio valore al filtro 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; 
} 
} 

si volesse cancellare il valore di intestazione in Apache prima di proxy per Zuul per evitare di accettare un qualsiasi valore fornito dall'utente: RequestHeader unset X-Forwarded-For

+0

Risolto in https://github.com/spring-cloud/spring-cloud-netflix/pull/952 – Tim

1

In genere, è possibile utilizzare servletRequest.getRemoteAddr() per ottenere l'indirizzo IP del client che accede all'applicazione Web Java.

String ipAddress = request.getRemoteAddr(); 

Ma, se l'utente si trova dietro un server proxy o accedere al server web attraverso un bilanciamento del carico (ad esempio, in cloud hosting), il codice sopra riceverà l'indirizzo IP del server proxy server o di bilanciamento del carico , non l'indirizzo IP originale di un client.

Per risolvere il problema, è necessario ottenere l'indirizzo IP dell'intestazione HTTP della richiesta "X-Forwarded-For (XFF)".

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

Questo è quello che ho fatto prima ho aggiunto Zuul, ma questo approccio non è più lavori. Le intestazioni non vengono passate e/o ottengo l'indirizzo del server proxy. Vedere il penultimo paragrafo. – Tim

Problemi correlati