Skip to content

Latest commit

 

History

History

chapter16

Return to the Table of Contents

Chapter 16
Telnet and SSH

This is a directory of program listings from Chapter 16 of the book:

Foundations of Python Network Programming
Third Edition, October 2014
by Brandon Rhodes and John Goerzen

You can learn more about the book by visiting the root of this GitHub source code repository.

These scripts were written for Python 3, but can also run successfully under Python 2. Simply use 3to2 to convert them to the older syntax.

Before diving into Telnet and SSH, the chapter introduces a small shell program shell.py that interprets nothing but whitespace as special on the command line, in an attempt to demonstrate to the skeptical reader that all of the characters they are used to treating as special are in fact quite ordinary down at the level of the operating system.

Once the reader has been instructed as to the role of command lines, the features of terminals, and the pitfalls of special characters and quoting, two scripts are introduced which use the old insecure Telnet protocol. They can be exercised in the Playground against the ftp.example.com server which, just for fun, has a Telnet server running as well.

$ python3 telnet_login.py ftp.example.com brandon
exec uptime
21:18:15 up  5:40,  1 user,  load average: 0.00, 0.02, 0.05
$ python3 telnet_codes.py ftp.example.com brandon
Sending terminal type "mypython"
('Will not', 32)
('Will not', 35)
('Will not', 39)
('Do not', 3)
('Will not', 1)
('Will not', 31)
('Do not', 5)
('Will not', 33)
('Do not', 3)
('Do not', 1)
exec echo My terminal type is $TERM
My terminal type is mypython

When running the SSH scripts, you can target any of the hosts running in the Playground — they are all running SSH and should have both a root user and brandon user. For the examples below we will use the latter. To avoid having to edit the program listings to provide a password argument to client.connect(), ask SSH to install the root identity under the brandon account to which you wish to connect. Because Docker does not launch your initial shell on a host with everything set up as though you had logged in, this will only work if you su to the root user first:

$ ssh h1

# su root

# ssh-copy-id brandon@www.example.com

By entering the brandon password abc123 the ID should be copied successfully and a plain SSH command should then succeed without a password:

# ssh brandon@www.example.com echo Success
Success

Once ssh itself is working without a password, the Python scripts should succeed as well.

$ python3 ssh_simple.py www.example.com brandon
Welcome to Ubuntu 14.04.1 LTS (GNU/Linux 3.13.0-24-generic x86_64)

 * Documentation:  https://help.ubuntu.com/
Last login: Wed Oct 22 21:38:21 2014 from modema

echo Hello, world
exit
$ Hello, world
$ 

As you can see, trying to speak over a single communications channel to both a shell and the programs it invokes is something of a disaster. The book explains a better approach:

$ python3 ssh_commands.py www.example.com brandon
b'Hello, world!\n'
b'Linux\n'
b' 21:38:33 up  6:00,  0 users,  load average: 0.16, 0.05, 0.06\n'

The ability of SSH to support several channels even allows multiple Python threads to have remove commands running at the same time.

$ python3 ssh_threads.py www.example.com brandon
One
A
B
Two
Three
C

Finally, SSH includes a built-in file transfer protocol SFTP.

$ python3 sftp_get.py www.example.com brandon /etc/lsb-release
Transfer of '/etc/lsb-release' is at 105/105 bytes (100.0%)
Transfer of '/etc/lsb-release' is at 105/105 bytes (100.0%)