Description
You want to manage an ssh server that can be reached by specific IPs and only specified commands will be accessible to the ssh user.
Explanation
In our example we have 2 hosts located in the same network (to prove the concept) with followings IP's: 192.168.122.1 (backend) and 192.168.122.157 (frontend) and we'll export squid logs from the backend to the frontend using rsync. Squid is running as proxy.proxy user.
In our case the only allowed command is rsync, all the others are rejected. According with your needs you can modify the script and allow your own specific command/commands.
Steps to achieve our goal include: creating of the user on the host, creating specific ssh keys (public/private key pair), defining specific commands that can be run.
On frontend
A1) Create restricted user
useradd -d /home/restricted_ssh_user -m -s /bin/bash restricted_ssh_user
A2) Create a strong password for the user - usually I'm using a (pseudo) random one generated with OpenSSL
#openssl rand -base64 9
A3) Change the password for the user (use the generated one)
#passwd restricted_ssh_user
A4) Create ssh keys for the restricted_ssh_user user
#su - restricted_ssh_user
$ssh-keygen -t rsa -b 2048 (just press enter for default)
The content of the /home/restricted_ssh_user/.ssh/id_rsa.pub file (which is the public key of the user) will be placed on each sever in /home/restricted_ssh_user/.ssh/authorized_keys for which we want to add ssh authentication using public keys.
In our case we placed it only on backend server (192.168.122.1).
On /home/restricted_ssh_user/.ssh create rsync script (called Rsync_SSH.sh) (The presence of the script can be enforced by any automation system like puppet, chef, or ansible).
#!/bin/bash
HOSTS=()
#HOSTS+=('backend')
HOSTS+=('192.168.122.1')
#HOSTS+=('backend-01')
#HOSTS+=('backend-02')
EXIT=0
RSYNCDIR=/home/restricted_ssh_user/LOGS
if [ ! -d ${RSYNCDIR} ]; then
mkdir ${RSYNCDIR}
fi
for i in `seq 0 $(( ${#HOSTS[@]}-1 ))` ; do
h=${HOSTS[$i]}
echo rsync up $h
mkdir -p ${RSYNCDIR}/${h}
rsync -avz -e ssh restricted_ssh_user@${h}:}:/var/log/squid/*.log ${RSYNCDIR}/${h}
if [ $? != 0 ]; then
echo "RSYNC of $h failed."
EXIT=1
fi
done
Make the script executable
$chmod +x /home/restricted_ssh_user/.ssh/Rsync_SSH.sh
A5) Run the script as a cron job every hour
#touch /etc/cron.d/rsync_squid_logs
1 * * * * restricted_ssh_user /home/restricted_ssh_user/.ssh/Rsync_SSH.sh
Restart cron
# /etc/init.d/cron restart
On backend server (192.168.122.1)(If you have more than one, repeat the procedure for all of them.)
B1) Create restricted user user without password
#useradd -d /home/restricted_ssh_user -m -s /bin/bash restricted_ssh_user
B2) Add restricted_ssh_user to proxy group (You need read access to the squid logs. Squid runs as proxy.proxy in our scenario).
#usermod -a -G proxy restricted_ssh_user
B3) Create .ssh structure for the user
#su - restricted_ssh_user
$ssh-keygen -t rsa -b 2048 (hit enter for default)
$cd .ssh
$ touch authorized_keys
$ chmod 600 authorized_keys
B4) Copy the content of the /home/restricted_ssh_user/.ssh/id_rsa.pub from the
frontend server (which was generated at point A4) to authorized_keys file.
B5) Improve security by adding commands restriction and IP restrictions
In /home/restricted_ssh_user/.ssh directory
$ touch Verify_Rsync.sh
$ chmod +x Verify_Rsync.sh
$ cat Verify_Rsync.sh
#!/bin/sh
case "$SSH_ORIGINAL_COMMAND" in
*\&*)
echo "Rejected"
;;
*\(*)
echo "Rejected"
;;
*\{*)
echo "Rejected"
;;
*\;*)
echo "Rejected"
;;
*\<*)
echo "Rejected"
;;
*\>*)
echo "Rejected"
;;
*\`*)
echo "Rejected"
;;
*\|*)
echo "Rejected"
;;
rsync\ --server*)
$SSH_ORIGINAL_COMMAND
;;
*)
echo "Rejected"
;;
esac
The presence of the script can be enforced by any automation system like puppet, chef, or ansible.
B6) Now the content of the /home/restricted_ssh_user/.ssh/authorized_keys content should look similar:
from="192.168.122.157",command="/home/restricted_ssh_user/.ssh/Verify_Rsync.sh" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArVSkVFLsW2secu14TX8tOEnC2B0Y6/q0Ws18r2xPPnw79QKjYCBPZ+RnW4tcHY0kMEahn4X1AcYgbTrQaO0UqkPZkFy5mKRS9R+OWJDUxYGQnGHegWqrM7oWYBR3Bvj39z1U4sUvxrBxluYjUM6FnkYL1wsdsd9998K3axfAxg0mSTq2u0lGCd71MTyvlf677777cfvebtthrhrr+3ApDDDDFvR+pN7MJFzcbrRds5l8PuSDDFUYLAEqqlDDDDvPPPPPPfbwcsassasBjYTmasasaUOt4FW3aPmiWA2WCasasmIn8rMdQ2UdQpivJ+ymAd7NVTtwx/ewSzLRScHxX9WQKIw== restricted_ssh_user@frontend
Note: The key is not real. Use your own.
The authorized keys file now says that restricted_ssh_user is allowed to ssh only from 192.168.122.157 IP address and allowed command is specified by the script Verify_Rsync.sh (which checks for rsync).
Testing - being on frontend
From frontend try to ssh or scp to backend using restricted user
ssh [email protected]
Rejected
Connection to 192.168.122.1 closed.
scp 192.168.122.1:/var/log/squid/*.log .
Rejected
Now try to test our implementation
whoami
restricted_ssh_user
restricted_ssh_user@U_NEW_16:~/.ssh$ /home/restricted_ssh_user/.ssh/Rsync_SSH.sh
rsync up 192.168.122.1
receiving incremental file list
sent 20 bytes received 85 bytes 210.00 bytes/sec
total size is 8,246 speedup is 78.53
restricted_ssh_user@U_NEW_16:~/.ssh$
As we can see it's a success. If you are here it a REAL SUCCESS.