Impostor 1.10.8 introduced PacketSize as a category, which was added in
front of "Other". This caused the value of "Other" to shift, which is a
problem for AC checks. Let's prevent making this mistake again in 1.10.9
Previous commit already moved the Other category back, this commit puts in the note for future developers
* Deserialize gamecode as packed in PackedGameDataTo
Most packets use a normal 32 bit int but not PackedGameDataTo. Instead,
Innersloth decided to waste a byte by using WritePacked. As v2 game
codes are always negative, this is less efficient, but alas.
It was documented in the pseudocode and I didn't spot the difference
when reviewing the implementation, so I made this mistake when
deduplicating this code.
Test plan:
- Start EHR on at least 2 clients
- Use the game mode "Natural Disasters"
- Observe that pixelated blobs are visible for all players, not just the host
* uopt: stop parsing code to string
* Address review comments
* Add GameFilters interface
* Add Newtonsoft.Json
Used by InnerSloth
* Port 2025.3.25 Data
* Generate OptionNames
* Fix missing CategorizedOptionNames
* Remove Newtonsoft.Json
* Add missing GameFilterList
* Basic support for new filters
* Add FiltersController
Server need to tell clients its filters
* Add Tag filter in filtergames
* Add GameTags in legacy game options
* Correctly deserialize Filters
* Minor text fixes
---------
Co-authored-by: miniduikboot <mini@duikbo.at>
* Added an RPC packet size anti-cheat
* Support PackedGameDataTo
* Move packet size check to HazelConnection
* Update PacketSizeLimit to 1153 and add anti-cheat docs
* Change default to value determined on officials
Thanks Niko for doing the research
---------
Co-authored-by: miniduikboot <mini@duikbo.at>
Co-authored-by: NikoCat233 <139348239+NikoCat233@users.noreply.github.com>
On January 21 Innersloth released a document that details a few new
features. One of these are host chat commands: any chat message that
starts with "/cmd" is forwarded to the host and to the host only.
Implement this feature in Impostor too for implementation parity.
For more info, see their GitHub page:
https://github.com/Innersloth-LLC/AmongUsModdingInformation
From their Discord:
Admin has pushed hotfix v17.1.2 for mobile players! minor changes to the ad rewards to the daily cap (subject to future change) and updated the screen to clarify when the daily cap is reset.
The new Unity version used by Among Us 16.0.5 disables the
"InsecureHttpOption", which blocks UnityWebRequests via HTTP. Therefore
all Impostor servers should now switch to HTTPS.
https://docs.unity3d.com/2022.3/Documentation/ScriptReference/InsecureHttpOption.html
Thanks to TianMengLucky for reporting this and NikoCat233 for
identifying the cause
Among Us always adds a constant amount of roles to this dict, so it
doesn't make sense to clear this dictionary every time.
Furthermore, previously it was possible to trigger a
ConcurrentModificationException when running Deserialize in parallel
with Serialize. This should no longer happen, as new keys are no longer added
It is possible to spawn invalid network objects without an attached
PlayerInfo, and Impostor will throw exceptions everywhere if you happen
to spawn one. Officials do allow spawning objects like this, so allow it
in Impostor for compatibility reasons
For some network objects, like PlayerControl, we expect that there is an
PlayerInfo object associated to them. If there isn't, throw an exception
in this AC category
Force(.*)Async will perform the same function as \1Async but without
throwing exceptions. The old API is maintained for backwards
compatibility reasons.
Murder checks are now shared with the main function that handles
CheckMurder, as ProtectPlayerAsync and ExileAsync aren't used in the
code I didn't make a similar change there. Checks were also synced
between both methods
This prevents situations where a player that requested red has a
different color when rejoining because red is the default color of a
PlayerInfo object. This is most noticeable if the host is late with
rejoining, and a lot of players are alreading in WaitingForHost limbo.
When the host finally rejoins, they will not assign Red immediately to
players that requested Red as it is "in use", and instead assign the
next color.
By recording and restoring this is avoided, and players tend to get
their own colors back in most cases.
This is not something that officials do at the moment, but I don't think
this has an impact on mods, as a normal checkcolor/setcolor cycle will
take place as usual.
These are no longer used, so warn people who do want to edit them.
I don't foresee these getting removed soon though, as we do want to kick
players on old versions for having an old game version
To prevent needing to pull in Impostor.Hazel, use an extension method
instead.
Thanks Niko for researching this part
Co-Authored-By: Niko233 <139348239+NikoCat233@users.noreply.github.com>
* Add diagnostic message to test HTTP server
This makes it possible to diagnose if the reverse proxy setup is working
correctly or if the game configuration is wrong
* Print console log as well
Only print it once to prevent console spam
* Update src/Impostor.Server/Http/HelloController.cs
Co-authored-by: js6pak <me@6pak.dev>
---------
Co-authored-by: js6pak <me@6pak.dev>
I've checked Impostor for issues that are similar to #664, and found
this one: if mods add a custom rpc on PlayerPhysics, Impostor will check
ownership of it, which isn't intentional.
Mods may send RPC's on a ShipStatus that aren't broadcasts. Previously
Impostor would forbid that, which doesn't make sense to me. By moving
down the check it'll allow mods to broadcast RPC's on ShipStatus.
Reported-By: xtracube
When a client disconnects without ever having joined a game, it leaves
behind an empty game on the server. Remove these when a player
disconnects.
Co-Authored-By: js6pak <me@6pak.dev>
* implemented the sequence ID
* implemented the sequence ID for the player outfits
the sequence ID in the set call must be greater than that stored on the client otherwise the client disregards the set call.
* make sequence IDs internal
* added space after closing brace
* make the sequence ID addition +5
Base game doesn't have a specific message for it so it results in a generic "left the game due to error" but it's still better than the default "left the game".
This also allows client side mods to fix the message.
DisconnectReason.Hacking has been broken in base game for a long time so replace it with a custom message.
Also add a random support code for easier debugging in case of false positives.
One issue with the ColorLimits checks is that it didn't account for mods
that add extra colors, this is fixed by checking if the route followed
is plausible instead of mimicking client logic and only accepting a
single answer that it expected. A false negative is possible where the
host decides to wrap back to the front but there are still custom colors
available at the end of the list. This is acceptable because Impostor
doesn't currently know the amount of colors available and this issue
isn't major enough to ask all mod authors to declare their custom color
amount to the server.
As extra colors should now be handled by this code, it makes sense to
change the category of the unknown colors check to ProtocolExtensions.
For these mods an exemption of the ColorLimits category is no longer
necessary.
Note that mods that allow duplicate colors that do not use a custom rpc
to set colors can only be supported by disabling the ColorLimits
category, this was already the case and I don't think it can be unified
with the existing check.
This commit does what official servers do:
- despawn the PlayerInfo if someone disconnects while in the lobby
- despawn all PlayerInfos at the end of a game when the EndGame screen
is shown. At this point a lot of other netobjects are destroyed as well,
with the PlayerInfos generally done first.
Looks like Innersloth added this but hasn't actually used this. Weird..
When sent it makes the new host perform a full rejoin, which gums up
Impostor's spawning logic. Fixing that causes the client to gum itself
up. Sigh.
After some testing it seems like host migration still works fine, so
this investigation wasn't needed. Committing for posterity.
Co-Authored-By: js6pak <me@6pak.dev>
In 2024.6.18 Innersloth changed the storage location of the PlayerName
from PlayerInfo to PlayerOutfit. If we don't set the PlayerName, we'll
send an incomplete PlayerInfo to new players, so new players are unable
to stay connected as they will not receive complete PlayerInfo objects
before a timeout in the client activates.
Because we publish PlayerName in the API, we can't completely remove
the PlayerName field from PlayerInfo. We also use it internally in a few
places, so I don't this is worth removing.
As tasks used to be part of the GameData, 2024.6.18 has moved them to
the PlayerInfo. Because they are now called on the PlayerInfo of the
correct player, the playerId field in the RPC is no longer necessary.
2024.6.18 adds a NetId field *in front* of the existing fields to help link back to the PlayerInfo. We don't actually need this NetId and assume it's called on the correct PlayerControl, so we ignore it.
In 2024.6.18 Innersloth promoted PlayerInfo to its own network object, and gave it to the server. InnerGameData is now a container that holds these players. This commit implements the changes necessary to handle these separate PlayerInfo network objects.
To prevent excessive modifications in the codebase, which is prone to
issues if a callsite is missed, automatically do this using properties.
Keep the access modifiers intact for now.
I'm seeing multiple warnings in my server log about forbidden scene
changes. Unfortunately this warning does not include the actual scene
that was triggering the issue, which makes diagnosis/remediation difficult.
Additionally change this logging call to use names suitable for
structured logging.
The default ListenIp for the base game server has been set to 0.0.0.0 in
config.json for as long as I remember, and a different value is only
sporadically used. I remember a case where someone was fancy with Split
DNS. 0 is better as a default than localhost, so change the code
accordingly to aligh with config.json
Fixes CVE-2024-30105 (High 7.5/10)
https://github.com/advisories/GHSA-hh2w-p6rv-4g7w
Impostor doesn't use the affected
JsonSerializer.DeserializeAsyncEnumerable method as it doesn't accept
JSON formatted payloads, but the NU1903 warning is shown on all builds,
leading to warning fatigue.
Previously Impostor liked to kill exiled players server side to raise an
event. This is quite early, as the host will SetRole them to a ghost
role later.
However as PlayerInfo is server-owned by default in 2024.6.18, it starts
killing players client side. This caused meetings to immediately
conclude if the final impostor was voted out, ruining the cutscene.
So this commit makes Impostor wait for hosts to actually kill the player
using SetRole. Do set the LastDeathReason property though for players
using the API.
This item is only used in a LogTrace call, so it seems excessive to kick
a player on servers just for a log statement
Co-Authored-By: js6pak <me@6pak.dev>
There are various bugs in the 2024.6.18 implementation of host-authoritive
multiplayer such that I can't recommend players to use it. Fixing these
issues on the server side is impossible, and I can't smell remotely if
clients have applied the necessary fixes. The currently known bugs
include at least:
- Unable to join more than 8 players in a room
- Unable for new players to join if host switched from host authoritive
to server authoritive
- Host is unable to kill if it is in a host authoritive game while it
thinks it is in server authoritive mode
If Innersloth fixes this mode in future game patches, this option may be
reconsidered.
Some people were confused by config-full.json, thinking that this file
should be edited too. This is not the case and the values in this file
don't apply as it was only meant as an example, so rename the file to
make that more clear.
Also update this file to add the options from the Modular Anticheat
Currently, Impostor will show an "Client is in an invalid state."
message if a player tries to join a match where the host or the joining
player is using a version unknown to Impostor.
This message confused a *lot* of people, so this PR changes the API such
that if the version is not registered, the version itself is put in a
compatibility group and compared, assuming no other game versions are
compatible with it. This works fine in most cases, as Among Us network
versions generally increase over time.
Failure on 2222.2.2 (which is ancient at this point, so likely no longer
used) and future cases where Innersloth messes up (which is unlikely) is
an acceptable consequence to me.
Previously Impostor would just throw when a method was called on a
GameManager, but this caused issues with client mods that did just this,
even through vanilla never calls an RPC on GameManager.
This commit changes that throw statement to pass the exception to the
custom message handler/anticheat instead, which is also how it works for
the other NetObjects
When a player is kicked or banned from a game, the client is expected to
disconnect in response. When they decide not to *or* the disconnect
packet is lost, Impostor just silently disposes of the connection.
This does not remove them from ClientManager, which is how I tracked
this bug down.
By sending them a proper disconnect message, clients should have
received *a* disconnection message before dropping their connection.
Future work should split this entire method in removing players from a
game and processing kick/bans because the latter feature is not relevant
for other callers of this method.
Multiple guard clauses make the file harder to navigate, so put them in
a single guard clause with one validation rule per line. Some statements
in the file were already set up like this, so this commit makes it consistent
When a game has just been created, it does not yet have any players in
them, and as a result you can't get the host or its connection id when
this event is called. This makes it annoying to link between this event
and the IGameCreationEvent that came just before it.
Having this link is useful for the usecase of a game code allocation
plugin that allocates codes from a pool, and needs to return codes to
a pool if these codes weren't picked.
* Add extra configuration options for the anticheat
* Implement option to exempt hosts from AC checks
* Add AntiCheatConfig to InnerNetObject and friends
* Categorize calls in InnerNetObject.Anticheat
* Categorize other calls to ReportCheatAsync
* Update cosmetics AC handling
When Innersloth changed SetHat etc to SetHatStr as part of the cosmicube
update we accidentally created a few dead methods. Restore and update
the code.
* Push up cheat category to ReportCheatAsync
This makes it possible to log failed checks for diagnosis. Also much
cleaner now that we don't have to push AntiCheatConfig everywhere.
Should've done this immediately q.q
* Add back old version of ReportCheatAsync
some plugins used this method. affected plugins should rebuild after the
next impostor release
* Add documentation for modular anticheat
* Address comments
* Sort AntiCheatConfig keys
* Rework the option to allow cheating hosts
This option should actually be tristate: to not break host-only mods we
should disable the anticheat for hosts running host-only mods.
* Document CheatingHostMode
* Split Limits category in Color and Name Limits
- Update versions to the latest one
- Get rid of .gitmodules as we dumped that years ago
- Change ::set-output to output files as the former is slated for removal
We see that a lot of support tickets are caused by this default setting,
as it is one of the things that blocks connections to the server with no
obvious indication that this is happening. To make it easier for first
time users to set up Impostor, it is important that this setting is
changed.
Previously we also recommended against direct exposing due to security
reasons, but I believe this fear to be unfounded: Microsoft claims that
the Kestrel server is hardened against web server vulnerabilities and
supports its use both with and without a reverse proxy.[1]
We still recommend using reverse proxies if HTTPS support is needed, so
that section of documentation still remains. Setting the ListenIp to
127.0.0.1 is still recommended when using a reverse proxy to remove the
ability for people to connect directly, so we add it there as a recommendation.
[1]: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/when-to-use-a-reverse-proxy?view=aspnetcore-8.0
This RPC is still sent by clients, but no longer used by clients. As the
server can get the info it wants from LogicOptions instead, remove this
RPC to prevent people from using it accidentally
This can be triggered by both RPC 02 and a(nother) plugin calling
SyncSettings to force certain settings on the host. Users of this API
could cause this event to recurse by calling SyncSettingsAsync inside an
event handler, so we prevent such reasonable foreseeable misuse.
In games where players have a high ping, they can get disconnected if
they try and murder a player twice. If a player tries to kill a player
again while they are still under a cooldown from their previous kill,
cancel their request if the game is server authoritive and don't process
it anymore if the game is host authoritive
- IPlayerCheckMurderEvent now exists
- You can see if a kill was successful with IPlayerMurderEvent
- You can now see if host authority was requested with Game.IsHostAuthoritive
In 2023.10.24, vanilla started expecting that CheckMurder is handled on
the server. That is, unless the host is modded, then CheckMurder calls
are handled by the host as before
Innersloth has changed CNT from position/velocity to a queue of
positions. As a result, drop the velocity as well.
We're currently not tracking the current position of the player, so
we're just storing the last one
We had a nice year of backwards compatibility, but the changes in Fungle
are large enough that dropping support for old versions is the only
logical path forward
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.
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
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.
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
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.
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>
Now that our game version compatibility list is growing longer with
every game patch, we need a way to make sure people in a game run the
same version of the game. Mismatching game version can lead to weird
issues, especially if mods are involved.
- .NET download link was broken
- They also renamed their packages slightly, so update wording
- Add a note on port forwarding
- Add a note on setting up the region file
This is needed for mods that add tasks to standard maps, but also mods
that add custom maps: because their custom netobjects don't get
registered Impostor thinks people are still on the old map when people
switch to the custom map after playing a game.
* Upgrade to .NET 6
.NET 5 has gone EOL, so move to a supported version.
* Upgrade Docker container as well
* Update docs for .NET 6
* Re-add hack for System.IO.Pipelines
* Bump dependency versions
* Update the deps of the other projects too
* Only declare TargetFramework once
* Dockerfile: also copy over Directory.Build.props
* Cake: pick up target framework automatically
* Upgrade Cake as well
Because it is fine to add data to the end of messages the new fields
could be added to Message 1 just fine, but because Message 7 contains a
loop, we need to send a different message to old clients there.
Starting from version 2021.11.9, join errors no longer exist, instead a
client will show the message "An unknown error disconnected you from the
server". As a workaround, the connection is disconnected entirely when
an error occurs, which allows us to show a custom message.
Oversized nicknames can cause bigger issues, so it is desireable to
still block them. .Length counts codepoints, not bytes, which means
that 10 character Japanese nicknames, which are configurable ingame,
should still be allowed.
Before this commit, when the host of a game disconnects, the InnerPlayerInfo from the player is removed, which causes the new host to disconnect because of a deserialization error. This PR fixes this issue
Length and validity are checked also checked by the anticheat. In case
Impostor goes out of sync with the allowed characters again, this can
just be fixed by disabling the Anticheat.
Check for NullOrWhiteSpace is kept because an empty username could be annoying
When the Guardian Angel protects a player, the impostor that just missed
their kill gets back half of their cooldown. Keeping track of whether or
not the player was protected is more difficult due to how the Guardian
Angel is implemented, so instead we halve the minimum time between kill
in order to minimize false positives.
In 2021.11.9, the host now uses MurderPlayer instead of impostors.
Impostor now use CheckMurder to request the host to kill a player. This
allows the host to prevent the target of the Guardian Angel from dying.
However, if the impostor that is checking the kill is also the host, AU
internally processes the CheckMurder RPC and sends the MurderPlayer RPC
first, *then* it sends the CheckMurder RPC.
2021.6.30 added new fields, which aren't present on old clients.
This commit makes sure players on old versions are disconnected properly
instead of the server erroring internally.
* Improve error when client version is unsupported
In the default message that was used previously the user is asked to
upgrade his game. This is not always correct, as sometimes the Impostor
server is too old and should be updated instead. Therefore custom
disconnect messages are used that blames either the user or the server
operator, which is hopefully more accurate.
I've chosen not to include the game version that is supported by the
server in this message because the network version rarely matches the
advertised version in the main menu.
* Rewrite versionCompare switch case
Co-authored-by: js6pak <kubastaron@hotmail.com>
Co-authored-by: js6pak <kubastaron@hotmail.com>
This is used to hide players that are still selecting their spawn
location. If this is cancelled, players are left standing at the
location they were at when the last meeting was called, which is undesirable.
There is no significant performance difference: while accessing the
getters is slightly slower, this can be balanced against the cost of
setting the property. As this is also cleaner, switch to getters.
As Among Us is getting a lot of small network-compatible bugfix releases
nowadays, it doesn't seem necessary to maintain the table anymore.
Release notes state clearly which network version is supported and there
is limited support for old versions anyway.
The patcher has not been updated to support the new JSON format and is
less necessary now that JSON is used for the region file format.
The website also now has deeplinking support, so we point Android/iOS
people to the website now too as that is more convenient compared to the
previous methods.
This could lead to an AC disconnect if the host picked red and waited
for other players to rejoin before joining back himself. Before this
commit, the host would SetColor himself to Red, but this would be
flagged as all other players would have been set to Red as enums
initialize to 0 (= Red) by default.
After the host SetColor'd himself, the host will send over the color
array, which initializes player colors to -1. This commit follows AU by
also initializing the color to -1, preventing the AC from flagging the
duplicate colors.
Some mods add extra vents that don't yet exist, this commit checks if a
given vent exists and if it doesn't, throw an AC violation instead of
disconnecting the player
One downside is that the Enter/ExitVent events are no longer called, but
this would require the vent in that event to become nullable
* upgrade PlayerReportedBodyEvent to PlayerStartMeetingEvent
now triggers on host player actions as well
* update OnPlayerReportedBodyEvent in plugin example
This pr should give the plugin dev the option to receive all events to his liking without constraining it to a specific type at compile time
Co-authored-by: Weirdo <git.jonas@kamsker.at>
Co-authored-by: AeonLucid <aeonlucid@outlook.com>
* Ignoring .Vs folder
* Improved Gamemanager
- Retry code creation
- Async Node Lookup
* Switched back to old using order
* Removed IAsyncNodeLocator
* Found one more use of find
* deleted submodule
Co-authored-by: Weirdo <git.jonas@kamsker.at>
* Improved EventManager
Now it actually will order the event listeners on their priority. Also I've cleaned up the registering of temporary event listeners.
* Ignore new Impostor.Api library while loading plugins
* Fixed Dockerfile
* Update README
* Update README
* ✨ added list of recent used ips in the client
* rollbacked client version bump
* added combo clearing before loading new items
* Rewrite configuration
Co-authored-by: AeonLucid <aeonlucid@gmail.com>
If your pull request closes any issues, add them below with the `closes` keyword before them
Example: closes #101
See the following article for more information: https://docs.github.com/en/free-pro-team@latest/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword
We are always looking for people to help improve Impostor.
## Code
- If you are implementing or fixing an issue, please comment on the issue so work is not duplicated.
- If you want to implementing a new feature, create an issue first describing the issue so we know about it. We are always open for discussion or questions on [Discord](https://discord.gg/Mk3w6Tb).
- Don't commit unnecessary changes to the codebase or debugging code.
- Write meaningful commits or squash them.
- Please try to follow the code style of the rest of the codebase. An `.editorconfig` file has been provided to keep consistency.
- Stylecop is also enabled: please make sure your PR compiles without warnings.
## Pull requests
- Only make pull requests to the `dev` branch.
- Only implement one feature per pull request to keep it easy to understand.
- Expect comments or questions on your pull request from the project maintainers. We try to keep the code as consistent and maintainable as possible.
- Each pull request should come from a new branch in your fork, it should have a meaningful name.
- We try to respond to pull requests as fast as possible. If you think we might have missed it, let us know on [Discord](https://discord.gg/Mk3w6Tb).
The latest version supported is `2020.9.9`, both desktop and mobile.
Impostor is the first working **Among Us** private server, written in C#.
There are no special features at this moment, the goal is aiming to be as close as possible to the real server, for now. In a later stage, making modifications to game logic by modifying `GameData` can be looked at.
As Among Us is actively updated, you may want to use the latest build from the master branch if you want to play on the latest version of Among Us that supported by Impostor.
[Discord server for Impostor](https://discord.gg/Mk3w6Tb)
If you want to play on an olderversion of Among Us, you can download old releases from [here](https://github.com/Impostor/Impostor/releases/), however these versions are less supported.
## Features
Almost all standard features are implemented at this moment, except for public games. It is already possible to host and play private games.
- [x] Create game
- [x] Join game
- [x] Start game
- [ ] Find game
- [x] V1 GameCodes (AAAA)
- [x] V2 GameCodes (AAAAAA)
- [x] Kick player
- [x] Ban player
- [ ] Server redirection
- [ ] Server reselect
- All Among Us features are implemented. It is a full replacement for the official server.
- Plugin support.
- Server-sided anticheat.
## Installation
When hosting a server, make sure port **22023** is open and forwarded for **UDP**. It is not possible to use a different port because Among Us seems to have hardcoded 22023, even though the functionality for setting a port exists.
### Client
If you just want to play on a server hosted by someone else, you need to follow these instructions.
If you just want to play on a server hosted by someone else, you need to configure your client to connect to an Impostor server. Please go to [this website](https://impostor.github.io/Impostor) to set up your client by following the instructions for your OS there.
> W.I.P
### Server
### Server (Docker)
See the [docs](docs/Running-the-server.md) for instructions on how to set it up.
The solution contains the Impostor server and its dependencies, like Hazel and the plugin API. The server is built using [.NET 8](https://dotnet.microsoft.com/download/dotnet/8.0).
- [Rider](https://www.jetbrains.com/rider/) or [Visual Studio](https://visualstudio.microsoft.com/vs/) (Optional, only if you want the full IDE experience)
### Build using the CLI
```bash
cd src/Impostor.Server/
dotnet build
# Or if you want a single file, ready for production: (change linux-x64 to win-x64 if you use Windows)
The Impostor project is a reverse engineered and open source server for the game Among Us. The game itself is developed by [Innersloth](http://www.innersloth.com/) while this project is maintained by the community. This project was built out of frustration for the lack of server availability in certain regions and the inability for the core developer, [AeonLucid](https://github.com/AeonLucid), to join a public game. As of this time, it has not been officially endorsed by the studio.
## Can this be used with the mobile version of the game?
Yes, Impostor can be used with both the Android and iOS versions of the game. You can add a custom server via a link, you can do this using the [site](https://impostor.github.io/Impostor)
## Can this be used with the console version of the game?
Sadly not, as these don't allow adding custom servers.
## Can this be used with Among Us 3D/VR?
No, it's an entirely different game with a completely different network stack. So we'd need to develop another server completely from scratch. We're currently not interested in doing this.
## How can I get started?
See [Setting up your Server](Running-the-server.md) for more information on running the server and [Client Setup](https://impostor.github.io/Impostor/) for helping your friends join in!
If you're having issues with the server software, check the [Troubleshooting page](TROUBLESHOOTING.md).
Since Impostor 1.9.0 a HTTP service is included for matchmaking, which is required for clients to connect to the Impostor server.
Starting from Among Us 16.0.5, you need to set up HTTPS for players to connect to your server.
Unfortunately Impostor doesn't handle SSL certificates, so you need to set up a reverse proxy.
## Use a reverse proxy
A reverse proxy allows you to forward HTTP requests from users to multiple services. If you already have one, you should configure it to add Impostor.
If you have never set up a reverse proxy before, we recommend you to set up [Caddy](https://caddyserver.com/). It is easy to set up and comes with support for requesting SSL certificates out of the box.
To prevent people from connecting directly to Impostor, we recommend changing the "ListenIp" in the "HttpServer" section to "127.0.0.1". This makes sure people can't connect to your HTTP server other than via your reverse proxy. Keep the "ListenIp" in the "Server" section at "0.0.0.0" though, running the normal game traffic through a proxy is not supported.
### Caddy
To install Caddy, follow the [official installation guide](https://caddyserver.com/docs/install). Then use the following lines as your `Caddyfile` configuration file:
```
example.com # replace example.com with your domain name
reverse_proxy :22023
```
Now run `caddy run` in the folder with this Caddyfile and it should set up a server for you with a free SSL certificate.
If this works, you should set up [Caddy to run in the background](https://caddyserver.com/docs/running)
### Nginx
Nginx is an alternative to Caddy that is a bit harder to set up. If you already use Nginx, you can use our snippet to add Impostor:
<details><summary>Nginx configuration</summary>
```nginx
server{
listen443sslhttp2;
server_nameexample.com;# replace example.com with your domain name
# Assuming you're using Certbot, replace example.com with your domain name
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.
## General remarks for both install methods
This section applies to both the normal installation as well as the Docker (Compose) installation
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.
To connect to your Among Us version from another PC, you need to set up a HTTP reverse proxy to support HTTPS. If you're just running a version of Impostor for testing Setup instructions for this are in the [Http Server documentation](Http-server.md).
If you want to test if your Among Us HTTP server is working, open `http://localhost:22023` (assuming you're using the default settings, change the IP and port respectively) in a browser
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 8.0](https://dotnet.microsoft.com/download/dotnet/8.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/VPS with an Arm processor.
3. Extract the zip.
4. 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.
5. Run `Impostor.Server` (Linux/macOS) or `Impostor.Server.exe` (Windows)
6. Set up a reverse proxy to support HTTPS, so you can connect to your server from another device. See [reverse proxy configuration](Http-server.md)
7. (OPTIONAL - Linux) Configure a systemd definition file and enable the service to start on boot, see [systemd configuration](Server-configuration.md#systemd)
| **PublicIp** | `127.0.0.1` | This needs to the public IPv4 address of the server which you give to others to connect. You can find your IPv4 address [on this website](http://whatismyip.host/). Unless you are only planning to use Impostor privately, on your local network, you should change this to your public ip. It is also possible to use hostnames instead of IPv4 addresses, which will be resolved to IPv4 addresses. |
| **PublicPort** | `22023` | The public port of the server which you give to others to connect. (**This is the external port you configure on your router when port forwarding.**) Usually `22023`. |
| **ListenIp** | `0.0.0.0` | The network interface to listen on. If you do not know what to put here, use `0.0.0.0`. Since 1.2.2 it is also possible to use hostnames instead of IPv4 addresses, these must resolve to a valid IPv4 address. |
| **ListenPort** | `22023` | The listen port of the server, usually `22023`. For port forwarding purposes: this is an UDP port |
### HttpServer
Impostor has an Http Server that is used by recent versions of Among Us to connect to. See [the Http Server page](Http-server.md) for more details on how to set this up.
| **Enabled** | `true` | Whether the http server should be enabled. |
| **ListenIp** | `0.0.0.0` | The network interface to listen on. Use `127.0.0.1` if you use a reverse proxy or just run locally. Use `0.0.0.0` if you are directly exposing this server to the internet |
| **ListenPort** | `22023` | The listen port of this server. For port forwarding purposes, this is an TCP port. |
### AntiCheat
Impostor has an Anticheat that makes it possible to kick cheaters from games automatically. Note that the anticheat is tuned on the vanilla version of the game, so client-side modifications could trigger the Anticheat if you're playing with them.
| **Enabled** | `true` | Whether the anticheat should be enabled. |
| **BanIpFromGame** | `true` | When anticheat is enabled and a player is caught hacking, they will be kicked from the server. If this value is set to `true`, the player will be banned instead and will not be able to rejoin that specific game. |
| **AllowCheatingHosts** | `"Never"` | Configure whether hosts are allowed to cheat. "Never" forbids it, "Always" allows it. "IfRequested" allows hosts to cheat if they connect with the DisableServerAuthorityFlag set. |
| **AllowHostOnlyExtensions** | "IfRequested" | Configure whether [Host-Only extensions](https://github.com/Innersloth-LLC/AmongUsModdingInformation#host-only-mods) are allowed in all games ("Always"), +25 games only ("IfRequested") or by nobody ("Never") |
| **EnableGameFlowChecks** | `true` | Enable checks that check if certain actions are done in the appropriate order or at the appropriate moment in the game. This includes changing cosmetics while in game or murdering too fast. |
| **EnableInvalidObjectChecks** | `true` | Enables checks that check if network objects are spawned properly. Disabling this option also implies disabling EnableRoleChecks. |
| **EnableMustBeHostChecks** | `true` | Enables checks that check if players are the host before they can do actions that require them to be host of the game. This includes starting the game and spawning objects. |
| **EnableColorLimitChecks** | `true` | Enables checks that checks if players request colors that are already in use. |
| **EnableNameLimitChecks** | `true` | Enables checks that checks if player names have a length that is possible to set using the user interface. |
| **EnableItemLimitChecks** | `true` | Enables checks for item counts that cannot be exceeded in the official clients. |
| **EnableOwnershipChecks** | `true` | Enables checks that check if players are allowed to perform a certain action on themself or another player. |
| **EnableRoleChecks** | `true` | Enables checks that check if players have the correct role when performing certain role abilities like venting or murdering. |
| **EnableTargetChecks** | `true` | Enables checks that check if certain packets to everyone that should only have been sent to certain players or vice versa. This includes sending votes or network objects. |
| **EnableIdentifierChecks** | `true` | Enables checks that verify if the friendcode and puid a host claims for a player in their PlayerInfo match the ones known for that player. |
| **ForbidProtocolExtensions** | `true` | If disabled allows players to send network packets that go beyond the network packets sent by the vanilla game. This is necessary for most mods that need all players to install it. |
| **EnablePacketSizeChecks** | `true` | Enables checks that verify if network messages exceed the maximum allowed size. |
| **PacketSizeLimit** | `1203` | The maximum allowed size (in bytes) for a network message. The official servers of Among Us requires that a Hazel packet is < 1204 bytes, excluding headers. |
### Compatibility
Impostor has some compatibility options which allow some extra flexibility but may not work properly. Enabling any of these options is not recommended. When contacting support, please mention which of these options are enabled.
| **AllowFutureGameVersions** | `false` | Warning: Setting this option to `true` is unsupported and may cause issues when large updates to Among Us are released, but can be useful when a small patch is released. Allows future versions of Among Us to join your server. |
| **AllowHostAuthority** | `false` | Certain Among Us mods allow disabling some server-authoritative features, which also changes some code paths in the client. These code paths have not undergone as much testing and contain bugs, which can't be fixed from the Impostor side. Use with caution. |
| **AllowVersionMixing** | `false` | Allows players using different game versions to play in one lobby that have not been marked by the Impostor developers as compatible. |
### Debug
The Debug configuration is used to enable the game recorder. This is mostly useful when developing Impostor.
| **MinimumLevel** | `Information` | Minimum log level for a message to be printed. If a log entry is as severe or more severe than this level, it will be printed. From most severe to least severe: `Fatal`,`Error`, `Warning`, `Information`, `Debug`, `Verbose` |
| **Using** | `[]` | List of additional Serilog Sinks assemblies to load. |
| **WriteTo** | `[]` | Additional logging sinks. See the Serilog documentation or the example in this section. Serilog |
For more information, check the [Serilog.Settings.Configuration](https://github.com/serilog/serilog-settings-configuration) documentation.
For example, to add logging to a file, you should add the following snippet to your configuration:
```json
"Serilog":{
"Using":[
"Serilog.Sinks.File"
],
"WriteTo":[
{
"Name":"File",
"Args":{
"path":"logs/log.txt",
"rollingInterval":"Day"
}
}
]
}
```
Next to that, you also need to copy over Serilog.Sinks.File.dll from [NuGet](https://www.nuget.org/packages/Serilog.Sinks.File/). See the [Serilog.Sinks.File documentation](https://github.com/serilog/serilog-sinks-file#json-appsettingsjson-configuration) for a list of parameters that can be configured.
Other Serilog sinks are also supported, but are out of scope for this documentation.
## Config providers
### File
The `config.json` file contains all the configurable options.
### Environment variables
If you're unable to edit the `config.json` file, you can instead set Environment variables to configure Impostor. The general pattern for each variable is `IMPOSTOR_SectionName__VariableName`. For example, to disable the anticheat, you can set the environment variable `IMPOSTOR_AntiCheat__Enabled=false`. Here are some more examples:
```
IMPOSTOR_Server__PublicIp=127.0.0.1
IMPOSTOR_Server__PublicPort=22023
IMPOSTOR_Server__ListenIp=0.0.0.0
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.
Don't worry though, as this is the most thorough guide to help you!
## `./Impostor.Server: line 1: ELF: not found` (plus other errors)
No idea where you got that system. But we clearly do **NOT** support it.
## `cannot execute binary file: Exec format error`
Please check that you have downloaded the right version of Impostor, as we mantain two CPU architectures (x64 and ARM).
Unless you are running Impostor on a computer like the Raspberry Pi, you most likely want to use the x64 version.
## `./Impostor.Server: Permission denied`
This is an error related to Linux file permissions.
Some files do not hold their executable bit (the permission that allows them to run) during a download.
You can solve this by doing: `chmod +x Impostor.Server`
## Disconnected with `Your client is too new, please update your Impostor to play`
This happens when your game is too new for your copy of Impostor to support.
If you're using an Impostor release, check if there is a newer release available that supports your version. If this doesn't exist, you can try the [latest build from CI](https://nightly.link/Impostor/Impostor/workflows/ci/master).
If even that build doesn't work, you can try looking through the Pull Requests to see if there is a pending pull request that aims to update it to the next version, but note these may be unstable and may contain malicious code, as they haven't been vetted by the Impostor development team yet.
## Disconnected with `Please update your game to play on this server`
This happens when you're using a version of Impostor that is too new for your game version. You can download an older version from [the GitHub release page](https://github.com/Impostor/Impostor/releases). We however don't support older versions of Impostor with new API's and bugfixes so we recommend to update your game instead.
## Disconnected with `You are using an older version of the game`
You are using a version of Impostor that is not designed for the version of the game you're playing. The game does not really check who is outdated and blames it on the user. Newer versions (v1.5.0+) do warn correctly and send the correct message.
Look at which version of the game you're playing, which you can see in the top left corner of the main menu, then download an Impostor version for that game. Every [release on the release page](https://github.com/Impostor/Impostor/releases) shows which version of the game it is compatible with. If your game version is newer than the latest release, check if the [latest build from CI works](https://nightly.link/Impostor/Impostor/workflows/ci/master).
## Disconnected with `You disconnected from the server. Reliable Packet 1 ...`
Please double-check that you have followed the [Server Configuration](Server-configuration.md) correctly.
**NOTE: Your public ip does not start with `10`, `127` or `192`**
Also check if the port Impostor (ListenPort) is listening on is correctly port-forwarded for UDP (or TCP/UDP).
## `Could not load file or assembly...`
Please check that you only have **working** plugins in the `plugins` folder.
This error can be caused by non-plugin files or plugins that are not working correctly.
## Disconnected with `You disconnected from the server. If this happens often, check your network strength. This may also be a server issue`
Usually this means that Among Us couldn't connect to Impostor's HTTP server.
Open the address of your server in a web browser, it should show you a small page confirming that Impostor is available.
## My question is not yet answered and I'm still having problems!
That's unfortunate. Join the [Impostor Discord](https://discord.gg/Mk3w6Tb), ask your question there and we'll try to help you out. Note that we're not always available, so it may take some time to get an answer. To make answering your question easier, please add the following details:
- Which version of Impostor are you using?
- Which version or Among Us are you using?
- Which operating system are you running Impostor on?
- If you have console logs, attaching these will also help.
Sometimes we make incompatible changes to existing code. This document lists these changes and which changes you should make as a server administrator.
## Impostor 1.9.0
Previously we recommended using the Impostor.Http plugin for HTTP matchmaking. Because Among Us now relies on HTTP matchmaking, this plugin is now part of the default installation. As a result, you should change your server as follows:
- If you have Impostor.Http installed, you should remove that plugin. If you have changed the default settings, you need to move these changes to the [HttpServer section in config.json](Server-configuration.md#HttpServer).
- If you have plugins that required Impostor.Http's API (like Reactor.Impostor.Http), you should check that plugin for updates
- It is no longer necessary to add the ASP.NET Core folder to the PluginLoader's LibraryPaths
- [3. Add the Impostor.Api library](#3-add-the-impostorapi-library)
- [Quick](#quick)
- [Visual Studio](#visual-studio)
- [4. The plugin class](#4-the-plugin-class)
- [5. Adding an event listener](#5-adding-an-event-listener)
- [6. Registering the event listener](#6-registering-the-event-listener)
- [7. Build and run your plugin](#7-build-and-run-your-plugin)
- [8. Extra](#8-extra)
- [Event listeners](#event-listeners)
- [Dependency injection](#dependency-injection)
- [Server configuration](#server-configuration)
- [Using other libraries](#using-other-libraries)
- [Impostor versions](#impostor-versions)
- [9. Missing/invalid data or want more functions?](#9-missinginvalid-data-or-want-more-functions)
## 1. Install .NET SDK
Download and install the latest .NET SDK.
https://dotnet.microsoft.com/download
## 2. Create a C# project
The first step is creating a new C# project, it must be a **Class Library (.NET Standard)**. The target framework can be any of those compatible with .NET 8, but we recommend sticking with **.NET 8.0**.
For more information about compatibility, see https://docs.microsoft.com/en-us/dotnet/standard/net-standard.
When the project has been created, you should have `Class.cs` and `Project.csproj` files. Your `Project.csproj` should look something like this.
```xml
<ProjectSdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>
```
## 3. Add the Impostor.Api library
You only have to follow the instructions of one below.
### Quick
Install the `Impostor.Api` NuGet package.
Make sure to get a prerelease if you are writing a plugin for a dev release of the server.
### Visual Studio
1. Right click your project.
2. Click `Manage NuGet Packages`.
3. Click `Browse`.
4. Search for `Impostor.Api`.
5. Click the `Impostor.Api` result and press install on the right side.
### Dotnet CLI
1. Open your project folder in command prompt / bash.
2. Run `dotnet add package Impostor.Api`.
## 4. The plugin class
Now the `Impostor.Api` is installed, you need to create a class for your plugin. A plugin **must** contain exactly one. See the code below for an example.
```csharp
usingSystem.Threading.Tasks;
usingImpostor.Api.Events.Managers;
usingImpostor.Api.Plugins;
usingMicrosoft.Extensions.Logging;
namespaceImpostor.Plugins.Example
{
/// <summary>
/// The metadata information of your plugin, this is required.
/// </summary>
[ImpostorPlugin(
package: "gg.impostor.example",
name: "Example",
author: "AeonLucid",
version: "1.0.0")]
publicclassExamplePlugin:PluginBase// This is also required ": PluginBase".
{
/// <summary>
/// A logger that works seamlessly with the server.
/// </summary>
privatereadonlyILogger<ExamplePlugin>_logger;
/// <summary>
/// The constructor of the plugin. There are a few parameters you can add here and they
/// will be injected automatically by the server, two examples are used here.
///
/// They are not necessary but very recommended.
/// </summary>
/// <param name="logger">
/// A logger to write messages in the console.
/// </param>
/// <param name="eventManager">
/// An event manager to register event listeners.
/// Useful if you want your plugin to interact with the game.
// This prints out for all players if they are impostor or crewmate.
foreach(varplayerine.Game.Players)
{
varinfo=player.Character.PlayerInfo;
varisImpostor=info.IsImpostor;
if(isImpostor)
{
_logger.LogInformation($"- {info.PlayerName} is an impostor.");
}
else
{
_logger.LogInformation($"- {info.PlayerName} is a crewmate.");
}
}
}
[EventListener]
publicvoidOnGameEnded(IGameEndedEvente)
{
_logger.LogInformation($"Game has ended.");
}
[EventListener]
publicvoidOnPlayerChat(IPlayerChatEvente)
{
_logger.LogInformation($"{e.PlayerControl.PlayerInfo.PlayerName} said {e.Message}");
}
}
}
```
## 6. Registering the event listener
The last step to get your plugin working is to register the event listener, so the server knows about it. Go back to your plugin class and modify it as below.
_logger.LogInformation("Example is being disabled.");
// Add the line below!
_unregister.Dispose();
returndefault;
}
}
}
```
## 7. Build and run your plugin
Now your plugin is ready to be tested.
1. Right click your project and press `Build`.
2. Right click your project and press `Open Folder in File Explorer`.
3. Go to `bin/Debug/net8.0/`.
4. In this directory, you should find your plugin named `Project.dll`.
5. Copy the `Project.dll` to the `plugins` directory in your Impostor server directory.
6. (Re)start your Impostor server.
7. Open Among Us, create a game and send a chat message. In the console you should see your plugin being loaded and the messages from the example.
## 8. Extra
Some extra information that might be useful for those developing plugins.
### Event listeners
- You can have multiple event listener on the same event.
- An event listener can be given a priority `[EventListener(EventPriority.Normal)]` and is called in order.
- It is not recommended to block for a long time inside `EventListener` because the events are called from inside the packet handlers. Blocking too long causes the client to time out. You should create a new `Task` for operations that will take a lot of time.
### Dependency injection
- The main plugin class is constructed by the `IServiceProvider` of the server and can inject everything the server uses. A few examples are:
-`ILogger<T>`
-`IEventManager`
-`IClientManager`
-`IOptions<ServerConfig>`
- You can add your own classes and `EventListener` implementation to the `IServiceProvider` by creating a new class and implementing `IPluginStartup`. Make sure to register them as a singleton `services.AddSingleton<IEventListener, GameEventListener>();`.
### Server configuration
Constantly copying the plugin dll to your server directory can be pretty annoying. Luckily we have a solution for that. In your Impostor server open the `config.json` and add the `PluginLoader` from the example below, replace the path with the build destination of your plugin.
Sometimes you need to use libraries that the original Impostor server does not provide. The dll files of these libraries must be placed in the `libraries` folder next to the server executable. You could also provide them by modifying the `PluginLoader.LibraryPaths` option in the `config.json`, similarly to the `PluginLoader.Paths` option.
### Impostor versions
It is important to use the correct versions when working with `Impostor.Api` prereleases and the `Impostor` dev builds to reduce the chances of mismatching assemblies.
**Example**
The prerelease `Impostor.Api` package `1.2.0-ci.54` belongs to build `54` on AppVeyor, which can be found here https://ci.appveyor.com/project/Impostor/Impostor/build/54. Notice the `54` on the end of the url.
## 9. Missing/invalid data or want more functions?
The `Impostor.Api` is currently in beta. There are a lot of things still missing and we would like to hear from you what you need to develop a plugin.
Create an issue:
- [Suggest a function](https://github.com/Impostor/Impostor/issues/new?template=3--api-suggestion.md)
- [Data is invalid](https://github.com/Impostor/Impostor/issues/new?template=4--api-invalid.md)
- [Data is unavailable](https://github.com/Impostor/Impostor/issues/new?template=5--api-missing.md)
Loaded 100 of 612 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.