Skip to content

Commit 152fa12

Browse files
lexclaude
andauthored
Read rcon password from settings.json and bind rcon to localhost (#135)
* Read rcon password from settings.json The rcon password was a hardcoded constant, so every server started with the same, publicly known password. Since #132 this also applies on Linux. Add an optional rcon_password setting to the wrapper's settings.json. If it's empty or missing, a random password is generated each time the wrapper starts, so existing settings files keep working. The password is also no longer written to the wrapper log. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Bind rcon to localhost only --rcon-port makes Factorio listen for rcon on all interfaces. The wrapper only connects to rcon on 127.0.0.1, so bind it there and keep it off the public network. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: lex <lex@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent c66144a commit 152fa12

4 files changed

Lines changed: 27 additions & 8 deletions

File tree

‎FactorioWrapper/FactorioWrapper.cs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Serilog;
33
using System;
44
using System.IO;
5+
using System.Linq;
56

67
namespace FactorioWrapper
78
{
@@ -55,6 +56,13 @@ public static void Main(string[] args)
5556
settings.Url = url;
5657
}
5758

59+
// The password is passed to factorio as a command line argument, so it can't contain whitespace or quotes.
60+
if (settings.RconPassword != null && settings.RconPassword.Any(c => char.IsWhiteSpace(c) || c == '"'))
61+
{
62+
Log.Fatal("rcon_password in settings.json must not contain whitespace or quotes");
63+
return;
64+
}
65+
5866
if (args.Length < 3)
5967
{
6068
Log.Fatal("Missing arguments");

‎FactorioWrapper/MainLoop.cs‎

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System;
88
using System.Diagnostics;
99
using System.Linq;
10+
using System.Security.Cryptography;
1011
using System.Text.RegularExpressions;
1112
using System.Threading;
1213
using System.Threading.Tasks;
@@ -25,7 +26,7 @@ public class MainLoop : IDisposable
2526
private readonly Settings settings;
2627
private readonly string serverId;
2728
private readonly string factorioFileName;
28-
private string factorioArguments;
29+
private readonly string factorioArguments;
2930

3031
// This is to stop multiple threads writing to the factorio process concurrently.
3132
private readonly SemaphoreSlim factorioProcessLock = new SemaphoreSlim(1, 1);
@@ -45,9 +46,9 @@ public class MainLoop : IDisposable
4546

4647
private volatile RconMessenger rcon;
4748
private int rconPort;
48-
private const string rconPassword = "no_one_will_guess_this_awesome_password.";
49+
private readonly string rconPassword;
4950

50-
private void PrependRconArguments()
51+
private void SetRconPort()
5152
{
5253
int index = factorioArguments.IndexOf("--port");
5354

@@ -61,8 +62,6 @@ private void PrependRconArguments()
6162
string port = factorioArguments.Substring(start, end - start);
6263

6364
int.TryParse(port, out rconPort);
64-
65-
factorioArguments += $" --rcon-port {rconPort} --rcon-password {rconPassword}";
6665
}
6766

6867
private async Task ConnectRCON()
@@ -88,7 +87,12 @@ public MainLoop(Settings settings, string serverId, string factorioFileName, str
8887
this.factorioFileName = factorioFileName;
8988
this.factorioArguments = factorioArguments;
9089

91-
PrependRconArguments();
90+
// Fall back to a random password so RCON is never left with a known password.
91+
rconPassword = string.IsNullOrWhiteSpace(settings.RconPassword)
92+
? Convert.ToHexString(RandomNumberGenerator.GetBytes(32))
93+
: settings.RconPassword;
94+
95+
SetRconPort();
9296

9397
messageQueue = new SingleConsumerQueue<Func<Task>>(maxMessageQueueSize, async func =>
9498
{
@@ -384,7 +388,9 @@ private async Task StartFactorioProcess()
384388
factorioProcess = new Process();
385389
var startInfo = factorioProcess.StartInfo;
386390
startInfo.FileName = factorioFileName;
387-
startInfo.Arguments = factorioArguments;
391+
// The rcon password is added after logging so that it doesn't end up in the log file.
392+
// Rcon is bound to localhost so that it isn't reachable from outside this machine.
393+
startInfo.Arguments = $"{factorioArguments} --rcon-bind 127.0.0.1:{rconPort} --rcon-password {rconPassword}";
388394
startInfo.UseShellExecute = false;
389395
startInfo.CreateNoWindow = true;
390396
startInfo.RedirectStandardInput = true;

‎FactorioWrapper/Settings.cs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,9 @@ public class Settings
1212
[JsonProperty(PropertyName = "url")]
1313
[JsonPropertyName("url")]
1414
public string Url { get; set; }
15+
16+
[JsonProperty(PropertyName = "rcon_password")]
17+
[JsonPropertyName("rcon_password")]
18+
public string RconPassword { get; set; }
1519
}
1620
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
22
"token": "asdasdjuteoinbjnlkrutpeoplp.fkgcldfooklisfgsdlafhlfreFGTRydegsJJKGHURTDSwaerqsdfdfsgtJFHDfbgsDASDASDFERGDFBGsdfsdfSFQAWSEAZBBVJNHGJdfghfghSERWSFSVXBGFDgtDRTDGFJHJKykjHjHBKJfyjutygj_bLJyuhHUIOgJKBLnoOUiohuiGh_JKBjkGj-guiGhfu",
3-
"url": "http://localhost/factorioProcessHub"
3+
"url": "http://localhost/factorioProcessHub",
4+
"rcon_password": ""
45
}

0 commit comments

Comments
 (0)