Skip to content disloops

MUSH and Restricted Shell

I have slowly been working on a MUSH, which is an online, multi-player, text-based social game. The game Zork (1977) is probably the most popular game in this style, although it is not multi-player. I decided to use PennMUSH as the server distro since it seems to have the widest support.

MUSH servers open a raw TCP socket for incoming connections and most sessions occur over plaintext. There are a handful of MUSH clients that players can use but a simple TELNET connection also works. MUSH servers understand enough of the TELNET protocol to refuse option negotiation.

At one time I decided to create restricted shell accounts for users and have them connect to the MUSH via localhost rather than expose the MUSH server to the open internet. I have since walked that back and just opened it to the internet but shell accounts are still an option. See this page for some details.

Update: The configuration that follows has been deprecated in a couple places due to the diligence of @unix-ninja and his testing. Essentially, the use of an rbash restricted shell still allowed for a "history" file to be written to disk. Its location could then be passed as an argument to the TinyFugue client and loaded as a more permissive configuration file, which gave way to an unrestricted shell. Excellent work!

Setting Up Restricted Shell

The premise for setting up restricted accounts is as follows:

  • Use rbash as a restricted shell
  • Limit $PATH to a custom /bin directory
  • Add symbolic links in custom /bin directory to a limited set of commands

If bash is started with the name rbash, the shell becomes restricted, meaning that a number of commands are prohibited. We'll enable that now with a symlink:

cd /bin
sudo ln -s bash rbash

We'll also add a group for the restricted users:

sudo groupadd mushusers

Creating Users

Now let's go through the process of creating a restricted user account:

  • lution is to just use TinyFugue as the shell and scrap rbash altogether.
  • Read his
sudo useradd -m -d /home/mushusers/basic_user -s /bin/rbash -N -g mushusers -c "Testing the restricted access shell" basic_user

The options above are as follows:

  • -m  →  creates a home directory
  • -d  →  specifies a non-default location for the home directory
  • -s  →  specifies the login shell to use
  • -N  →  do not create a group with the same name as the user but add the user to the group specified by the -g option
  • -c  →  comment field

Note: As stated above this is deprecated. We're now using /usr/bin/tf as the login shell. A lot of the configuration is still the same in either case.

Linux systems use a few different files to configure a user's session in different scenarios:

  • .bashrc
  • .bash_profile
  • .profile

This is where the PATH environment variable is located, which defines where to find executables. So we want to wipe any existing config files and create our own with a custom PATH:

sudo rm -rf /home/mushusers/basic_user/.bash*
sudo rm -rf /home/mushusers/basic_user/.profile
sudo vi /home/mushusers/basic_user/.bashrc

Here's the full text of the .bashrc file I created for restricted users:

export PATH
echo "  Welcome! This is a restricted shell. Type 'mush' to visit Parlor City."
echo "  You can also type 'passwd' to change your password. Type 'exit' to leave."

This same file can be used as .bash_profile too:

sudo cp /home/mushusers/basic_user/.bashrc /home/mushusers/basic_user/.bash_profile

You can see that we define and export the PATH variable above, which is limited to a single /bin directory that we'll create now:

sudo mkdir /home/mushusers/basic_user/bin
sudo ln -s /usr/bin/tf /home/mushusers/basic_user/bin/mush
sudo ln -s /bin/passwd /home/mushusers/basic_user/bin/passwd

Within this directory we've created symlinks for only two commands:

  • passwd to allow users to change their password
  • mush to allow them to connect to the MUSH (explained below)

Now we'll correct the owner and permissions and use chattr to make the files immutable with the +i attribute:

sudo chmod -R 750 /home/mushusers/basic_user
sudo chown -R basic_user:mushusers /home/mushusers/basic_user
sudo chattr +i /home/mushusers/basic_user/.bashrc
sudo chattr +i /home/mushusers/basic_user/.bash_profile

That completes the configuration for the restricted shell user. The only thing left is to create a password for the account:

sudo passwd basic_user

I also had to modify /etc/ssh/sshd_config and to enable password authentication. Set PasswordAuthentication to yes then restart the SSH service.

Last Configuration Items

The mush command above is symlinked to the TinyFugue client for restricted shell users. By default, TinyFugue will pull from /usr/share/tf5/tf-lib/ for configuration data. There are two custom lines needed here:

/addworld -T"tiny" ParlorCity localhost 4201
/restrict WORLD
  • The addworld command defines a shortcut for a known world. TinyFugue will connect here by default.
  • The restrict command prevents users from defining new worlds, writing files, etc. This appropriately locks down TinyFugue for general use.

One note regarding TinyFugue for my own sake, it was necessary to install libncurses to get TinyFugue working correctly:

sudo apt-get install libncurses5-dev libncursesw5-dev

Before TinyFugue was in place, restricted shell users used the telnet command to connect to the MUSH server locally. We needed to prevent these users from making connections to remote servers, though. The solution was to use iptables to prevent users in the "mushusers" group from establishing outbound connections. The resulting command looked like this:

iptables -A OUTPUT -o eth0 -m owner --gid-owner 1001 -j REJECT

...where "1001" is the ID for the "mushusers" group we added the users to.

Because iptables rules don't persist across reboots, I added this command to /etc/rc.d/rc.local so that it will always run on startup. I also had to make this file executable:

sudo chmod +x /etc/rc.d/rc.local

This configuration is still in place.

That's it! The commands in the "Creating Users" section above can now be repeated to add more users. I will keep this article updated if I come across any further best practices for configuring restricted shell accounts.

Leave a Reply

Your email address will not be published. Required fields are marked *