skip to Main Content

I have a docker container running on the server side as a user’s login shell so that anyone can ssh into the server and get access to some resource inside.

Say, I have a user called test and I want people to be able to SSH into test‘s account using some publicly available password. Here’s what I have in /etc/passwd

test:1000:1000::/:/bin/test-shell

and in /bin/test-shell

#!/bin/bash
docker run -it --rm --network none python:3.10-alpine /bin/sh

Now, whenever someone ssh into my machine using ssh [email protected], they are immediately dropped into a disposable docker container. So far so good.

The problem I have is, if the user doesn’t exit the shell by either calling exit or pressing Ctrl-D but just closes their terminal window instead, the container is left running indefinitely and taking up limited server resources. I’m wondering if it is possible (and if so, how) to make sure the container is properly stopped (and therefore deleted) when a user disconnects.

I have seen Why does SIGHUP not work on busybox sh in an Alpine Docker container? and tried the approach of trapping both SIGHUP and SIGPIPE (running trap exit SIGHUP SIGPIPE inside the container), unfortunately nothing happens. I’m suspecting maybe the signals are received by the host shell instead of inside the shell inside the container, but I’m not sure how I can leverage that (if that’s really what happens) considering I have no way to get the dynamically generated container name, and I can’t name the container because I want every single ssh attempt to spawn a different container.

3

Answers


  1. Maybe setting up a connection timout with ClientAliveInterval and ClientAliveCountMax from /etc/ssh/sshd_config will help. By default it is not active.

    https://linux.die.net/man/5/sshd_config

    Login or Signup to reply.
  2. I think this answer may help you: https://unix.stackexchange.com/a/85429
    For example you can try something like this:

    #!/bin/bash
    [[ "$PAM_USER" -ne "test" ]] && exit 0
    
    SESSION_COUNT="$(w -h "$PAM_USER" | wc -l)"
    
    if (( SESSION_COUNT == 0 )) && [[ "$PAM_TYPE" == "close_session" ]]; then
      docker kill <containerId>
    fi
    

    You should use some unique tag for containerId maybe you can associate id of the container with the session id

    Login or Signup to reply.
  3. You could add this in your /bin/test-shell script:

    #!/bin/bash
    # Generate a random name for container
    CONTAINER_NAME=${RANDOM}
    
    # Register script to stop container with name
    trap '/bin/stop-container "$CONTAINER_NAME"' EXIT
    
    # Run container with name
    docker run --name $CONTAINER_NAME -it --rm --network none python:3.10-alpine /bin/sh
    
    # Unregister trap if normal exit
    trap - EXIT
    

    At the moment, I can’t test it, but it could works, because as described in trap manual:

    The environment in which the shell executes a trap on EXIT shall be identical to the environment immediately after the last command executed before the trap on EXIT was taken.

    Hope this help you to find the right direction.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search