Skip to content

Gracefully handle IPv6 not fully respecting RFC7239 #2512

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gabac opened this issue Feb 7, 2022 · 5 comments
Closed

Gracefully handle IPv6 not fully respecting RFC7239 #2512

gabac opened this issue Feb 7, 2022 · 5 comments

Comments

@gabac
Copy link

gabac commented Feb 7, 2022

Describe the bug
Google Cloud Run is not fully respecting the RFC7239 for their IPv6.
This has also been mentioned here:
https://issuetracker.google.com/issues/184230536?pli=1

The error message which is throw looks like this. The IP address in the header attribute Forwarded: for= has no [ and ].

I know this is an Google Cloud Run issue but could Spring handle this more gracefully?

java.lang.IllegalArgumentException: Invalid IPv4 address: 2001:1715:4e23:a370:a1d3:c50d:5862:9aeb
	at org.springframework.web.util.UriComponentsBuilder.parseForwardedFor(UriComponentsBuilder.java:363)
	at org.springframework.web.server.adapter.ForwardedHeaderTransformer.apply(ForwardedHeaderTransformer.java:111)
	at org.springframework.web.server.adapter.HttpWebHandlerAdapter.handle(HttpWebHandlerAdapter.java:232)
	at org.springframework.boot.web.reactive.context.WebServerManager$DelayedInitializationHttpHandler.handle(WebServerManager.java:98)
	at org.springframework.http.server.reactive.ReactorHttpHandlerAdapter.apply(ReactorHttpHandlerAdapter.java:65)
	at org.springframework.http.server.reactive.ReactorHttpHandlerAdapter.apply(ReactorHttpHandlerAdapter.java:40)
	at reactor.netty.http.server.HttpServer$HttpServerHandle.onStateChange(HttpServer.java:934)
	at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:671)
	at reactor.netty.transport.ServerTransport$ChildObserver.onStateChange(ServerTransport.java:478)
	at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:559)
	at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:93)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:217)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:311)
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:432)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795)
	at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480)
	at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Unknown Source)

Workaround
Remove the corresponding header attributes with a filter

       @Bean
	public ForwardedHeaderTransformer forwardedHeaderTransformer() {
		ForwardedHeaderTransformer transformer = new ForwardedHeaderTransformer();
		transformer.setRemoveOnly(true);
		return transformer;
	}

Sample
Any request to a Spring Cloud Gateway with an invalid IPv6 results in an error.

@jpd1
Copy link

jpd1 commented Feb 18, 2022

To add a note, we had this same problem with an IPv6 address without square brackets, and used the suggested workaround. I think we may need to consider handling this more gracefully. I suspect this is going to be more frequent as more users move over to IPv6 and more vendors not following the RFC7239 standard.

@spencergibb
Copy link
Member

I don't understand how this is a gateway issue when framework rejected it as well. I think the noted work around (which is from framework, not gateway) is how to deal with this.

@Illutax
Copy link

Illutax commented Mar 2, 2022

@spencergibb we encountered this issue as well although we don't use spring-cloud--gateway.
I'll report here if we find more Information on this.

@spencergibb
Copy link
Member

@Illutax if you don't use spring-cloud-gateway, what is the point of commenting here was there is nothing specific to gateway? If you are using framework, comment on the issue linked above.

@jpd1
Copy link

jpd1 commented Mar 3, 2022

Adding a note as the information within this issue may help others if they come across this issue.

I think @spencergibb is right to close this ticket as I don't think this is the responsibility of Spring Cloud Gateway or the Spring framework.

The correct resolution is to go back to the gateway that is providing the IPv6 traffic and ask them to comply with RFC7239.

However, this can be challenging as we're seeing more and more mobile traffic that is not compliant, difficult to identify who should be contacted and whether they show interest in addressing the issue.

This has an impact on users, thus SCG can be used to mitigate the issue with the suggested workaround but is not the ideal long-term fix.

If you know your downstream does not need the forward header, an alternative is to use the following configuration however this is at your own risk.

spring:
  cloud:
      forwarded:
        enabled: false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants