Skip to content

smj-cc/ssh-chat

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 

Repository files navigation

NOTICE: THIS PROJECT HAS MOVED TO CODEBERG

ssh-chat

A very simple daemonless chat via ssh (or mosh) that works through your existing openSSHd, written entirely in execline for security and ease of maintenance.

Users all log into your existing sshd as user 'chat', using their ed25519 public key. Their 'nick' and other settings are associated with that key and preserved.

When accessed via the mosh client, this is effectively a UDP chat.

Commands ( start with / )

  • /clear Clear the screen. This also reloads the 'chat' script, if it was updated, and adjusts the window for any SIGWINCH events.

  • /quit Disconnect from chat.

  • /nick {newnick} Change your current 'nick'.

  • /color {number} Set the color of your 'nick'.

  • /colors Show the color each number selects.

  • /join {channel} Leave your current 'channel' (initially 'main') and 'join' a new channel.

  • /who Show who else is in your current channel.

  • /status {status string} Changes a 'status' string visible to the /who command

  • /version Show the current version of the 'chat' script.

  • /{nick} {message string} Send a direct message to a 'nick'. If the user is offline, the message will display when the user next connects.

History

I was inspired by the post "Why aren’t we using SSH for everything?", and thereby discovered the 'real' ssh-chat, but could not get it to compile and run under musl. Shazow's ssh-chat is arguably superior on many counts, including that it runs as a daemon, and therefore can do things this ssh-chat cannot, even when no users are online, and that it is compiled and therefore runs with much more potential efficiency and scalability. (execline makes extensive 'execv' calls)

Differences from Shazow's ssh-chat

  • This 'ssh-chat' is accessed through your existing openSSHd, so it shares the same port, and adds very little attack surface.

  • Each login is an instance of the 'chat' script, and instances are in 'peer' communication with each other through pipes. There is no 'server' daemon. When everyone logs out, nothing is running but the sshd. When instances run, there is no 'shell' or interpreter running or involved.

  • Easier to modify and test by editing the execline script. No server to restart. (chat users have to log out and back in, or issue a 'clear' command, to see the changes)

If you're experienced with the unix command shell 'execv'/'argv' system, and have not yet discovered execline, you're in for a treat. The beauty, simplicity, and resultant security which is inherent to this system, can be fully appreciated only when you fully understand the unix 'exec' system.

An execline script is not interpreted by a shell. In fact, no shell or interpreter of any kind is involved anywhere in the entire process of running this ssh-chat. There is a 'parser' (execlineb), but it runs only once, and terminates before running the 'script'. (it 'execs' into the single command line built from the script) This means there is no parser/interpreter running to be confused/tricked by user input. Auditing the security of the script is trivial, at least compared to a shell script.

Making changes to the script is obviously much simpler than to a compiled object, so by all means, personalize your copy... and let me know what you've done so I can can steal it from you!

How to install

  • Ensure that you have sys-apps/coreutils and dev-lang/execline installed on your system. Unless you edit the 'chat' script to use the unix default versions, you'll need to install sys-apps/s6-portable-utils. I've also used app-admin/pwgen to assign an initial random 'nick', and sys-libs/ncurses for colors, and for a fake "status line".

  • Create the user account for chat. I use 'chat' as the username. Ensure that the account entry in /etc/shadow has '*' in the password field (not '!'), so that sshd will allow only public key logins, and ensure that the chat script is the user's shell. e.g.:

/etc/passwd

chat:x:2000:2000::/home/chat:/home/chat/.bin/chat

/etc/group

chat:x:2000:

/etc/shadow

chat:*:17868::::::

/etc/gshadow

chat:!::
  • Install the script, and the directory structure to the user's home directory, and set file and directory permissions. e.g:
# mkdir /home/chat/.bin /home/chat/.channels /home/chat/.keys /home/chat/.nicks
# mkdir /home/chat/.channels/main
# mv /path-to/chat /home/chat/.bin/
# chown root:chat -R /home/chat/
# chmod 770 -R /home/chat/
# chmod 710 /home/chat /home/chat/.bin
# chmod 650 /home/chat/.bin/chat
  • Edit your /etc/ssh/sshd_config ( or /etc/ssh/sshd_config.d/whatever ) to add the following, which will allow everyone with an ed25519 key to log in as user 'chat':
PermitUserEnvironment chatkey

Match User chat
	AuthorizedKeysCommand /bin/echo environment=\"chatkey=%k\" ssh-ed25519 %k
	AuthorizedKeysCommandUser nobody

File transfer via scp

To allow chat users to transfer files via scp (sftp)

If the following changes are not made, no file transfers are allowed.

  • Place a copy of your chroot binary into ~chat/.bin, and give it chroot caps
cp /usr/bin/chroot ~chat/.bin/
chown root:chat ~chat/.bin/chroot
setcap cap_sys_chroot=ep ~chat/.bin/chroot
  • Create the chroot environment
mkdir ~chat/.files
chown root:chat ~chat/.files
chmod 3770 ~chat/.files
mkdir ~chat/.files/.bin ~chat/.files/dev ~chat/.files/etc
chown root:chat ~chat/.files/.bin ~chat/.files/dev ~chat/.files/etc
cp -arv /etc/passwd ~chat/.files/etc
cp -arv /dev/null ~chat/.files/dev/
  • Create a statically linked copy of sftp-server, and place it into ~chat/.files/.bin/sftp-server-static

  • Create a file called files in the ~chat/.keys/{key} directory for each user you authorize to upload files. All users can download files.

License

I've chosen the ISC license out of deference to, and respect for skarnet.

Foibles

  • I wrote this over a weekend. There are doubtless many tweaks to be made or improved, but I know of no bugs. (editing and testing the code is so easy, that I'd just fix them if I knew of any)

  • It needs a /proc filesystem available.

  • If a user changes his window size (SIGWINCH), 'chat' will behave poorly until the user logs out and back in again, or issues a 'clear' command, which reloads the script. (the SIGWINCH occurs on the user's client) I suppose I could 'poll' for changes, but why bother?

About

A very simple daemonless chat via ssh (or mosh) that works through your existing openSSHd

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors