smcr

module
v0.2.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 11, 2024 License: GPL-3.0

README

SMCR: Simple Minecraft Router

License Issues Docker

A simple Minecraft router that routes using the server address in the handshake packet

With SMCR, you can connect to multiple Minecraft servers with only 1 port, which is helpful if you don't want to expose too many ports, or you're using reversed proxy like frp that only provides a few ports

flowchart LR
    client1[Minecraft Client 1] -- a.example.com --> SMCR
    client2[Minecraft Client 2] -- b.example.com --> SMCR
    client3[Minecraft Client 3] -- c.example.com --> SMCR
    client4[Minecraft Client 4] -- "bad.host.name (rejected)" --x SMCR
    
    SMCR -- client 1 --> server1[Minecraft Server A]
    SMCR -- client 2 --> server2[Minecraft Server B]
    SMCR -- client 3 --> server3[Minecraft Server C]

Similar projects

There are some similar projects that provides better support on metrics / high availability, go check them out:

Usages

Prepare your config file, then you can start SMCR with the following command

./smcr  # use ./config.yml as the configuration
./smcr -c /path/to/config.yml  # explicitly supply the path to the config

# declare config content in environment variable SMCR_CONFIG (yaml format)
export SMCR_CONFIG='{"listen": "0.0.0.0:7777", "routes": [{"name": "default", "matches": ["example.com"], "target": "127.0.0.1:25565"}]}'
./smcr
Config Examples

An example config file with all available options can be found here

Here's some useful config examples for lazyman

A basic connection forwarder that to ensure the client connects with example.com

listen: 0.0.0.0:7777
routes:
  - name: example
    matches:
      - example.com
    target: 127.0.0.1:25565

A config with more routes defined

listen: 0.0.0.0:7777
routes:
  - name: svr1
    matches:
      - svr1.example.com
    target: 127.0.0.1:10000
    
  - name: svr2
    matches:
      - svr2.example.com
    target: 127.0.0.1:20000

  - name: svr3
    matches:
      - svr3.example.com
    target: 127.0.0.1:30000

A connection forwarder that modifies the server address in the handshake packet from whatever value to mc.example.com:25565. Notes that the only route in the config has the name default

listen: 0.0.0.0:7777
routes:
  - name: default
    target: server.example.com:20001
    mimic: mc.example.com:25565

A connection forwarder that has a server address check, and will append a proxy protocol header to the downstream target server

listen: 0.0.0.0:7777
routes:
  - name: example
    matches:
      - 127.0.0.1
      - example.com:20001
    target: 127.0.0.1:25577
    mimic: mc.example.com:25565
    proxy_protocol: 2

Config Entries

Here's a detailed explanation of all options in the config file

General options
listen

The address where SMCR listens on

Example: 120.0.0.1:6666, 0.0.0.0:7777, :8888

listen: 0.0.0.0:7777
debug

The debug switch of SMCR. Set to true to enable debug level logging and log caller will be included in the log

log_level: false
routes

Route definition. It's an object list where each item represents a route

See section route for explanation on route items

routes:
  - name: example
    matches:
      - localhost:7777
    target: 127.0.0.1:25565
srv_lookup_timeout

The timeout for querying an SRV record

See section timeout format section for more details on its format

srv_lookup_timeout: 3s
default_connect_timeout

The timeout for connect to a route target

You can set a lower timeout for fast response, if SMCR and the target server is in the same LAN

See section timeout format section for more details on its format

default_connect_timeout: 3s
proxy_protocol

Enable support for accepting proxy protocol from client

When enabled, client connections are required to send a proxy protocol header (in either version 1 or 2) to smcr

proxy_protocol: false
Route

When received a client connection, SMCR will try to read the handshake packet from the client and extract the hostname + port from it.

name

The name of the route

name: foo
matches

A list of address which this route will accept

SMCR will check if any of these addresses matches the hostname and port in client's handshake packet

There are 2 valid formats for the address

  1. Hostname with port, e.g. "localhost:7777", "127.0.0.1:7777", "mc.example.com:7777", which matches the both the hostname of the port
  2. Hostname only, e.g. "localhost", "mc.example.com", which matches the hostname only

The hostname-with-port match has a higher priority than the hostname-only match, so if you have 2 matching routes, where one uses hostname with port and the other uses hostname only, the route will the port will get the match, no matter what the route order in the routes list is

matches:
  - localhost:7777
  - 127.0.0.1:7777
  - mc.example.com
action

Optional option, define what SMCR will do with this route for the client connection

action explanation
forward Accept the connection and forward it to the given target
reject Simply close the connection

The default value is forward

action: forward
reject_message

Available when reject is true

Optional option, the message to be sent back to the client as the disconnect reason

If not given, SMCR will just close the connection directly

See mc message section for more details on its format

reject_message: 404 not found
target

Available when reject is false

Required, The address of the target server that SMCR will forward the client connection to

If the port is absent, SMCR will try to perform an SRV lookup on the given hostname. If SRV lookup fails, port 25565 will be used as the fallback value

target: 127.0.0.1:25565
mimic

Available when reject is false

Optional option. If given, SMCR will modify the hostname and port in the handshake packet

It should be an address with hostname and port

It can be used to bypass the handshake address check on the actual Minecraft server

mimic: mc.hypixel.net:25565
timeout

Available when reject is false

Optional, the maximum timeout for connecting to the target server.

If not given the value from default_connect_timeout will be used

See section timeout format section for more details on its format

timeout: 5s
dial_fail_message

Available when reject is false

Optional option, the message to be sent back to the client if smcr fails to connects to the target server

If not given, SMCR will just close the connection directly

See mc message section for more details on its format

dial_fail_message: server down?
proxy_protocol

Available when reject is false

If given, send proxy protocol header to the target server using given version (1 or 2)

proxy_protocol: 2  # using version 2
Default route

A route named default is the default route, which works as a fallback route for the unmatched client connections. It accepts all client connections, only when other routes fail to match client's connecting address

The matches field of the default route is ignored

Here's some example default routes:

# Reject with message
name: default
action: reject
reject_message: '{"text": "oops", "color": "red"}'
# Route to given target
name: default
target: localhost:20000

If there's no default route in the config, unmatched client connections will be simply discard, just like a default route with reject action and no reject message

Field formats
timeout format

It's string that represents a time duration format. Examples:

example_timeout1: 1.5s
example_timeout2: 300ms

The value should greater than 0. Zero or negative values are treated as unset values

See https://pkg.go.dev/time#ParseDuration for more details

mc message format

It's a string that represents a Minecraft message component

If the given input is a valid json string, then SMCR will just the given value directly as the message json. Notes that the json object in the string should satisfy Minecraft's json text format

example_message1: '{"text": "hello world", "color": "green"}'
example_message2: '"foobar"'

Otherwise, SMCR will treat the given input as a plain string, and convert it into a valid message json

example_message3: this is a plain text
# SMCR will use "this is a plain text" as the message json

Docker

The docker image of SMCR is released at DockerHub

You can run SMCR with the following command

docker run -p 7777:7777 -v ./config.yml:/app/config.yml fallenbreath/smcr:latest

You can also use the example docker-compose.yml as an example docker-compose.yml file to run SMCR

Directories

Path Synopsis
cmd
internal
dns

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL