5

I would like to know how i could log SSH command lines a user is using on a server. For exemple, if the user Alex on my server is doing the following set of commands :

$ cd /tmp
$ touch myfile
$ ssh staff@10.0.0.1
$ ssh staff@10.0.0.2
$ vim anotherfile
$ ssh alex@192.168.0.12

I would like to log the ssh commands used on the server in a file which looks like :

[2014-07-25 10:10:10] Alex : ssh staff@10.0.0.1
[2014-07-25 10:18:20] Alex : ssh staff@10.0.0.2
[2014-07-25 11:15:10] Alex : ssh alex@192.168.0.12

I don't care what he did during his ssh session, i just want to know WHEN and TO WHERE he made a connection to another server.

The user is not using bash and i would like to avoid manipulating .bash_history anyway as the user can modify it.

Any clue on this ?

Thank you :)

edit : to be more specific :

a user connects to a server A and then connects from the server A to server B. I want to track down to which server he connects through ssh from server A.

  • Set LogLevel in sshd to one of the DEBUG levels? sshd_config(8) says that this "violates the privacy of users and is not recommended"... sounds like just what you want! – Andrew Schulman Sep 25 '14 at 10:13
  • 1
    Install a tool for user account auditing like auditd. It's better if you want to quickly filter by criterion and make your search easier on activity logs. – Xavier Lucas Sep 25 '14 at 10:28
  • Actually, there is no log file for ssh CLIENT. If i change LogLevel in ssh_config it will only display more things on screen. Furthermore, the user privacy is not applicable in that case, so i don't really care ^^ I'll give a try to auditd but i'm not sure it will log ssh commands... – Kevin Merigot Sep 25 '14 at 12:38
  • @KevinMerigot Auditd will log everything, and map ssh users on shared accounts to different audit ids. – Xavier Lucas Sep 25 '14 at 15:18
  • Eventually, i use the logger solution and force users to use bash at connection, with a little trick to include /etc/bashrc at startup in /etc/profile : if [ $0 = '-bash' ]; then . /etc/bashrc fi – Kevin Merigot Sep 26 '14 at 13:38
3

You could do it in three different ways as i see it - There are most likely many other ways to do it as well! The best method would be to attach a audit tool to the kernels sysexec calls so it would be untraceable by the user etc. The two other ways would simply be to modify the shell environment to log it.

Instead of me (grabbing the code/answers from google) showing you how to do it. I will give you links to sites that have explained this detailed already. I hope it's exactly what you need.

Btw, the easiest way is by far just to include something in your main bashrc/profile to affect all users.

Anyway's, here are links to bashrc solutions.

1) Bashrc solution: How to log commands executed by all the users in Linux? 2) Bashrc/trap solution: Bash: History to Syslog

The other way (kernel level) would be to look into to tools audit or acct. There are many sites out there who tell you how to setup logging of commands via kernel sysexec calls.

2

Here's a script that you can use to capture the userid and other info to put in a logfile before kicking off the ssh. I tested it with several very complicated multiline ssh commands.

#!/bin/bash

# Title......: ssh (wrapper)
# Description: this script replaces the ssh binary and runs the real binary after logging the connection attempt

# variables
#----------------------------------
REALBINARY=/usr/bin/sshu
THISHOST=$(uname -n)
LOGFILE=/var/log/sshclient.log
CALLINGPROC=$(ps -o comm= $PPID)

log() {  # creates a basic log entry; $LOGFILE must be defined
 echo "$(date '+%Y-%m%d %H:%M:%S %Z') $$  $*">>$LOGFILE
}

SSHTARGETOPTS=$(echo "$@" | head -1)
while getopts :l: OPT 2> /dev/null
do
 case "$OPT" in
  l) TARGETUSER="$OPTARG" ;;
 esac
done

#after parsing with getopts, OPTIND will be the positional parameter number of the first argument after the options
FIRSTARG=$(echo $SSHTARGETOPTS | awk "{print \$$OPTIND}")
#if there is an '@' symbol in the FIRSTARG, parse out the LOGIN and TARGETSERVER, if not, TARGETSERVER is FIRSTARG
if [[ "$FIRSTARG" =~ '@' ]] ; then
 TARGETUSER="${FIRSTARG%@*}"
 TARGETSERVER=${FIRSTARG##*@}
else
 TARGETSERVER="$FIRSTARG"
fi
TARGETUSER="${TARGETUSER:-$LOGNAME}"

if [[ "$SUDO_USER" ]] ; then
 log "$THISHOST CallingProc='$CALLINGPROC' SUDO_USER='$SUDO_USER' became LOGNAME='$LOGNAME' ssh to TARGETSERVER='$TARGETSERVER' as TARGETUSER='$TARGETUSER' with command '$0 $SSHTARGETOPTS'"
else
 log "$THISHOST CallingProc='$CALLINGPROC' LOGNAME='$LOGNAME' ssh to TARGETSERVER='$TARGETSERVER' as TARGETUSER='$TARGETUSER' with command '$0 $SSHTARGETOPTS'"
fi

exec $REALBINARY "$@"
-1

The most obvious, shell agnostic method would be to replace ssh with a wrapper script/program that does the needed logging, and then execs ssh.

Using the wrapper program means that it doesn't matter what shell the users are using (yes, there are shells other than bash!), and "shell escapes" from other programs (such as emacs, vi, mailx, etc.) will also be logged.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.