You are viewing a potentially older version of this package. View all versions.
ferrinius-RCON_Next-1.0.0 icon

RCON Next

Secure Source RCON support for BepInEx-compatible servers

Date uploaded a day ago
Version 1.0.0
Download link ferrinius-RCON_Next-1.0.0.zip
Downloads 2
Dependency string ferrinius-RCON_Next-1.0.0

This mod requires the following mods to function

README

RCON Next

RCON Next provides a Source RCON endpoint for dedicated servers running BepInEx 5. It is designed for Valheim and emits a single rcon.dll plugin assembly targeting .NET Standard 2.0. The assembly includes a compatibility facade for plugins compiled against the earlier rcon integration API.

The implementation emphasizes protocol correctness, authenticated command execution, bounded resource use, and a small integration API for other BepInEx plugins.

Install

Remove any existing implementation of rcon.dll, then install through a Thunderstore-compatible mod manager or extract the release ZIP into the game server directory. The archive places the plugin at BepInEx/plugins/RconNext/rcon.dll. For a DLL-only manual installation, copy rcon.dll anywhere below BepInEx/plugins.

Start the game server once so BepInEx creates:

BepInEx/config/com.github.ferrinius.rcon-next.cfg

For configuration before the first server start, copy the bundled sample configuration to that path and remove the .example suffix.

Set a private password, choose the listening port, and enable the endpoint:

[rcon-next]
enabled = true
port = 2458
password = replace-with-a-strong-password

The plugin will not listen when the password is ChangeMe, blank, or incompatible with Source RCON's printable-ASCII password format. Expose the selected TCP port only to networks that should reach it.

Integrate a command

Add rcon.dll as a reference and declare the RCON Next plugin dependency:

using BepInEx;
using RconNext;

[BepInPlugin("org.example.server-health", "Server Health", "1.0.0")]
[BepInDependency(RconPlugin.PluginGuid, BepInDependency.DependencyFlags.HardDependency)]
public sealed class ServerHealthPlugin : BaseUnityPlugin
{
    private RconPlugin? _rcon;

    private void OnEnable()
    {
        _rcon = GetComponent<RconPlugin>();
        _rcon?.RegisterCommand(this, "health", _ => "ok");
    }

    private void OnDisable()
    {
        _rcon?.UnregisterCommand(this, "health");
        _rcon = null;
    }
}

Class-based handlers remain available for compatibility:

public sealed class PlayerCountCommand : AbstractCommand
{
    public override string onCommand(string[] args)
    {
        return "0";
    }
}

// During plugin enable:
rcon.RegisterCommand<PlayerCountCommand>(this, "players");

UnRegisterCommand and the lowercase onCommand member are retained for existing integrations. New code should prefer UnregisterCommand; see COMPATIBILITY.md for the complete contract.

Legacy plugin compatibility

The same assembly also exposes the former rcon namespace, rcon.rcon plugin type, command classes, delegates, event, and plugin GUID. Existing plugins compiled against that API can therefore resolve rcon.dll and their hard BepInEx dependency without being rebuilt.

The compatibility facade delegates to RCON Next; it does not run a second listener. If nl.avii.plugins.rcon.cfg already exists and the new RCON Next configuration did not exist before startup, its [rcon] values are imported into the new configuration and used immediately. A pre-existing RCON Next configuration takes precedence.

RCON Next and the earlier rcon.dll implementation are replacements for one another and must not be installed together.

When no registered handler matches, RconPlugin.OnUnknownCommand receives the normalized command name and parsed arguments. This can be used to forward commands into another command system.

Security properties

Authentication belongs to an individual TCP connection. Commands received before successful authentication are never dispatched. A failed login—including reauthentication after a successful login—revokes the session and closes the connection.

Default resource limits are deliberately finite:

Resource Limit
Active connections 16
Connections from one IP address 4
Source RCON body size 4 096 bytes
Framing storage per connection 8 200 bytes
Packets per connection per second 30
Time allowed to authenticate 10 seconds
Authenticated idle time 10 minutes
Socket send timeout 5 seconds
Command response length 65 536 characters

Malformed frames, unsupported packet types, rate-limit violations, expired sessions, and oversized responses are rejected without unbounded buffering. These application limits complement rather than replace firewall rules and upstream protection against volumetric traffic.

Develop in containers

Docker Compose and just are the only host-side build dependencies.

just test   # NUnit compatibility, protocol, and security suite
just build  # tests, then a clean release build

Both commands compile as an unprivileged UID/GID matching the invoking user. Source is mounted read-only and copied into an ephemeral container workspace. A successful build replaces artifacts/ with rcon.dll and its build metadata.

Build versions are derived from v-prefixed SemVer tags. An exact tag such as v1.2.3 produces plugin version 1.2.3; untagged commits receive a MinVer prerelease version. The legacy compatibility plugin remains version 1.0.5, and the assembly version remains 1.0.0.0 to preserve existing binary references.

Production sources share one project under src/RconNext:

src/RconNext/
├── BepInEx/   plugin lifecycle and public command API
└── Core/      Source RCON framing, sessions, and TCP server

The NUnit test project is in tests/RconNext.ProtocolTests.

Release

Push a v-prefixed version tag to build and publish a release:

git tag v1.2.3
git push origin v1.2.3

The workflow runs the tests and release build, stages the BepInEx install layout, and creates one versioned ZIP containing the Thunderstore manifest. That exact archive is attached to the GitHub Release and uploaded to Thunderstore. The leading v is removed from the package version.

License

RCON Next is distributed under the ISC license. See LICENSE.