Como localizar sessões de xrdp desconectadas?

5

Eu tenho um servidor Xubuntu 14.04 aqui que executa o xrdp para ter alguns usuários conectados a ele. Agora, há um problema: os usuários que acessam esse servidor via RDP a partir de thin clients Windows geralmente usam o "X" para fechar a sessão RDP (portanto, desconecte, mas não faça logout).

Eu sei que há algumas opções no sesman.ini para lidar com esse tipo de comportamento, mas, como diz a manpage, essas opções são atualmente ignoradas (e já existem há anos). As opções que resolveriam meus problemas são:
KillDisconnected
DisconnectedTimeLimit
IdleTimeLimit

Agora preciso hackear algo que lide com sessões desconectadas. Meu primeiro pensamento foi simplesmente matar todos os usuários remotos que estão desconectados - mas não sei como obter as informações sobre quais sessões estão desconectadas.

Então ... como faço para encontrar sessões desconectadas?
Ou: já existe alguma maneira preferida de lidar com sessões desconectadas?

    
por wullxz 06.10.2015 / 15:32

3 respostas

3

Eu finalmente encontrei uma solução para isso.
Primeiro de tudo, eu tive que instalar um pequeno programa chamado xprintidle :

sudo apt-get install xprintidle

Depois disso, escrevi um pequeno script que primeiro busca todas as exibições usadas pelo Xvnc e pelo xrdp e, em seguida, verifica as sessões de exibição se elas estiverem inativas por mais de alguns minutos:

#!/bin/bash

displays='ps aux | grep Xvnc | grep -v 'grep\|sed' | sed -r 's|.*(Xvnc :[0-9]*).*||' | 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"
    
por 31.03.2016 / 17:59
4

Aqui está uma maneira de obter uma lista de sessões de xrdp desconectadas. Ele se baseia no fato de que o servidor xrdp é, no uso normal do gerenciador de sessões X, o único cliente que estabelece uma conexão TCP com o servidor de exibição Xvnc X Window System. Quando uma sessão xrdp está ativa, o servidor de exibição Xvnc associado tem duas conexões TCP, uma no estado ESTABLISHED e a outra no estado LISTEN. Isso se parece com isso usando o programa 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)

Se o usuário da sessão remota o abandona fechando a conexão RDP (ou, no caso de uma sessão RDP do Apache Guacamole, fechando a janela do navegador), é algo como isto:

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

Observe que não há nenhuma conexão ESTABLISHED neste processo do servidor de exibição Xvnc desconectado. Portanto, qualquer processo Xvnc que esteja apenas ouvindo é uma sessão desconectada.

Aqui está um script de shell (denominado lsdisconnected ) que exibe o PID e o USUÁRIO para cada sessão remota desconectada. Ele usa lsof (1) e gawk (1) para implementar a lógica de conexão.

#!/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];
              }
          }};
     '

Esta é uma maneira prática de encontrar sessões de área de trabalho remota desconectadas; funciona imediatamente após a desconexão, sem a necessidade de usar um tempo ocioso.

Para quem não está familiarizado com lsof (1) , aqui está uma explicação dos parâmetros da linha de comando neste exemplo.

  • -b -w evita esperas de kernel lsof. Eles não são necessários aqui.
  • -n evita pesquisas de DNS para nomes de host.
  • -c /^Xvnc$/b procura por processos com o nome de comando exato Xvnc, usando um regex.
  • -a diz ao lsof para usar AND, não OR ao filtrar.
  • -iTCP:5900-5999 filtra por portas TCP numeradas de 5900 a 5999, aquelas usadas para conexões de exibição X.)
por 20.07.2016 / 17:22
0

Obrigado pelo lsof -fu! Detectar% dead Xvnc sessions tem sido um problema de longa data com Xrdp . Eu incorporei o código do O. Jones em um shell script que pode ser carregado na inicialização e executado a partir da tela para limpar dead Xvnc processos deixados para trás quando um usuário fecha sua janela RDP, ou a conexão cai por qualquer motivo. Eu nunca encontrei uma maneira com Xrdp para lidar com isso, então esse código lsof é perfeito.

#!/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
    
por 03.05.2017 / 20:08

Tags