Foreword
This guide is not intended for people hoping to screencast or record a window so they can produce a video demonstrating something on their system. There are plenty of guides for how to use tools like OBS to record your screen and/or mix in audio. Instead, I am attempting to solve a need that exists in system security to provide session recording capabilities for users on Linux, similar to tools like Verint.
Tools like this already exist for SSH connections, such as tlog, but I couldn't find a similar utility to record an X session. I had a need to set up a jumpserver that is accessed via xrdp to provide a graphical environment to users, but needed to be able to capture screen activity as they access web-based tools. Due to budget and licensing constraints, installing a Windows terminal server with Verint or similar was not a viable option. System logs within the tools are available, but we wanted to be able to actually see what a user did with their time.
Here, I will detail the process I used to bodge together screen recording for user sessions. This method does have one glaring vulnerability: if users are aware that the recording is happening, they can kill the process which is recording as it will show up in tools like htop. This is intended functionality in Linux: anything that can actually see a user's X session can also be seen by the user. I've tried to have the minimum impact on user experience possible, but I'm also not trying to hide that this recording is happening: Security through obscurity is not Security.
Disclaimer
Recording somebody without their consent is, at best, extremely unethical. It may be illegal where you are. This guide is provided for educational purposes only, and is intended for use in a business context on company-provided equipment (or a jumpbox that is used to access privileged resources, in my use case), where the user does not have an expectation of privacy. DO NOT take these steps on a personal device, and especially do not do it on a computer you do not own. I don't take responsibility for your stupidity, but I will be there to laugh if you get yourself arrested.
No really
I'm serious. Don't do this unless you have a business need to capture this kind of logging. The screenshots will capture everything that is on a user's screen, including any passwords or other PII that is not hidden by the input. It's fine to try this out in a lab or if you have a business need, but outside of those circumstances you're inviting abuse and providing a juicy target for any would-be attacker. I do not run this in my personal system, and after I confirmed the steps were repeatable I disabled it in my lab jumpbox. There is no reason to have this kind of recording in a home situation.
My system configuration
This method is tested on Fedora Linux. It should work on any Linux system as long as you are using X.org instead of Wayland compositor. This is fine in this case, because xrdp does not spawn a Wayland session. If you wish to record Wayland, the basic principles should be the same but you will need to find a different screen recording software.
Additionally, I am not capturing video. I'm instead capturing a screenshot every second. While it is possible to capture a screen using ffmpeg, space is also a consideration: screenshots are significantly less space than video.
Packages to install
Most of what you'll need for this method should already be installed on your system. I needed to install incron
and maim
- both of these tools exist in the Fedora repositories.
Set up the location where the screenshots will be saved.
I have elected to use /var/log/screenrec to store recordings. You can theoretically put this anywhere on the filesystem. All of the following commands need to be run as root:
mkdir /var/log/screenrec
Now we need to make it world writeable. This will allow the screen recording software to create subdirectories within that folder. It's necessary to run the screen recorder as user because by default X.org will not allow screen capture/recording by another user (even root).
chmod 777 /var/log/screenrec
Finally, we need to set that directory to append-only. This will allow file/subdirectory creation, but prevent deletion.
chattr -R +a /var/log/screenrec
Create a trigger script that will set any new subdirectories as append-only
The above chattr command only works to one level of subdirectory. As we'll be storing screenshots in user/session-id/filename.jpg
, we need to set the attribute on any directories that get created. The first part of doing that is writing a script to make the necessary changes. I am saving it in /usr/local/sbin/protect-folder.sh
#!/bin/bash
# Set a few variables.
targetdir=/var/log/screenrec
filename=$1
[[ ! -d $filename ]] && exit 0
[[ "${filename}" =~ "${targetdir}" ]] && chattr -R +a $targetdir
This script will accept a target directory/filename from command-line. If it's not a directory, the script exits - this is basic protection against malicious input, though the script should only ever be called by root. After confirming it's a directory, it checks that it is in the correct location we want to modify: if it is then it will set the append-only attribute to the directory.
Set up incron
We need to call the above script whenever a directory is created in the correct location.
Incron is a utility that will watch a given location in the filesystem for changes, and trigger an event when the conditions are met. In this case, we're using it to watch the location where we're going to save screenshots to set the filesystem to append-only. This should prevent any user from deleting the screenshots that will be captured.
Set up the incron ACL
We need to set an ACL for incron so that only root can use the service. While this isn't absolutely necessary, it's possible to load a CPU with a lot of incron tasks running, and it's very unusual that a regular user will need to watch the filesystem for changes.
Create/edit the file /etc/incron.allow
, and put the following in it:
root
Enable incron
By default, the incron daemon will not be running. Enable it & start it with the following command as root:
systemctl enable --now incrond
Set up incrontab
Like cron, incron uses a configuration file called a tab to tell it what it needs to do. Edit root's incron tab with the following command:
incrontab -e
And add the following line to tell it to watch our screen recording folder, and call the protect-folder.sh
we created above whenever a new subfolder is created:
/var/log/screenrec IN_CREATE,IN_ISDIR /usr/local/sbin/protect-folder.sh $@
Set up the screen recorder script
Now we need to create a screen recorder script. This script can be called by a user, and will capture screenshots every second, saving them in a subdirectory in /var/log/screenrec. Because of the above steps setting up the protect-folder.sh
and incron
, we know that any files created in this location cannot be deleted through normal means.
Create /usr/local/sbin/screen-recording.sh
#!/bin/bash
# Check that we're running under X. The user might call it from SSH and we don't want it to do anything.
if [ -z $DISPLAY ]; then
echo "No active X session found"
exit 1
fi
# Generate the session ID & storage location
systemdate=$(date +"%Y-%m-%d-%H%M%S")
storage_location=/var/log/screenrec/$(whoami)/${systemdate}
# Make the directory where the session will be recorded
mkdir -p $storage_location
# Run the recording loop
while true; do
maim -m 2 $storage_location/$(date +"%H%M%S").jpg
sleep 1
done
This script can be called by any user. If they're running under X, it will start a loop that captures a screenshot every second, saving it in our /var/log/screenrec location. This shouldn't have an outsized impact on system performance, and because we're using JPEG with quality setting of 2, it should be readable while still producing small-ish file sizes: roughly 100kb for a 1080p screen size, every second.
Set up an autostart service to trigger the screen recorder
Finally, we need to make sure that the screen recorder starts automatically every time a user logs in. We do this with an xdg autostart service, though there are other methods to ensure that this happens. I am aware that there are methods to prevent the service from running - to get around that I am not creating user home directories on my jumpserver: every user gets a default configuration loaded from /etc/skel and nothing they create will last beyond logout. There are other methods to protect startup services, but they are outside of the scope of this document.
Create the file /etc/xdg/autostart/screen-recording.desktop
[Desktop Entry]
Type=Application
Name=Screen recorder
Exec=/usr/local/sbin/screen-recording.sh
Final words
If everything worked, your users should now have a service running that will capture a screenshot of their X session every second, and store it in a location where they can't delete files. There are limitations to this method as it is not impossible for a user to stop the recording service. Unfortunately, while it is possible to prevent them from stopping it (or configure it to automatically start itself back up), I have not addressed that in this document.
Please also scroll up and re-read the Disclaimer and the No Really section of this document.