GeyserMC / Geyser

A bridge/proxy allowing you to connect to Minecraft: Java Edition servers with Minecraft: Bedrock Edition.
https://geysermc.org
MIT License
4.71k stars 675 forks source link

Geyser select wrong destination IP address family type when forwarding IP information #4244

Open BadAimWeeb opened 11 months ago

BadAimWeeb commented 11 months ago

Describe the bug

When connecting to proxy server (with PROXY protocol support enabled for both ends - use-proxy-protocol: true and enable-proxy-protocol: true), Geyser selected wrong address to set as destination address (in this case source IP is IPv6 but Geyser tried to set destination IP as IPv4).

[07:31:36 ERROR]: java.lang.IllegalArgumentException: invalid IPv6 address: 172.19.0.2
[07:31:36 ERROR]:       at io.netty.handler.codec.haproxy.HAProxyMessage.checkAddress(HAProxyMessage.java:455)
[07:31:36 ERROR]:       at io.netty.handler.codec.haproxy.HAProxyMessage.<init>(HAProxyMessage.java:105)
[07:31:36 ERROR]:       at io.netty.handler.codec.haproxy.HAProxyMessage.<init>(HAProxyMessage.java:79)
[07:31:36 ERROR]:       at org.geysermc.geyser.network.netty.LocalSession$2.channelActive(LocalSession.java:133)
[07:31:36 ERROR]:       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:262)
[07:31:36 ERROR]:       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:238)
[07:31:36 ERROR]:       at io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:231)
[07:31:36 ERROR]:       at io.netty.channel.DefaultChannelPipeline$HeadContext.channelActive(DefaultChannelPipeline.java:1398)
[07:31:36 ERROR]:       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:258)
[07:31:36 ERROR]:       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:238)
[07:31:36 ERROR]:       at io.netty.channel.DefaultChannelPipeline.fireChannelActive(DefaultChannelPipeline.java:895)
[07:31:36 ERROR]:       at io.netty.channel.local.LocalChannel$3.run(LocalChannel.java:186)
[07:31:36 ERROR]:       at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173)
[07:31:36 ERROR]:       at io.netty.channel.DefaultEventLoop.run(DefaultEventLoop.java:54)
[07:31:36 ERROR]:       at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
[07:31:36 ERROR]:       at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
[07:31:36 ERROR]:       at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
[07:31:36 ERROR]:       at java.base/java.lang.Thread.run(Thread.java:833)

To Reproduce

  1. Install Geyser as plugin
  2. Enable PROXY protocol support in remote server (in this case Velocity) and both use-proxy-protocol, enable-proxy-protocol to true
  3. Use proxy server: https://pastebin.com/PmZ0RuU2 (install node.js to use)
  4. Change bedrock listen address to ::
  5. Connect to Geyser through proxy (provided code will listen on 19133 on both IPv4 and IPv6)

Expected behaviour

Should select correct destination address and connect like usual.

Screenshots / Videos

image

Server Version and Plugins

Velocity 3.2.0-SNAPSHOT (git-81b183ac-b276)

Geyser Dump

Haven't configured permission yet so cannot create a dump, sorry.

Geyser Version

2.2.0-SNAPSHOT (git-master-2e68244)

Minecraft: Bedrock Edition Device/Version

1.20.32, Windows

Additional Context

I'm using Docker with IPv6 enabled, but should also be applicable without Docker.

onebeastchris commented 11 months ago

Please send a Geyser dump - additionally, i would recommend to try and set the bedrock address to your local ipv6 address. Geyser doesn't support both ipv4/ipv6 at once

BadAimWeeb commented 11 months ago

Please send a Geyser dump - additionally, i would recommend to try and set the bedrock address to your local ipv6 address. Geyser doesn't support both ipv4/ipv6 at once

I've tried setting it to IPv6, and IPv6 works but IPv4 would have this problem. For now I'm currently hardcoding address as 127.0.0.1 or ::1 depends on client address family.

diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java
index 551bc1de..ef2e148f 100644
--- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java
+++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java
@@ -129,7 +129,7 @@ public final class LocalSession extends TcpSession {
                     }
                     ctx.channel().writeAndFlush(new HAProxyMessage(
                             HAProxyProtocolVersion.V2, HAProxyCommand.PROXY, proxiedProtocol,
-                            clientAddress.getAddress().getHostAddress(), remoteAddress.getAddress().getHostAddress(),
+                            clientAddress.getAddress().getHostAddress(), (proxiedProtocol == HAProxyProxiedProtocol.TCP4 ? "127.0.0.1" : "0:0:0:0:0:0:0:1"),
                             clientAddress.getPort(), remoteAddress.getPort()
                     ));
                     ctx.pipeline().remove(this);

I don't think forwarding remote address matters in server though. Target server is auto (I'm using Velocity plugin)

onebeastchris commented 10 months ago

Thanks for the code snippet :) Out of curiosity, what happens if you bind Geyser to the :: wildcard? Does that too select the wrong address family type?

BadAimWeeb commented 10 months ago

Does that too select the wrong address family type?

Yes. I don't think where Geyser bind bedrock port is important, since remoteAddress is Java address.

I've also updated bug report to correctly describe bug, since enable-proxy-protocol might be relevant here now that I noticed Geyser doesn't listen to both IPv4 and IPv6.