08 May 2009

When you want to quit a SSH session, you usually simply enter exit. But sometimes, there is no exit or alike command available, say, when a session is NOT a shell or not responding. In this case, we often use the escape sequence ~. to terminate the connection. This solution, however, may cause some confusion when nested SSH sessions are involved. Suppose you ssh from host A to server B and then from B ssh to C, when you type the escape sequence ~., it is not the session from B to C but the session for A to B that quits. And, nested telnet sessions are in a similar situation. This blog is to answer why this happens and present a way to quit nested ssh/telnet sessions (from B to C).

NOTE: ~. is the default escape sequence that terminates ssh connections. To enter it, press <enter> then ~ then .. The default escape sequence for telnet connections is ^]q, i.e. press Ctrl+] then press q.

The Reason

 O  normal chars              normal chars            normal chars
/|\ ------------> localhost A ------------> machine B ------------> machine C
/ \  keyboard                 ssh session1            ssh session2


                               '~' NOT
 O      ~                      fowarded
/|\ ------------> localhost A ------------> machine B ------------> machine C
/ \  keyboard                 ssh session1            ssh session2
                             enter command mode


 O      .                       closed
/|\ ------------> localhost A -----X------> machine B ------------> machine C
/ \  keyboard                 ssh session1            ssh session2

Solutions

Use different escape characters

All sessions use different escape characters. Or, disable escape in first the telnet/ssh session.

ssh -e none hostname            # for ssh
telnet -E hostname              # for telnet

Or, in session A send escape characters to session B explicitly

For nested telnet sessions:

  1. Enter command mode of telnet session A by typing an ^]
     O   ^]                     NOT forwarded
    /|\ -------> Telnet session --------> Telnet session ---> machine C
    / \           on Machine A             On Machine B
    
  2. Type in command send escape so that session A send an escape character to session B (and quit command mode). Session B thereby enter command mode as well.
     O  "send escape"              ^]
    /|\ --------> Telnet session --------> Telnet session ---> machine C
    / \           on Machine A             On Machine B
    
  3. Type q. Since session A is now in normal mode, q is transfered to session B, which just entered command mode. Therefore, session B quit upon the receiving of q.
     O    'q'                      'q'
    /|\ --------> Telnet session --------> Telnet session -X-> machine C
    / \           on Machine A             On Machine B
    

This technique works with ssh as well but is much simpler: press as many ~ as level of nest before . (by default, ~ is the escape character while . is to terminate ssh).



blog comments powered by Disqus