mirror of
https://gitlab.com/mangadex-pub/mangadex_at_home.git
synced 2024-01-19 02:48:37 +00:00
Hides proxy protocol support behind a settings toggle and adds some implementation comments.
This commit is contained in:
parent
ecab240817
commit
610300c2e4
|
@ -80,3 +80,10 @@ server_settings:
|
|||
# 0 defaults to (2 * your available processors)
|
||||
# https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Runtime.html#availableProcessors()
|
||||
threads: 0
|
||||
# Whether to enable support for HAProxy Proxy Protocol
|
||||
# If using a reverse proxy to forward requests to MD@H via
|
||||
# ssl passthrough, you can use Proxy Protocol to preserve
|
||||
# original IP if your reverse proxy supports it. This
|
||||
# will allow geo location metrics to work correctly.
|
||||
# https://www.haproxy.com/blog/haproxy/proxy-protocol/
|
||||
enable_proxy_protocol: false
|
||||
|
|
|
@ -184,29 +184,35 @@ class Netty(
|
|||
.childHandler(object : ChannelInitializer<SocketChannel>() {
|
||||
val HAPROXY_SOURCE = AttributeKey.newInstance<String>("haproxy_source")
|
||||
public override fun initChannel(ch: SocketChannel) {
|
||||
ch.pipeline().addLast(
|
||||
"proxyProtocol",
|
||||
object : ChannelInboundHandlerAdapter() {
|
||||
override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {
|
||||
if (msg is ByteBuf) {
|
||||
val result: ProtocolDetectionResult<HAProxyProtocolVersion> = HAProxyMessageDecoder.detectProtocol(msg)
|
||||
if (result.state() == ProtocolDetectionState.DETECTED) {
|
||||
ctx.pipeline().addAfter("proxyProtocol", null, HAProxyMessageDecoder())
|
||||
ctx.pipeline().remove(this)
|
||||
if (serverSettings.enableProxyProtocol) {
|
||||
ch.pipeline().addLast(
|
||||
"proxyProtocol",
|
||||
object : ChannelInboundHandlerAdapter() {
|
||||
override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {
|
||||
if (msg is ByteBuf) {
|
||||
// Since the builtin `HAProxyMessageDecoder` will break non Proxy Protocol requests
|
||||
// we need to use its detection capabilities to only add it when needed.
|
||||
val result: ProtocolDetectionResult<HAProxyProtocolVersion> = HAProxyMessageDecoder.detectProtocol(msg)
|
||||
if (result.state() == ProtocolDetectionState.DETECTED) {
|
||||
ctx.pipeline().addAfter("proxyProtocol", null, HAProxyMessageDecoder())
|
||||
ctx.pipeline().remove(this)
|
||||
}
|
||||
}
|
||||
super.channelRead(ctx, msg)
|
||||
}
|
||||
super.channelRead(ctx, msg)
|
||||
}
|
||||
}
|
||||
)
|
||||
ch.pipeline().addLast(
|
||||
"saveOriginalIp",
|
||||
object : SimpleChannelInboundHandler<HAProxyMessage>() {
|
||||
override fun channelRead0(ctx: ChannelHandlerContext, msg: HAProxyMessage) {
|
||||
(ctx as AttributeMap).attr(HAPROXY_SOURCE).set(msg.sourceAddress())
|
||||
)
|
||||
ch.pipeline().addLast(
|
||||
"saveOriginalIp",
|
||||
object : SimpleChannelInboundHandler<HAProxyMessage>() {
|
||||
override fun channelRead0(ctx: ChannelHandlerContext, msg: HAProxyMessage) {
|
||||
// Store proxy IP in an attribute for later use after HTTP request is extracted.
|
||||
// Using an attribute ensures the value is scoped to this channel.
|
||||
(ctx as AttributeMap).attr(HAPROXY_SOURCE).set(msg.sourceAddress())
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
ch.pipeline().addLast(
|
||||
"ssl",
|
||||
SniHandler(DomainWildcardMappingBuilder(sslContext).build())
|
||||
|
@ -239,19 +245,25 @@ class Netty(
|
|||
ch.pipeline().addLast("keepAlive", HttpServerKeepAliveHandler())
|
||||
ch.pipeline().addLast("aggregator", HttpObjectAggregator(65536))
|
||||
|
||||
ch.pipeline().addLast(
|
||||
"setForwardHeader",
|
||||
object : SimpleChannelInboundHandler<FullHttpRequest>(false) {
|
||||
override fun channelRead0(ctx: ChannelHandlerContext, request: FullHttpRequest) {
|
||||
if ((ctx as AttributeMap).hasAttr(HAPROXY_SOURCE)) {
|
||||
val addr = (ctx as AttributeMap).attr(HAPROXY_SOURCE).get()
|
||||
request.headers().set("Forwarded", addr)
|
||||
if (serverSettings.enableProxyProtocol) {
|
||||
ch.pipeline().addLast(
|
||||
"setForwardHeader",
|
||||
object : SimpleChannelInboundHandler<FullHttpRequest>(false) {
|
||||
override fun channelRead0(ctx: ChannelHandlerContext, request: FullHttpRequest) {
|
||||
// The geo location code already supports the `Forwarded header so setting
|
||||
// it is the easiest way to introduce the original IP downstream.
|
||||
if ((ctx as AttributeMap).hasAttr(HAPROXY_SOURCE)) {
|
||||
val addr = (ctx as AttributeMap).attr(HAPROXY_SOURCE).get()
|
||||
request.headers().set("Forwarded", addr)
|
||||
}
|
||||
// Since we're modifying the request without handling it, we must
|
||||
// call retain to ensure it will still be available downstream.
|
||||
ReferenceCountUtil.retain(request)
|
||||
ctx.fireChannelRead(request)
|
||||
}
|
||||
ReferenceCountUtil.retain(request)
|
||||
ctx.fireChannelRead(request)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
ch.pipeline().addLast("burstLimiter", burstLimiter)
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ data class ServerSettings(
|
|||
val externalIp: String? = null,
|
||||
val port: Int = 443,
|
||||
val threads: Int = 0,
|
||||
val enableProxyProtocol: Boolean = false,
|
||||
)
|
||||
|
||||
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class)
|
||||
|
|
Loading…
Reference in a new issue