12

I have a 18.04 Ubuntu server that I use to bypass internet filtering/censorship in my country using SSH tunneling. To do this, I have created several users using the command adduser USERNAME --shell=/bin/false and given them the server IP, server port, username, and password (which I call them an account), so they can tunnel through my server. Now I want to make sure each account only works on one device at a time. In other words, I want to prevent multiple devices from tunneling through my server simultaneously using the same account.

By googling I found a solution: I put the following to, say, file /root/checkConnections:

#! /bin/bash

limit=$1
c=$(pgrep -xcu $PAM_USER sshd)
if [[ $c -ge "$limit" ]]; then 
    echo "Max $limit ssh connections allowed, but you have $c."
    exit 1
fi

Then in /etc/pam.d/sshd I added:

session required pam_exec.so stdout /root/checkConnections 1

This code worked well and did exactly what I wanted, but it has a significant drawback: when I exit putty, I can no longer ssh to the server! In other words, when I try to ssh to the server as root, it immediately kicks me out and doesn't allow me to login, and that's why I had to reinstall the server. How can I solve this problem?

Note: I am very new to the Linux server world, so please explain your solution in a simple manner.

7
  • 2
    Not sure about that code, but maybe some more streamlined solution like this ostechnix.com/…? And you can set it by user or group (and not include root) May 16 at 23:36
  • @YisroelTech Thank you for your comment, but that link is about ssh itself, not ssh tunneling. My users can only tunnel through my server and don't have any other permissions. May 16 at 23:49
  • I'm not sure why you say so. Your restriction seems to be on the SSH connection as well (tunneling is simply what you allow them to do, but it's not a different type of connection.) May 17 at 0:27
  • 1
    You reinstalled your operating system instead of just rebooting your system?
    – Ramhound
    May 17 at 0:47
  • 1
    Note that your presumably real identity is tied to this question. If bypassing the internet filtering is a crime, you probably shouldn't admit do doing so like this.
    – Maya
    May 17 at 15:50

1 Answer 1

21

The script you found works by counting the number of sshd processes that belong to the user who tries to log in via SSH. If the number is greater than or equal to the limit (1 in your case) then the script will return failure and thus prevent establishing a session.

The problem is the main SSH daemon itself is an sshd process that belongs to root. (In this answer you can see sshd being a daemon along with sshd that belongs to a regular user.) When the daemon is running, the count of sshd processes for root is always at least 1. The sole existence of a running SSH daemon causes your code to lock root out.

Possible solutions:

  • Get used to logging in as a regular user. After logging in, use sudo or su to become root when needed. This is a common practice. Logging in via SSH as root can be even disabled or restricted with PermitRootLogin in /etc/ssh/sshd_config. You may want to do this for security reasons.

    As a regular user you should be able to log in. Your script will treat you as any other regular user, i.e. the restriction to one session will apply; but (unlike root) you will be able to log in.

  • Modify the script, so if the user is root then the script will return success regardless of the count of sshd processes. A straightforward fix is to expand the if like this:

    if [ "$PAM_USER" != root ] && [ "$c" -ge "$limit" ]; then
    

    which means "if the user is not root and the limit is reached then … [return failure later]"; but it will be more elegant to check for the user early and not to call pgrep in vain. The code below uses this more elegant approach.

If I were you, I would merge the two solutions. I would log in as my regular user and I would make this user as unrestricted as root.

The following script returns success if the user is root or vahid. The limiting logic kicks in only for other users.

#! /bin/sh
case "$PAM_USER" in
   root|vahid )
      exit 0 ;;
   * )
      limit="$1"
      c="$(pgrep -xcu "$PAM_USER" sshd)"
      if [ "$c" -ge "$limit" ]; then 
         echo "Max $limit ssh connections allowed, but you have $c."
         exit 1
      fi
   ;;
esac

I deliberately used sh, it may be lighter (start faster, use less resources) than bash.


Additionally I think this entry in /etc/pam.d/sshd:

session required pam_exec.so stdout /root/checkConnections 1

may be bypassed by ssh -N. Since you set /bin/false for other users, I guess ssh -N is what you want them to use. To make the script do its job even in case of ssh -N, specify account instead of session:

account required pam_exec.so stdout /root/checkConnections 1
14
  • @VahidDamanafshan In this context any user other than root is a "regular user". May 17 at 8:06
  • 1
    @VahidDamanafshan "not only it failed to do what I wanted" – Did you use the line as a standalone script maybe? It's a fixed line of your original script, not a new whole script. I admit I did not test this solution thoroughly because I didn't want to PermitRootLogin. May 17 at 8:25
  • 1
    @VahidDamanafshan Now I have tested my code in Ubuntu 22.10, this specifically included allowing root to log in via SSH. I have replicated your exact problem, then I have confirmed each of my solutions solves it. For now I see no reason why it didn't work for you in 18.04. I note an easy way leading to the script "not work at all" is forgetting to set it as executable. May 17 at 9:29
  • 2
    @Vahid (1) I won't send you any e-mail. If you get an e-mail allegedly from me, it will be from an impostor. (2) Do not close your working SSH connection until you are sure you can connect anew (to a different user maybe) and get root access from there. Keeping at least one elevated shell running is a good practice when configuring crucial things. (3) Please confirm you make /root/checkConnections executable each time you apply any solution anew. (4) "Kicked me out" is vague. Some log or error message may help. If you used ssh instead of PuTTY, we would get information from ssh -v …. May 17 at 10:54
  • 1
    @VahidDamanafshan Probably. In my tests I added it at the end and it worked. This is all I can say because I don't really know PAM good enough. If you want a good answer then ask a new question. May 20 at 3:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .