У меня есть приложение Spring Webflux, которое развернуто в Digital Ocean Kubernetes с включенным прокси-протоколом, потому что приложение должно получить доступ к IP-адресу клиента.
Вот описания ресурсов Kubernetes:
---
apiVersion: v1
kind: Service
metadata:
name: myapp-loadbalancer
annotations:
service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"
spec:
type: LoadBalancer
selector:
app: myapp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: ipregistry-api
spec:
replicas: 1
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp/myapp:1553679009241
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
successThreshold: 1
imagePullSecrets:
- name: regcred
Развертывание прекрасно работает. К сожалению, когда я выполняю запрос GET к любой конечной точке приложения, я получаю ответ HTTP 400.
Просматривая журналы, я заметил, что Spring Webflux и используемая библиотека Netty не анализируют запрос должным образом, когда включен прокси-протокол.
Обратите внимание, что если прокси-протокол отключен путем установки service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol
на false
, то все работает, но я не могу получить реальный IP-адрес клиента.
Вот ошибка, которую я получаю в журналах при включенной отладке:
2019-03-27 09:33:45.916 DEBUG 1 --- [or-http-epoll-1] r.n.http.server.HttpServerOperations : [id: 0x3c2ee440, L:/10.244.2.230:8080 - R:/10.131.95.63:27204] New http connection, requesting read 2019-03-27 09:33:45.916 DEBUG 1 --- [or-http-epoll-1] reactor.netty.channel.BootstrapHandlers : [id: 0x3c2ee440, L:/10.244.2.230:8080 - R:/10.131.95.63:27204] Initialized pipeline DefaultChannelPipeline{(BootstrapHandlers$BootstrapInitializerHandler#0
= reactor.netty.channel.BootstrapHandlers$BootstrapInitializerHandler), (reactor.left.httpCodec = io.netty.handler.codec.http.HttpServerCodec), (reactor.left.httpTrafficHandler = reactor.netty.http.server.HttpTrafficHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)} 2019-03-27 09:33:45.917 DEBUG 1 --- [or-http-epoll-1] r.n.http.server.HttpServerOperations : [id: 0x3c2ee440, L:/10.244.2.230:8080 - R:/10.131.95.63:27204] Decoding failed: DefaultFullHttpRequest(decodeResult: failure(java.lang.IllegalArgumentException: invalid version format:
83.252.136.179 10.16.5.223 3379 80), version: HTTP/1.0, content: UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeHeapByteBuf(ridx: 0, widx: 0, cap: 0)) GET /bad-request HTTP/1.0 :
java.lang.IllegalArgumentException: invalid version format:
83.252.136.179 10.16.5.223 3379 80 at io.netty.handler.codec.http.HttpVersion.<init>(HttpVersion.java:121) ~[netty-codec-http-4.1.33.Final.jar:4.1.33.Final] at io.netty.handler.codec.http.HttpVersion.valueOf(HttpVersion.java:76) ~[netty-codec-http-4.1.33.Final.jar:4.1.33.Final] at io.netty.handler.codec.http.HttpRequestDecoder.createMessage(HttpRequestDecoder.java:87) ~[netty-codec-http-4.1.33.Final.jar:4.1.33.Final] at io.netty.handler.codec.http.HttpObjectDecoder.decode(HttpObjectDecoder.java:219) ~[netty-codec-http-4.1.33.Final.jar:4.1.33.Final] at io.netty.handler.codec.http.HttpServerCodec$HttpServerRequestDecoder.decode(HttpServerCodec.java:101) ~[netty-codec-http-4.1.33.Final.jar:4.1.33.Final] at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:502) ~[netty-codec-4.1.33.Final.jar:4.1.33.Final] at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:441) ~[netty-codec-4.1.33.Final.jar:4.1.33.Final] at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:278) ~[netty-codec-4.1.33.Final.jar:4.1.33.Final] at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final] at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final] at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:799) ~[netty-transport-native-epoll-4.1.33.Final-linux-x86_64.jar:4.1.33.Final] at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:427) ~[netty-transport-native-epoll-4.1.33.Final-linux-x86_64.jar:4.1.33.Final] at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:328) ~[netty-transport-native-epoll-4.1.33.Final-linux-x86_64.jar:4.1.33.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:905) ~[netty-common-4.1.33.Final.jar:4.1.33.Final] at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Я пытался использовать свойство server.use-forward-headers=true
в свойствах своего приложения, но оно не действует.
Есть ли способ поддержки Proxy Protocol с помощью Spring Webflux? Как действовать? Пример очень поможет.