Compare commits

...
25 Commits
Author SHA1 Message Date
miniduikboot 7b341bea14 Update docker container to I.Http 0.5
Also update the documentation to deal with the new default port and
clarify some stuff
2023-07-15 13:46:58 +02:00
miniduikboot af371c92ef add another version code to the pile 2023-07-15 12:34:29 +02:00
miniduikboot ff49e895ec make stylecop happy 2023-06-15 22:38:03 +02:00
miniduikboot 0e9fb4b41c Bump version to 1.8.3 2023-06-15 22:38:03 +02:00
miniduikboot 4f00bf1ee7 Add GameVersion for 2023.6.13
There seem to be no functional changes
2023-06-15 22:38:03 +02:00
miniduikboot a519c0daed Allow multiple SetName commands per CheckName
Some mods use SetName to set player-specific names, for example to set
player-specific roles. When Anticheat is disabled, this should be
allowed for feature-parity with officials.
2023-06-01 19:39:46 +02:00
yukieiji 1f98102e5a update:config 2023-05-23 21:39:09 +02:00
yukieiji 93fdc83ce7 refactor:ConnectionTimeout 2023-05-23 21:39:09 +02:00
yukieiji e29552ca28 refactor:SpawnInTime to config 2023-05-23 21:39:09 +02:00
yukieiji 8eee7f888f feat:timeout config 2023-05-23 21:39:09 +02:00
miniduikboot a77e4e17c2 Bump version to 1.8.2 2023-04-09 16:54:38 +02:00
danbudworthmead 9ebf5cd8e9 Adding missing 2023.3.13 version for android 2023-03-30 21:29:37 +02:00
miniduikboot 4ffca69714 Update to 2023.3.28 2023-03-28 20:15:11 +02:00
miniduikboot dede1c5b09 Reorder GameFull and GameStarted join errors
If a game is in progress, a player can't join it anyway and spam-joining
to see if a spot becomes available is useless. So the GameFull error is
more important than the GameStarted error, therefore reorder them.

Closes: #518
2023-03-08 20:46:29 +01:00
miniduikboot b31e3bf1e3 Add network version for 2023.2.28 2023-03-02 20:04:40 +01:00
miniduikboot c9bb8323f4 Add missing game keywords
These have been added in 2021.6.30, but this has only now been
problematic because Impostor.Http requires this array to be accurate
2023-02-14 23:29:25 +01:00
miniduikboot 1521410e79 Add a warning for using the default PublicIp
This is a misconfiguration in most cases and it breaks Impostor.Http.
Throw a warning so that people know that they should return to the
install instructions.
2023-02-14 23:26:32 +01:00
miniduikboot be8e4a49f0 Merge pull request #512 from Impostor/fix/docs-n-docker
Various improvements to the Dockerfile and the docs
2023-02-14 23:26:09 +01:00
miniduikboot 631e994759 Prepare for 1.8.1
This will be a release focused on setup convenience
2023-01-30 00:06:18 +01:00
miniduikboot c06916084e Rewrite Running-the-server.md
- Multi-server is removed from the intro
- Add Impostor.Http stuff
- Stress the importance of public ip
2023-01-30 00:04:55 +01:00
miniduikboot c9c044365a Dockerfile: install Http plugin in separate folder
Some people mount a folder on the plugin directory. This is fine, but
our sneaky Impostor.Http install method won't work here. So put it in a
different folder and prepend our folder to the plugin search path.

The number 76 has been randomly picked using dice
2023-01-29 22:58:30 +01:00
miniduikboot 5ab4bf70da Dockerfile: [[ -> [
[[ is a bash extension and is not supported by posix sh, throwing an
error. [ is supported and does enough
2023-01-29 22:57:05 +01:00
bkloosterboer 58c8bdec26 systemd template and instructions (#508)
* systemd template and instructions

* clarify some intsructions, change a few systemd paramters

* change targets
2023-01-22 23:29:22 +01:00
miniduikboot 5e080b290b Add Impostor.Http to the Docker image (#509)
Adding plugins to the docker image is pretty hard as you need to install
ASP.Net Core and add the plugin. As Impostor.Http has become pretty much
mandatory, install the plugin by default.
2023-01-20 15:25:22 +01:00
miniduikbootandjs6pak 97390a0882 Automatically add ASP.NET Core to the library path (#507)
Currently Impostor.Http is becoming an almost mandatory plugin. Because
it depends on ASP.Net, many people who fail to add the required path to
their config will run into an error. Help them by automatically adding
ASP.NET Core.

Also .NET updates every now and then and updating the version number in
the config.json is annoying me.

This commit uses the fact that ASP.NET Core DLL's are in a sibling folder
to the .NET runtime and should therefore work on most setups unless
they've installed ASP.NET Core in a very weird way.

* Fix casing

Co-authored-by: js6pak <kubastaron@hotmail.com>
2023-01-20 15:23:33 +01:00
17 changed files with 206 additions and 66 deletions

No files matched your search

+13 -3
View File
@@ -30,12 +30,22 @@ RUN case "$TARGETARCH" in \
arm) NETCORE_PLATFORM='linux-arm';; \
*) echo "unsupported architecture"; exit 1 ;; \
esac && \
[[ $VERSIONSUFFIX = "none" ]] && VERSIONSUFFIX=; \
[ $VERSIONSUFFIX = "none" ] && VERSIONSUFFIX=; \
dotnet publish -c release -o /app -r "$NETCORE_PLATFORM" -p:VersionSuffix="$VERSIONSUFFIX" --no-restore ./src/Impostor.Server/Impostor.Server.csproj
# Final image.
FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/runtime:7.0
FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /app
COPY --from=build /app ./
EXPOSE 22023/udp
# Add Impostor.Http as a default built-in plugin
ADD https://github.com/Impostor/Impostor.Http/releases/download/v0.5.0/Impostor.Http.dll /app/builtin-plugins/
# Make it listen to 0.0.0.0 to expose it to the outside world.
ENV IMPOSTOR_HTTP_HttpServer__ListenIp=0.0.0.0
# Override ASPNETCORE_URLS to stop warning.
ENV ASPNETCORE_URLS=
# Enable the built-in plugin folder. Use a high number to prevent conflicts with existing configurations
ENV IMPOSTOR_PluginLoader__Paths__76=/app/builtin-plugins
EXPOSE 22023/tcp 22023/udp
ENTRYPOINT ["./Impostor.Server"]
+33 -15
View File
@@ -1,34 +1,49 @@
# Running the server
There are currently two modes to run the Impostor server. The first way, Single Server, is the simplest one, can handle up to a few hundred simultaneous players, and is the one you should probably use. Multi-Server mode will distribute players across other servers and is intended for advanced users.
There are currently two install methods for Impostor: You can install it normally or inside of a Docker container. If you do not have a particular preference, we recommend the normal installation over the Docker container method.
## Single server
## General remarks for both install methods
### Without Docker
This section applies to both the normal installation as well as the Docker (Compose) installation
1. Install the [.NET 7.0 runtime](https://dotnet.microsoft.com/download/dotnet/7.0). Installing the SDK also works, but is not necessary unless you plan on developing Impostor or Impostor plugins. If you're asked to pick between the normal, desktop or server runtime, the normal runtime is enough, but some plugins may require the ASP.NET Core Runtime as well.
2. Find the [latest release](https://github.com/Impostor/Impostor/releases) or the [latest CI build](https://nightly.link/Impostor/Impostor/workflows/ci/master).
3. Download the version for your OS (linux/win/osx). Impostor is built for multiple CPU-architectures, you most likely want the x64 version, unless you are running on a Raspberry Pi or another device with an ARM processor.
4. Extract the zip.
5. Modify `config.json` to your liking. Documentation can be found [here](Server-configuration.md) _(this step is mandatory if you want to expose this server to other devices)_
To connect to the server, you need to configure and install a region file on https://impostor.github.io/Impostor/
Among Us connects to the server using two network services: the (TCP) HTTP service points Among Us to the UDP service, then the UDP service hosts the actual game traffic. Because of this, Impostor uses port 22023 using **both** the TCP and UDP protocols.
As the phone version of Among Us requires this HTTP connection to be secure, we recommend using a HTTP reverse proxy to terminate SSL on the HTTP service. Setup instructions for this are in the [Impostor.Http readme](https://github.com/Impostor/Impostor.Http#readme).
Depending on your host you may also need to port forward Impostor to the internet or pass Impostor traffic by your firewall. Port 22023 UDP needs to be accessible for everyone that wants to play on the server, then you also need to portforward your HTTP reverse proxy or port 22023 TCP if you don't use a reverse proxy. As port forwarding changes per host or router configuration, port forwarding is not covered by this guide.
## Normal installation
1. Install [.NET 7.0](https://dotnet.microsoft.com/download/dotnet/7.0). We recommend either the ASP.NET Core Runtime or the SDK. The SDK is necessary in case you want to develop Impostor or Impostor plugins.
2. Download the [latest release](https://github.com/Impostor/Impostor/releases) or the [latest CI build](https://nightly.link/Impostor/Impostor/workflows/ci/master). Note that Impostor is built for multiple CPU-architectures and operating systems, you most likely want the x64 version, unless you are running on a Raspberry Pi or another device with an Arm processor.
3. Extract the zip.
4. Download the [Impostor.Http](https://github.com/Impostor/Impostor.Http) plugin and put it in your `plugins` folder. Please note the Reverse Proxy configuration: you either need to configure a reverse proxy to terminate SSL or expose the service to the world by changing ListenIp.
5. Modify `config.json` to your liking. Documentation can be found [here](Server-configuration.md). You need to at least change `PublicIp` to the address people will connect to your server to.
6. Run `Impostor.Server` (Linux/macOS) or `Impostor.Server.exe` (Windows)
7. (OPTIONAL - Linux) Configure a systemd definition file and enable the service to start on boot - [systemd configuration](Server-configuration.md#systemd)
Depending on your host you may also need to port forward Impostor to the internet. By default Impostor uses port **22023** and the **UDP** protocol. As port forwarding changes per host or router configuration, port forwarding is not covered by this guide.
To connect to the server, you need to configure a region file on https://impostor.github.io/Impostor/
### Using Docker
## Using Docker
[![Docker Image](https://img.shields.io/docker/v/aeonlucid/impostor?sort=semver)](https://hub.docker.com/r/aeonlucid/impostor)
[![Docker Image](https://img.shields.io/docker/v/aeonlucid/impostor/nightly)](https://hub.docker.com/r/aeonlucid/impostor)
Docker is a program that allows you to run programs like Impostor in a container.
After installing Docker, you can just start a Docker container with `docker run`:
```
docker run -p 22023:22023/udp aeonlucid/impostor:nightly
docker run -p 127.0.0.1:22023:22023/tcp -p 22023:22023/udp -e IMPOSTOR_Server__PublicIp=your.public.ip.here aeonlucid/impostor:nightly
```
### Using Docker Compose
Please replace `your.public.ip.here` with the public IP address of your server. This is the address Among Us will try to reach your client at.
To configure the docker container, either use environment variables or mount config.json in your container.
## Using Docker Compose
Docker Compose allows you to start a Docker container using a prefined configuration. This is an example configuration you can continue on:
```
version: '3.4'
@@ -38,7 +53,10 @@ services:
image: aeonlucid/impostor:nightly
container_name: impostor
ports:
- 127.0.0.1:22023:22023/tcp
- 22023:22023/udp
environment: # Either configure Impostor using environment variables or mount a copy of config.json
- IMPOSTOR_Server__PublicIp=your.public.ip.here
volumes:
- /path/to/local/config.json:/app/config.json # For easy editing of the config
- /path/to/local/plugins:/app/plugins # Only needed if using plugins
+66
View File
@@ -93,3 +93,69 @@ IMPOSTOR_Server__ListenPort=22023
IMPOSTOR_AntiCheat__Enabled=true
IMPOSTOR_AntiCheat__BanIpFromGame=true
```
# systemd
Linux users will likely want to create a systemd service definition to manage running the Impostor application. Benefits to using a systemd service include the following:
- The server process can automatically restart if the process dies
- Impostor can be set to start on boot (handy if you do system updates regularly)
- You can use systemd targets to ensure the process doesn't start until the system dependencies are met
Using your favorite text editor, create the following service file:
```
sudoedit /etc/systemd/system/impostor.service
```
Modify the following template to your needs and populate the service file.
```
[Unit]
Description=Impostor private Among Us server - https://github.com/Impostor/Impostor
[Service]
# Directory where Impostor is installed
WorkingDirectory=/opt/impostor
# Path to Impostor binary
ExecStart=/opt/impostor/Impostor.Server
Restart=always
# Restart service after 10 seconds if the dotnet service crashes
RestartSec=10
KillSignal=SIGTERM
SyslogIdentifier=impostor
# User and group that will run the Impostor server process -- ensure that user is allowed to execute the binary
User=impostor
Group=impostor
TimeoutStopSec=10
[Install]
# Wait until most system services have started before starting Impostor
After=multi-user.target
WantedBy=multi-user.target
```
Reload all systemd unit files to source in the new file you've created.
```
sudo systemctl daemon-reload
```
Start the service.
```
sudo systemctl start impostor.service
```
Check the log for the service and verify it has started correctly -- Hint: Use the Q key to quit out of journalctl.
```
sudo journalctl -u impostor.service
```
If everything has started correctly, ensure the service is set to start on boot.
```
sudo systemctl enable impostor.service
```
+1 -1
View File
@@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<LangVersion>11</LangVersion>
<VersionPrefix>1.8.0</VersionPrefix>
<VersionPrefix>1.8.4</VersionPrefix>
<VersionSuffix>dev</VersionSuffix>
<EnforceCodeStyleInBuild Condition="$(MSBuildProjectName)!='Hazel'">true</EnforceCodeStyleInBuild>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
+11
View File
@@ -0,0 +1,11 @@
namespace Impostor.Api.Config
{
public class TimeoutConfig
{
public const string Section = "Timeout";
public int SpawnTimeout { get; set; } = 2500;
public int ConnectionTimeout { get; set; } = 2500;
}
}
@@ -21,6 +21,9 @@ namespace Impostor.Api.Innersloth
SpanishEU = 1024,
Arabic = 32,
Polish = 128,
SChinese = 65536,
TChinese = 131072,
Irish = 262144,
Other = 1,
}
}
-8
View File
@@ -1,8 +0,0 @@
namespace Impostor.Server
{
internal static class Constants
{
public const int SpawnTimeout = 2500;
public const int ConnectionTimeout = 2500;
}
}
@@ -513,36 +513,40 @@ namespace Impostor.Server.Net.Inner.Objects
}
else
{
if (!RequestedPlayerName.Any())
if (RequestedPlayerName.Any())
{
_logger.LogWarning($"Client sent {nameof(RpcCalls.SetName)} for a player that didn't request it");
return false;
}
var expected = RequestedPlayerName.Dequeue();
var expected = RequestedPlayerName.Dequeue();
if (Game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.PlayerName == expected))
{
var i = 1;
while (true)
if (Game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.PlayerName == expected))
{
var text = expected + " " + i;
if (Game.Players.All(x => x.Character == null || x.Character == this || x.Character.PlayerInfo.PlayerName != text))
var i = 1;
while (true)
{
expected = text;
break;
}
var text = expected + " " + i;
i++;
if (Game.Players.All(x => x.Character == null || x.Character == this || x.Character.PlayerInfo.PlayerName != text))
{
expected = text;
break;
}
i++;
}
}
if (name != expected)
{
_logger.LogWarning($"Client sent {nameof(RpcCalls.SetName)} with incorrect name");
await SetNameAsync(expected);
return false;
}
}
if (name != expected)
else
{
_logger.LogWarning($"Client sent {nameof(RpcCalls.SetName)} with incorrect name");
await SetNameAsync(expected);
return false;
if (await sender.Client.ReportCheatAsync(RpcCalls.SetName, $"Client sent {nameof(RpcCalls.SetName)} for a player that didn't request it"))
{
return false;
}
}
}
@@ -23,6 +23,11 @@ namespace Impostor.Server.Net.Manager
{
GameVersion.GetVersion(2022, 11, 1), // 2022.12.8
GameVersion.GetVersion(2022, 11, 9), // 2022.12.14
GameVersion.GetVersion(2022, 12, 2), // 2023.2.28
GameVersion.GetVersion(2023, 1, 11), // 2023.3.28s
GameVersion.GetVersion(2023, 3, 13), // 2023.3.28a
GameVersion.GetVersion(2023, 4, 21), // 2023.6.13
GameVersion.GetVersion(2023, 5, 20), // 2023.7.11
};
private readonly ILogger<ClientManager> _logger;
@@ -36,6 +36,14 @@ namespace Impostor.Server.Net
endpoint.Port,
_serverConfig.ResolvePublicIp(),
_serverConfig.PublicPort);
// NOTE: If this warning annoys you, set your PublicIp to "localhost"
if (_serverConfig.PublicIp == "127.0.0.1")
{
_logger.LogWarning("Your PublicIp is set to the default value of 127.0.0.1.");
_logger.LogWarning("To allow people on other devices to connect to your server, change this value to your Public IP address");
_logger.LogWarning("For more info on how to do this see https://github.com/Impostor/Impostor/blob/master/docs/Server-configuration.md");
}
}
public async Task StopAsync(CancellationToken cancellationToken)
@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading;
using System.Threading.Tasks;
using Impostor.Api.Net;
@@ -13,11 +13,13 @@ namespace Impostor.Server.Net.State
{
private readonly ILogger<ClientPlayer> _logger;
private readonly Timer _spawnTimeout;
private readonly int _spawnTimeoutTime;
public ClientPlayer(ILogger<ClientPlayer> logger, ClientBase client, Game game)
public ClientPlayer(ILogger<ClientPlayer> logger, ClientBase client, Game game, int timeOutTime)
{
_logger = logger;
_spawnTimeout = new Timer(RunSpawnTimeout!, null, -1, -1);
_spawnTimeoutTime = timeOutTime;
Game = game;
Client = client;
@@ -41,7 +43,7 @@ namespace Impostor.Server.Net.State
public void InitializeSpawnTimeout()
{
_spawnTimeout.Change(Constants.SpawnTimeout, -1);
_spawnTimeout.Change(_spawnTimeoutTime, -1);
}
public void DisableSpawnTimeout()
+10 -10
View File
@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading;
using System.Threading.Tasks;
using Impostor.Api.Games;
@@ -166,14 +166,6 @@ namespace Impostor.Server.Net.State
}
}
// Check if;
// - The player is already in this game.
// - The game is full.
if (player?.Game != this && _players.Count >= Options.MaxPlayers)
{
return GameJoinResult.FromError(GameJoinError.GameFull);
}
if (GameState == GameStates.Starting || GameState == GameStates.Started)
{
return GameJoinResult.FromError(GameJoinError.GameStarted);
@@ -184,11 +176,19 @@ namespace Impostor.Server.Net.State
return GameJoinResult.FromError(GameJoinError.GameDestroyed);
}
// Check if;
// - The player is already in this game.
// - The game is full.
if (player?.Game != this && _players.Count >= Options.MaxPlayers)
{
return GameJoinResult.FromError(GameJoinError.GameFull);
}
var isNew = false;
if (player == null || player.Game != this)
{
var clientPlayer = new ClientPlayer(_serviceProvider.GetRequiredService<ILogger<ClientPlayer>>(), client, this);
var clientPlayer = new ClientPlayer(_serviceProvider.GetRequiredService<ILogger<ClientPlayer>>(), client, this, _timeoutConfig.SpawnTimeout);
if (!_clientManager.Validate(client))
{
+2 -2
View File
@@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using System.Threading.Tasks;
using Impostor.Api;
using Impostor.Api.Innersloth;
@@ -76,7 +76,7 @@ namespace Impostor.Server.Net.State
// Player can refuse to be kicked and keep the connection open, check for this.
_ = Task.Run(async () =>
{
await Task.Delay(Constants.ConnectionTimeout);
await Task.Delay(_timeoutConfig.ConnectionTimeout);
if (player.Client.Connection.IsConnected && player.Client.Connection is HazelConnection hazel)
{
+4 -1
View File
@@ -30,6 +30,7 @@ namespace Impostor.Server.Net.State
private readonly HashSet<IPAddress> _bannedIps;
private readonly IEventManager _eventManager;
private readonly CompatibilityConfig _compatibilityConfig;
private readonly TimeoutConfig _timeoutConfig;
public Game(
ILogger<Game> logger,
@@ -41,7 +42,8 @@ namespace Impostor.Server.Net.State
GameFilterOptions filterOptions,
ClientManager clientManager,
IEventManager eventManager,
IOptions<CompatibilityConfig> compatibilityConfig)
IOptions<CompatibilityConfig> compatibilityConfig,
IOptions<TimeoutConfig> timeoutConfig)
{
_logger = logger;
_serviceProvider = serviceProvider;
@@ -59,6 +61,7 @@ namespace Impostor.Server.Net.State
_clientManager = clientManager;
_eventManager = eventManager;
_compatibilityConfig = compatibilityConfig.Value;
_timeoutConfig = timeoutConfig.Value;
Items = new ConcurrentDictionary<object, object>();
}
@@ -27,6 +27,19 @@ namespace Impostor.Server.Plugins
CheckPaths(pluginPaths);
CheckPaths(libraryPaths);
// Add library path for ASP.NET Core. This is useful for plugins that depend on ASP.NET Core,
// like Impostor.Http. The path contains the .NET version number, so it changes regularly.
var aspNetPath = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
.Replace("Microsoft.NETCore.App", "Microsoft.AspNetCore.App");
if (Directory.Exists(aspNetPath))
{
libraryPaths.Add(aspNetPath);
}
else
{
Logger.Information("ASP.NET Core not installed, this may cause issues if you have plugins that depend on it");
}
var rootFolder = Directory.GetCurrentDirectory();
pluginPaths.Add(Path.Combine(rootFolder, "plugins"));
+2 -1
View File
@@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -99,6 +99,7 @@ namespace Impostor.Server
services.Configure<AntiCheatConfig>(host.Configuration.GetSection(AntiCheatConfig.Section));
services.Configure<CompatibilityConfig>(host.Configuration.GetSection(CompatibilityConfig.Section));
services.Configure<ServerConfig>(host.Configuration.GetSection(ServerConfig.Section));
services.Configure<TimeoutConfig>(host.Configuration.GetSection(TimeoutConfig.Section));
services.AddSingleton<ClientManager>();
services.AddSingleton<IClientManager>(p => p.GetRequiredService<ClientManager>());
+4
View File
@@ -9,6 +9,10 @@
"Enabled": true,
"BanIpFromGame": true
},
"Timeout": {
"SpawnTimeout": 2500,
"ConnectionTimeout": 2500
},
"Compatibility": {
"AllowFutureGameVersions": false,
"AllowVersionMixing": false