mojira.dev
BDS-7707

bedrock binds to first IP address on multi-homed server

Steps to reproduce...

  1. Build Linux box - Attempted on both Gentoo and Ubuntu 20.04

  2. Install Minecraft

  3. Assign multiple IPs to an adaptor (192.168.1.2, 192.168.1.3, 192.168.1.4)

  4. Attempt to connect to 192.168.1.3 or 192.168.1.4 - doesn't work

  5. Attempt to connect to 192.168.1.2 - it works

What I expected to happen...
Bedrock should either bind to all IPs and answer on all IPs, or allow specification of which IP to bind to within server.properties

What actually happened...
Bedrock only binds to the first IP

How this affects the usage of BDS...
On a system with multiple IPs it is ambiguous as to which one Bedrock will answer on.

Comments 10

I'm not able to reproduce this on Windows, not the scenario you describe where BDS won't respond on both interfaces, however that's not the full story.

The server wont respond against both IP's without additional configuration. This is a networking thing to do with routing.

Lets say your server has 2 IP addresses (192.168.0.1 and .2), it will always have one of the two that it uses for outgoing traffic. So when using 192.168.0.1 to connect it responds using 192.168.0.1 to respond and everything works.

However when you try to connect using 192.168.0.2, it responds using 192.168.0.1 and because of the discrepancy it fails.

If you update the routing table to respond using the second interface everything will start working.

As such its not ambiguous which interface BDS will respond on, it will respond on any, however your routing will decide if it succeeds or fails.

I'll chuck this one into awaiting response. Let me know if you believe this to be incorrect.

I'm not able to reproduce this on Windows, not the scenario you describe where BDS won't respond on both interfaces, however that's not the full story.

The server wont respond against both IP's without additional configuration. This is a networking thing to do with routing.

Lets say your server has 2 IP addresses (192.168.0.1 and .2), it will always have one of the two that it uses for outgoing traffic. So when using 192.168.0.1 to connect it responds using 192.168.0.1 to respond and everything works.

However when you try to connect using 192.168.0.2, it responds using 192.168.0.1 and because of the discrepancy it fails.

If you update the routing table to respond using the second interface everything will start working.

As such its not ambiguous which interface BDS will respond on, it will respond on any, however your routing will decide if it succeeds or fails.

I'll chuck this one into awaiting response. Let me know if you believe this to be incorrect.

I think you might have misunderstood the concern, the operating system and resolution.

Firstly, this was discovered on two different Linux distributions, I'm not sure how relevant testing or not testing on Windows might be, but I don't know your code base.

Secondly, you've misinterpreted the defect, as well as how networking works under Linux.

This is not true, nor is it the root of the concern:

Lets say your server has 2 IP addresses (192.168.0.1 and .2), it will always have one of the two that it uses for outgoing traffic. So when using 192.168.0.1 to connect it responds using 192.168.0.1 to respond and everything works.

In Linux the struct for sockaddr_in is defined as follows in socket.h:

struct sockaddr_in { __uint8_t sin_len; sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; char sin_zero[8]; }; 

 

When passing this to bind() if you specify sin_addr as an actual address (rather than INADDR_ANY) it will bind() to a specific IP on the host.

Your statement regarding one always being used for outbound traffic is incorrect. If you bind to one IP, all datagrams will bear that IP as the source when responding. Doing otherwise would result in asynchronous traffic where traffic is sent from one IP and returns on another.

The issue, is that bedrock doesn't currently have a method of specifying what sin_addr is being used for bind(). Presumably you're using INADDR_ANY which subsequently binds to the first IP it sees. 

What I'm asking for is a config item in server.properties that will allow me to explicitly specific which IP bedrock binds to. For example:

server.properties 

bind-address=192.168.200.4

 

??Source : https://www.cs.rutgers.edu/~pxk/417/notes/sockets/udp.html??

I think you might have misunderstood the concern, the operating system and resolution.

Firstly, this was discovered on two different Linux distributions, I'm not sure how relevant testing or not testing on Windows might be, but I don't know your code base.

Secondly, you've misinterpreted the defect, as well as how networking works under Linux.

This is not true, nor is it the root of the concern:

Lets say your server has 2 IP addresses (192.168.0.1 and .2), it will always have one of the two that it uses for outgoing traffic. So when using 192.168.0.1 to connect it responds using 192.168.0.1 to respond and everything works.

In Linux the struct for sockaddr_in is defined as follows in socket.h:

struct sockaddr_in { __uint8_t sin_len; sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; char sin_zero[8]; }; 

 

When passing this to bind() if you specify sin_addr as an actual address (rather than INADDR_ANY) it will bind() to a specific IP on the host.

Your statement regarding one always being used for outbound traffic is incorrect. If you bind to one IP, all datagrams will bear that IP as the source when responding. Doing otherwise would result in asynchronous traffic where traffic is sent from one IP and returns on another.

The issue, is that bedrock doesn't currently have a method of specifying what sin_addr is being used for bind(). Presumably you're using INADDR_ANY which subsequently binds to the first IP it sees. 

What I'm asking for is a config item in server.properties that will allow me to explicitly specific which IP bedrock binds to. For example:

server.properties 

bind-address=192.168.200.4

 

??Source : https://www.cs.rutgers.edu/~pxk/417/notes/sockets/udp.html??

To cut a long story short, I don't misunderstand and BDS doesn't "bind" to any specific interface, it will respond to connections on any interface, obeying the OS's routing table. However in a default configuration this can result in linux responding on a different IP to the original destination, causing it not to connect. This means your below assertion is not accurate.

What actually happened...

Bedrock only binds to the first IP

BDS will respond to traffic coming in on any interface, it is not attached to one specific interface, your OS configuration however determines how it responds.

You can test this by forcing traffic to a specific destination out specific interfaces via routing and then monitoring the traffic and noting that BDS is responding on different interfaces simultaneously. You will also find that the IP your server responds on is the same one that shows when checking the default IP for all network traffic using a service like whatsmyip. I've just done this on Ubuntu 20.04 to cover your concern about using Windows (they are the same codebase, in 90% of cases issues translate).

BDS not responding to multiple interfaces would have in fact been a bug, but wanting a way to easily specify that it bind to a specific interface would be considered a feature request and as such is not suitable for the bug tracker. Feature Requests can be made over at https://feedback.minecraft.net, or more specifically the Realms and Dedicated Servers section.

To cut a long story short, I don't misunderstand and BDS doesn't "bind" to any specific interface, it will respond to connections on any interface, obeying the OS's routing table. However in a default configuration this can result in linux responding on a different IP to the original destination, causing it not to connect. This means your below assertion is not accurate.

What actually happened...

Bedrock only binds to the first IP

BDS will respond to traffic coming in on any interface, it is not attached to one specific interface, your OS configuration however determines how it responds.

You can test this by forcing traffic to a specific destination out specific interfaces via routing and then monitoring the traffic and noting that BDS is responding on different interfaces simultaneously. You will also find that the IP your server responds on is the same one that shows when checking the default IP for all network traffic using a service like whatsmyip. I've just done this on Ubuntu 20.04 to cover your concern about using Windows (they are the same codebase, in 90% of cases issues translate).

BDS not responding to multiple interfaces would have in fact been a bug, but wanting a way to easily specify that it bind to a specific interface would be considered a feature request and as such is not suitable for the bug tracker. Feature Requests can be made over at https://feedback.minecraft.net, or more specifically the Realms and Dedicated Servers section.

I'm not sure how else to describe this, but if you can forward to someone who understands socket programming it might help. In order to serve inbound connections, BDS needs to bind() to a port. There have been numerous reports on the internet with ridiculous problems with the way BDS binds on Linux.

 

Further you're completely mixing up how routing works. 

 

I'm not sure how else to describe this, but if you can forward to someone who understands socket programming it might help. In order to serve inbound connections, BDS needs to bind() to a port. There have been numerous reports on the internet with ridiculous problems with the way BDS binds on Linux.

 

Further you're completely mixing up how routing works. 

 

I am having an issue that is indicative of this behavior. The bedrock server appears to bind to all IP addresses using 0.0.0.0:19132. If I already have another server bound to an IP with the same port as bedrock 19132 it causes the bedrock server to fail to boot because it can't bind to an IP. I can put in the config to bind to a specific IP like the java version, but it does not appear to do anything.

This is causing an issue that prevents multiple bedrock servers from being able to run on the same box. 

Trying to run two servers:

A Survival server on IP1:19132
A Creative server on IP2:19132

I am having an issue that is indicative of this behavior. The bedrock server appears to bind to all IP addresses using 0.0.0.0:19132. If I already have another server bound to an IP with the same port as bedrock 19132 it causes the bedrock server to fail to boot because it can't bind to an IP. I can put in the config to bind to a specific IP like the java version, but it does not appear to do anything.

This is causing an issue that prevents multiple bedrock servers from being able to run on the same box. 

Trying to run two servers:

A Survival server on IP1:19132
A Creative server on IP2:19132

Omkhar

(Unassigned)

Unconfirmed

Retrieved