Как найти отключенные сеансы xrdp?

Как найти отключенные сеансы xrdp?

У меня есть сервер Xubuntu 14.04, на котором запущен xrdp, чтобы к нему могли подключиться несколько пользователей.
Теперь есть одна проблема: пользователи, которые получают доступ к этому серверу через RDP с тонких клиентов Windows, часто используют "X", чтобы закрыть сеанс RDP (то есть отключиться, но не выйти).

Я знаю, что в sesman.ini есть некоторые параметры для решения этой проблемы, но, как говорится в man-странице, эти параметры в настоящее время игнорируются (и так было в течение многих лет).
Параметры, которые могли бы решить мои проблемы:
KillDisconnected
DisconnectedTimeLimit
IdleTimeLimit

Теперь мне нужно взломать что-то, что будет иметь дело с отключенными сеансами. Первой моей мыслью было просто убить всех удаленных пользователей, которые отключены, но я не знаю, как получить информацию о том, какие сеансы отключены.

Итак... как мне найти отключенные сеансы?
Или: есть ли уже какой-то предпочтительный способ работы с отключенными сеансами?

решение1

Вот способ получить список отключенных сеансов xrdp. Он основан на том, чтоxrdpПри обычном использовании менеджера сеансов X сервер является единственным клиентом, который устанавливает TCP-соединение сXvncСервер отображения X Window System. Когда сеанс xrdp активен, связанный сервер отображения Xvnc имеет два TCP-подключения, одно в состоянии ESTABLISHED, а другое в состоянии LISTEN. Это выглядит примерно так с использованиемlsof(1)программа.

$ sudo lsof  -b -w -n -c /^Xvnc$/b -a -iTCP:5900-5999 
COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
Xvnc    1625 guest    1u  IPv4 252910      0t0  TCP 127.0.0.1:5910 (LISTEN)
Xvnc    1625 guest    9u  IPv4 261226      0t0  TCP 127.0.0.1:5910->127.0.0.1:35242 (ESTABLISHED)

Если пользователь удаленного сеанса покидает его, закрыв RDP-соединение (или, в случае сеанса Apache Guacamole RDP, закрыв окно браузера), это выглядит примерно так:

COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
Xvnc    1625 guest    1u  IPv4 252910      0t0  TCP 127.0.0.1:5910 (LISTEN)

Обратите внимание, что на этом отключенном процессе сервера отображения Xvnc нет УСТАНОВЛЕННОГО соединения. Таким образом, любой процесс Xvnc, который только слушает, является отключенным сеансом.

Вот скрипт оболочки (названный lsdisconnected), который отображает PID и USER для каждого отключенного удаленного сеанса. Он используетlsof(1)итаращиться(1)для реализации логики подключения.

#!/bin/bash
sudo lsof -FRgpLT -b -w -n -c /^Xvnc$/b -a -iTCP:5900-5999  |
gawk '
      match($0,/^p([0-9]+)/,       p) {pid = p[1]; pids[pid]=0; } ;
      match($0,/^L([A-Za-z0-9]+)/, p) {user[pid] = p[1]; } ;
      /TST=LISTEN/ {pids[pid] = pids[pid] - 1 ;};
      /TST=ESTABLISHED/{pids[pid] = pids[pid] + 1};
      END {
          for (pid in pids){
              if (pids[pid] < 0) {
                  print pid, user[pid];
              }
          }};
     '

Это удобный способ найти отключенные сеансы удаленного рабочего стола; он срабатывает сразу после отключения, без необходимости использования времени простоя.

Для тех, кто, возможно, не знакомlsof(1)Вот объяснение параметров командной строки в этом примере.

  • -b -wизбегает ожиданий ядра lsof. Они здесь не нужны.
  • -nпозволяет избежать поиска DNS-имен хостов.
  • -c /^Xvnc$/bищет процессы с точным именем команды Xvnc, используя регулярное выражение.
  • -aуказывает lsof использовать AND, а не OR при фильтрации.
  • -iTCP:5900-5999(Фильтры по TCP-портам с номерами 5900 - 5999, которые используются для подключений X-дисплея.)

решение2

Я наконец нашел решение этой проблемы.
Прежде всего, мне пришлось установить небольшую программу под названием xprintidle:

sudo apt-get install xprintidle

После этого я написал небольшой bash-скрипт, который сначала извлекает все дисплеи, используемые Xvnc и xrdp, а затем проверяет эти сеансы отображения, если они бездействуют более определенного количества минут:

#!/bin/bash

displays=`ps aux | grep Xvnc | grep -v 'grep\|sed' | sed -r 's|.*(Xvnc :[0-9]*).*|\1|' | cut -d' ' -f 2`
limit=180


date
echo "Checking for inactive sessions!"
while read -r d; do
    export DISPLAY=$d
    idle=`xprintidle`
    idleMins=$(($idle/1000/60))
    if [[ $idleMins -gt $limit ]]; then
        echo "WARN Display $d is logged in for longer than ${limit}min (${idleMins}m)"
    else
        echo "INFO Display $d is still ok (${idleMins}m)"
    fi  
done <<< "$displays"

решение3

Старый пост, но у меня та же проблема: параметры KillDisconnected/DisconnectedTimeLimit/IdleTimeLimit в sesman.ini неактивны в Xvnc.

Простым решением является добавление следующих параметров в sesman.ini в параграфе [Xvnc]:

paramX=-MaxDisconnectionTime
paramX=3600

(при этом X зависит от того, сколько параметров уже определено)

При этом отключенные сеансы автоматически завершаются через 1 час.

решение4

Спасибо за lsof-fu! Обнаружение «мертвых» Xvncсеансов было давней проблемой для Xrdp. Я включил код О. Джонса в скрипт оболочки, который можно загрузить при загрузке и запустить с экрана, чтобы очистить мертвые Xvncпроцессы, оставшиеся после того, как пользователь закрывает свое окно RDP или соединение разрывается по какой-либо причине. Я так и не нашел способа Xrdpсправиться с этим, так что этот lsofкод идеален.

#!/bin/bash

#
# this could be launched from rc.local via screen
#   echo '/usr/bin/screen -dmS xrdp_cleanup /root/bin/xrdp_cleanup_discod_sessions' | at now
#
while [ 1 ]; do
   # loop through all listening Xvnc processes and make sure there's an established connection
   for pid in `lsof -b -w -n -c /^Xvnc$/b -a -iTCP:5900-5999 | grep L[I]STEN | awk '{print $2};'`; do

      # new sessions may take a second or two on busy systems. 
      # wait for new LISTEN sessions to be become established. this also acts as a throttle for the loop
      sleep 2

      # get user for the established session
      euser=`lsof -b -w -n -c /^Xvnc$/b -a -iTCP:5900-5999 | grep L[I]STEN | grep "$pid" | awk '{print $3};'`
      esta=`lsof -b -w -n -c /^Xvnc$/b -a -iTCP:5900-5999 | grep E[S]TABLISHED | grep "$pid" | awk '{print $2};'`

      test -z "$euser" && echo "Unable to find user in lsof output!"

      if [ -n "$esta" ]; then
         # regular status update
         echo "user $euser has an established sesson on pid $pid"
      else
         isrunning="yes"

         # make sure the process is killed. keep trying.
         while [ -n "$isrunning" ]; do
            echo "Established session for user $euser is gone. killing pid $pid.."
            kill $pid
            sleep 1
            isrunning=`ps -ef | grep $pid | grep -v grep`
            test -z "$isrunning" && echo "$pid killed OK"
         done
      fi
   done
done

Связанный контент