OPNsense Forum

Archive => 20.7 Legacy Series => Topic started by: randomwalk on December 08, 2020, 07:56:24 pm

Title: HAProxy Help Needed -- Authenticated Access to Minecraft Server
Post by: randomwalk on December 08, 2020, 07:56:24 pm
I have a personal Minecraft server on the LAN that I run for my kids.  They want to allow cousins / school friends to play on our server.  For security reasons, I don't want to just port forward and allow public access to the Minecraft server, nor do I want these people access to my network via VPN.  I want an in between solution where people can access the Minecraft server after HTTPS user / password authentication.  I thought HAProxy would work for this, but have not gotten it to work.  Any guidance would be greatly appreciated!

End Goal:  I want people to go to some web address (e.g., https://minecraft.domain.xyz:12345) and authenticate using a user / password that I give them.  After that, they are able to connect to my server by connecting to minecraft.domain.xyz inside Minecraft.  If people do not first go to the URL to authenticate, they should not be able to connect via Minecraft.  I understand Minecraft uses port 25565.

Here is my set up so far:

1)  I installed the Let's Encrypt plugin.  I purchased my own domain (domain.xyz) and have successfully issued a wildcard certificate for domain.xyz and *.domain.xyz.  In the Let's Encrypt plugin, I do NOT check "HAProxy Integration" because I understand that is only needed if I use HTTP-01 validation and I don't use that method.

2)  I use Dynamic DNS to set domain.xyz and minecraft.domain.xyz to equal my WAN IP address.

3)  Here are my HAProxy settings:

Real Server
Enabled:  Checked
Name:  Minecraft
IP:  192.168.1.90
Port:  25565
Mode:  active [default]
SSL:  Unchecked

Backend Pool
Enabled:  Checked
Name:  Minecraft
Mode:  TCP (Layer 4)  --> my understanding is that this should be set to TCP because Minecraft is not a webserver
Balancing Algorithm:  Source-IP Hash [default]
Servers:  Minecraft
Enable Health Checking:  Checked
Health Monitor:  None
Persistence Type:  Stick-table persistence [default]
Stick-table persistence table type:  Source-IP [default]

Users / Group
I created a single test user / password.
I added this single user to a test group.

Conditions
Name:  Host_Minecraft
Condition type:  Host matches
Host string:  minecraft.domain.xyz

Name:  Auth_User
Condition type:  HTTP Basic Auth:  username/password from client matches selected user/group
Parameters:  matches to my test group.

Rules
Name:  Minecraft
Test type:  IF [default]
Selected conditions:  Auth_User AND Host_Minecraft
Execute function:  Use specified Backend Pool
Use backend pool:  Minecraft

Public Service
Name:  Frontend
Listen Addresses:  0.0.0.0:12345  I don't know if 0.0.0.0 is the right address to use here
Type:  HTTP / HTTPS (SSL offloading) [default]
Default Backend Pool:  none
Enable SSL offloading:  Checked

SSL Offloading:
Certificates:  wildcard certificate from Let's Encrypt
Default certificate:  wildcard certificate from Let's Encrypt
Enable Advanced Settings:  Unchecked

HTTP(S) settings:
Enable HTTP/2:  Checked
HTTP/2 Without TLS:  Unchecked

Basic Authentication:
Enabled:  Checked
Allowed Groups:  my test group

Firewall rules
On the WAN, I allow IPv4 TCP/UDP protocol to pass at port 12345.

Here is what happens:

1)  Using my browser, I am able to go to https://minecraft.domain.xyz:12345, it gets a user/password prompt, and I able to "login" using my test user credentials.  The connection is properly secured using the Let's Encrypt certificate.  After login, the browser shows an error message because there is no webserver at that location.  But I don't care.  I just want to satisfy the Auth_User condition.

2)  I open Minecraft and add the server minecraft.domain.xyz, and I try to connect, but it does not work.  I thought this would work because I thought this would satisfy the Host_Minecraft condition.

So what am I doing wrong?  I am able to get the user authentication working, but HAProxy is not correctly passing traffic to my Minecraft server.  I am guessing something is wrong with my "Public Server" settings, but am not sure what.
Title: Re: HAProxy Help Needed -- Authenticated Access to Minecraft Server
Post by: randomwalk on December 08, 2020, 08:15:02 pm
One thing I noticed that is in my "Public Service" settings, I did not set anything under "Select Rules".  But when I try to select "Minecraft" rule inside that setting, HAProxy says there is a critical configuration error: 

http frontend 'Frontend' (/usr/local/etc/haproxy.conf:48) tries to use incompatible tcp backend 'Minecraft' (/usr/local/etc/haproxy.conf:81) in a 'use_backend' rule (see 'mode').

I am guessing this means that the Public Service "Type" should be set to something else, rather than "HTTP / HTTPS (SSL offloading) [default]"?  But I don't know  how to set this up.  I want to keep the HTTPS user authentication, but pass through TCP traffic.
Title: Re: HAProxy Help Needed -- Authenticated Access to Minecraft Server
Post by: randomwalk on December 09, 2020, 06:50:46 am
After some searching, it seems that because Minecraft does not use HTTP, you cannot use Host_Minecraft condition.  That is, you can't depend on hostname = minecraft.domain.xyz to trigger the rule.

As a result, I have changed the rule Minecraft to equal IF Auth_User (i.e., the user successfully authenticates).

I think the solution must involving setting up a second frontend:

Public Service
Name:  Frontend_Minecraft
Listen Addresses:  0.0.0.0:25565
Type:  TCP
Default Backend Pool:  none
Rule:  Minecraft (this is basically just equal to IF Auth_User)

Unfortunately, the above does not seem to work.  I am able to connect to the Minecraft server from outside the network if I change the above public service to have Default Backend Pool = Minecraft.  But if I do that, then you are able to connect to the server regardless of whether you authenticated.

What I can't figure out is how to link the two Public Services.  I have one public service at port 12345 that just does HTTP authentication, and that works correctly and uses a proper SSL certificate.  I have another public service at port 25565 that connects to the Minecraft backend.  It works too, but I am not able to make the Minecraft backend conditional on authenticating with the first Public Service.

Any ideas on how to do this?
Title: Re: HAProxy Help Needed -- Authenticated Access to Minecraft Server
Post by: cmdr.adama on December 09, 2020, 10:42:19 am
So, First thing's first.

You won't be able to do this with HAProxy.

Really the only way you can achieve what you want is to sit the MC server behind a VPN.

So, you'll need to set up a VPN server, OpenVPN, WireGuard, etc.
Shift your MC server to sit in a DMZ, if you haven't already and then point all VPN connections to the DMZ.

If you want, you can also configure unbound to allow the users connecting to the VPN to use hostnames instead of IP addresses.
Title: Re: HAProxy Help Needed -- Authenticated Access to Minecraft Server
Post by: randomwalk on December 09, 2020, 06:05:44 pm
Yes, I am coming to the conclusion that this cannot be done using HAProxy after additional searching.  The main issue is that Minecraft is not an HTTP protocol, and you cannot authenticate using a TCP proxy.  This seems strange to me as I would think you can authenticate via HTTP, then remember the IP address that authenticated, and then allow only that IP address to go through the TCP proxy.  It seems like this would be a desired function as not everything is HTTP.

I'm aware that this can be done with VPN and I can lock it down with firewall rules so that users can only access the Minecraft server.  I already have an OpenVPN server running for my own remote access.  But I do not want to give VPN access to my kids' school friends because (1) it's too complicated, I would have to issue them certificates and they would have to set it up on their end, (2) hard to cut people off if I want to; I'd have to revoke their certificates (vs. just deleting their user account).  This is why I would prefer a user / password scheme rather than a VPN that requires certificates and complicated set up. 

I'm not looking to give users fully secured / encrypted access to the internal network -- I just don't want the whole world to have access to the Minecraft server.

So are there alternatives to VPN?  Are there VPNs that don't require certificates?  Is there like a scheme where you have port forwarding conditional on user authentication? 


So, First thing's first.

You won't be able to do this with HAProxy.

Really the only way you can achieve what you want is to sit the MC server behind a VPN.

So, you'll need to set up a VPN server, OpenVPN, WireGuard, etc.
Shift your MC server to sit in a DMZ, if you haven't already and then point all VPN connections to the DMZ.

If you want, you can also configure unbound to allow the users connecting to the VPN to use hostnames instead of IP addresses.
Title: Re: HAProxy Help Needed -- Authenticated Access to Minecraft Server
Post by: cmdr.adama on December 10, 2020, 01:11:13 pm
Yes, I am coming to the conclusion that this cannot be done using HAProxy after additional searching.  The main issue is that Minecraft is not an HTTP protocol, and you cannot authenticate using a TCP proxy.  This seems strange to me as I would think you can authenticate via HTTP, then remember the IP address that authenticated, and then allow only that IP address to go through the TCP proxy.  It seems like this would be a desired function as not everything is HTTP.

Well in theory you could utilize port knocking to open up port 25565 when someone makes a connection to port 80... You might be able to do something like this https://gist.github.com/cryptolok/326b6afc98bf4bb489a206d62ad12580. So use HAProxy to proxy connections to the Minecraft server, then use something similar to the above accordingly to knock port 80 to open 25565 for the user's IP... You may need to do some funky stuff to ensure the Source IP is correctly being passed through


Title: Re: HAProxy Help Needed -- Authenticated Access to Minecraft Server
Post by: fabian on December 10, 2020, 11:24:47 pm
A SOCKS proxy is probably your friend. It supports authentication and you can tunnel any TCP connection and you can set up an ACL on the server. Sadly there is none on OPNsense so you should go with IPsec or OpenVPN.
Title: Re: HAProxy Help Needed -- Authenticated Access to Minecraft Server
Post by: JoanCornishOj on May 06, 2022, 12:35:12 am
I know from personal experience what this is like. I have two kids too, and I've seen them inadvertently end up on unsafe Minecraft servers more than once. There is a lot of dirty content in the game besides the positives. When I started looking for adequate servers in the game, I came across servers-minecraft.net (https://servers-minecraft.net). There are a lot of mods here, and most importantly, you can choose the right server for you. Also, the links should not be viruses. That is, for the computer, too, do not worry. I advise you and look at these servers for your children.