eukara / freecs

Clean-room Counter-Strike 1.5 in QuakeC, using Nuclide SDK. Previously known as OpenCS! (2016)
https://www.frag-net.com/projects.html
ISC License
195 stars 16 forks source link

understanding the systemd units #40

Closed atomGit closed 6 months ago

atomGit commented 6 months ago

re: https://code.idtech.space/eukara/fhl-server-configs

my knowledge of systemd and linux security is rather poor, but i'm wondering about running the service as 'user' - wouldn't it be better to run this under a dedicated user:group for security reasons and eliminate loginctl enable-linger <username>?

eukara commented 6 months ago

You don't have to run them as user, no. That really depends on your setup. I didn't want to specify a user or ask people to modify the scripts and/or unit files and figured that server admins who know what they want will do the right thing.

atomGit commented 6 months ago

my setup is very simple: a VPS running Arch for the sole purpose of running an FTE and Mumble server, so very non-mission critical

given that, what would be your advice for running FTE?

the service scripts look easy enough to modify - just drop --user and change the systemd unit file directory to system

is that all that should be done, or should FTE be run under its own user:group?

i ask because i'm interested in best security practice

eukara commented 6 months ago

Generally it's best advised to run it as a specific user that only has the minimum amount of permissions required to do what it needs to do. If you hard-specify for the unit which user to run it as, you'll need superuser privileges to start/stop/restart/enable/disable it. That may be desirable to you if you want the most protection.

Considering anyone with read/write access to the users' home dir can also manipulate fteqw and the fteqw server into misbehaving by abusing the virtual filesystem and the paths it looks in for data and configs (and thus allowing the engine to diverge into executing native code for example) - it doesn't add that much more security. But it can inconvenience the people who don't know how to exploit most id Tech engines.

Edit: Some manual hardening methods I've thought about:

There's the -readonly flag. You can also pass -nohome to the engine to avoid it looking into any home directories. You will have to ensure that all the data is in a read-only location the user cannot write into. Quake's data usually goes into something like /usr/share/games/quake, for FreeHL the engine can look in /usr/share/games/halflife. You'll have to make your own solution to update the package_valve.pk3 file and to place it in /usr/share/games/halflife/valve. You can also override the location of the root game directory with -basedir to the engine.

However, I have not set up units using this. I have not tried the above, but I've used all of the arguments and I am certain they do work. I can make no claims to increased security as I have not tried it. But it should get rid of most exploits I can come up with.

There's areas of FTEQW that should be audited, before one can make any claims that it or anything using it is secure. In terms of in-game exploits and cheating it may very well be, but on a system application level that's a different story. As a general issue, game engines are complex beasts. They have to be the biggest application in the entire user-pace (together with web browsers) because they have to utilize every bit of hardware capability you got. You have to open file descriptors, network sockets, have to output audio/video - make use of video hardware where the video memory isn't all that protected either - the list goes on. Maybe if something like OpenBSD's pledge caught on, one could spend time hardening the server into not being tricked into doing things it's not supposed to do.

atomGit commented 6 months ago

thanks, i really appreciate your help

before i get to the systemd units, could you have a peek at this and let me know what you think - again, my interest is securing the server as best as i can...

# mkdir /usr/share/games/halflife
useradd --system -U -s /usr/bin/nologin fteqw
(all game files are present @ `/usr/share/games/halflife`)
# chown --recursive fteqw:fteqw /usr/share/games/halflife/*
# chmod --recursive u=r /usr/share/games/halflife/*
# chmod --recursive g=r /usr/share/games/halflife/*
# chmod --recursive o= /usr/share/games/halflife/*
# chmod u=rx /usr/share/games/halflife/fteqw-sv64
# chmod g=rx /usr/share/games/halflife/fteqw-sv64

the result...

# ls -l
total 2772
dr--r----- 14 fteqw fteqw    4096 Mar  8 17:12 cstrike
dr--r-----  9 fteqw fteqw    4096 Mar  7 17:08 dmc
dr--r----- 11 fteqw fteqw    4096 Mar  7 16:30 fhl-server-configs
dr--r----- 12 fteqw fteqw    4096 Mar  7 17:08 ricochet
dr--r-----  9 fteqw fteqw    4096 Mar  7 17:08 tfc
dr--r-----  9 fteqw fteqw    4096 Mar  7 17:08 valve
-r--r-----  1 fteqw fteqw    9058 Mar 10 01:32 ReadMe-FTEQW.txt
-r-xr-x---  1 fteqw fteqw 2791800 Oct 31 09:47 fteqw-sv64
-r--r-----  1 fteqw fteqw    1269 Mar  7 17:32 fullchain.pem
-r--r-----  1 fteqw fteqw    2455 Mar  7 17:32 privkey.pem

start the server:

[root@asylum halflife]# su --shell /bin/bash fteqw
[fteqw@asylum halflife]$ ./fteqw-sv64 -nohome -readonly -game cstrike -svport 64444 +sv_public 0 +set deathmatch 1 +set maxplayers 16 +map de_dust2

response...

Binary is located at "/usr/share/games/halflife/"
couldn't exec default.cfg
couldn't exec ftesrv.cfg
Can't find maps/de_dust2
Exe: FTE git-6496-eb6b127d9
======== Half-Life Initialized ========
Current search path:
 ----------
 /usr/share/games/halflife/valve  (e)(w)
 /usr/share/games/halflife/logos  (e)(w)
SV_Error: Couldn't load a map. You may need to use the -basedir argument.
[...]

the map exists, so there's some sort of permission issue i assume

specifying -basedir doesn't seem to help - i tried -basedir cstrike as well as the full path to cstrike

eukara commented 6 months ago

It doesn't list cstrike in the search path at all. Which shouldn't happen since you specify it via -game cstrike.

The -basedir parameter specifies the root game directory (e.g. /usr/share/games/halflife). If you want to be really verbose:

./fteqw-sv64 -basedir "/usr/share/games/halflife" -halflife -game cstrike [more options go here]

...although the above string you posted should work. I have prodded Spike about it. Unless you are executing some config (autoexec.cfg, etc.) that changes the game-dir I don't see what's messing with it.

atomGit commented 6 months ago

i think it's a permission issue - if i run the command as root the server starts fine, but if i switch to the fteqw user...

# su --shell /bin/bash fteqw
[fteqw@asylum halflife]$ ./fteqw-sv64 -nohome -readonly -game cstrike -svport 64444 +sv_public 0 +set deathmatch 1 +set maxplayers 16 +map de_dust2

... then the server won't start

/usr/share/games/halflife is owned by root, but everything in/under halflife is owned by fteqw:fteqw

so i think i messed up something here...

# chown --recursive fteqw:fteqw /usr/share/games/halflife/*
# chmod --recursive u=r /usr/share/games/halflife/*
# chmod --recursive g=r /usr/share/games/halflife/*
# chmod --recursive o= /usr/share/games/halflife/*
# chmod u=rx /usr/share/games/halflife/fteqw-sv64
# chmod g=rx /usr/share/games/halflife/fteqw-sv64
atomGit commented 6 months ago

if i run the command as root the server starts fine, but if i switch to the fteqw user...

...and that should have been the clue - all is ok here, but will open a new issue with a working server example and questions