The quick and simple task of starting a python FTP server (instead of TFTP) and transferring the image on to a router.

This post is uses the python library PyFTPdLib

I enjoy writing as much as I enjoy coding. My posts tend to be a lot longer and wordier than they need to be. Today, however, will be a departure. I don't have a lot to say.

I have been experiencing some problems using TFTP to transfer ios images on to some routers. New images are large. I had been looking for a nice small FTP server to run on my laptop. My coworkers and I have found several different things that worked, but this was super fun for me. Running a FTP server on one line. The same line on linux or windows. It can be scripted. This post is just about the quick and simple task of starting the server and transferring the image on to a router.

This post is about using PyFTPdLib written by Giampaolo Rodola.
pyftpdlib-1.5.6.
https://pythonhosted.org/pyftpdlib/
https://github.com/giampaolo/pyftpdlib
https://pypi.python.org/pypi/pyftpdlib/

I am playing with python 3.6 for my programming distractions. I had to install the PyFTPdLib library. and update pip first
C:\>python -m pip install --upgrade pip
"C:\>python -m pip install pyftpdlib"

My use case is my laptop is directly connected to the router. I can't use a USB (or other removable media) to transfer the ios image over. I have console access to the router, and a direct ethernet connection. I am uploading to a blank router with the only connection to my laptop. I'm using anonymous FTP.

Don't forget to permit FTP through the firewall. Open a command prompt, and browse to the folder with the image I want to share.

To perform the anonymous FTP Transfer, one line is run from the command line of the server machine, then the FTP transfer is initiated from the router.

Windows part (this launches the FTP Server) The -p switch is for tcp port 21:
C:\TFTP\IR809>python -m pyftpdlib -p 21
Router Part:
IR800#copy ftp://anonymous@192.168.20.9 flash:
Address or name of remote host [192.168.20.9]?
Source filename []? ir800-universalk9-bundle.SPA.155-3.M5.bin

here is the directory and output, from the server and from the router

Directory of C:\TFTP\IR809
29/04/2016 09:12 AM 144,082,060 ir800-universalk9-bundle.SPA.155-3.M2.bin
18/06/2017 09:15 AM 144,167,728 ir800-universalk9-bundle.SPA.155-3.M5.bin
4 File(s) 288,263,002 bytes
2 Dir(s) 21,685,391,360 bytes free

the library provides really good feedback about who is connected and what is happening for troubleshooting

C:\TFTP\IR809>python -m pyftpdlib -p 21
[I 2017-08-10 09:50:18] >>> starting FTP server on 0.0.0.0:21, pid=6644 <<<
[I 2017-08-10 09:50:18] concurrency model: async
[I 2017-08-10 09:50:18] masquerade (NAT) address: None
[I 2017-08-10 09:50:18] passive ports: None
[I 2017-08-10 09:51:49] 192.168.20.15:54483-[] FTP session opened (connect)
[I 2017-08-10 09:51:49] 192.168.20.15:54483-[anonymous] USER 'anonymous' logged in.
[I 2017-08-10 09:51:49] 192.168.20.15:54483-[anonymous] RETR
C:\TFTP\IR809\ir800-universalk9-bundle.SPA.155-3.M5.bin completed=0 bytes=65536 seconds=0.375
[I 2017-08-10 09:51:49] 192.168.20.15:54483-[anonymous] FTP session closed (disconnect).
[I 2017-08-10 09:51:49] 192.168.20.15:60037-[] FTP session opened (connect)
[I 2017-08-10 09:51:49] 192.168.20.15:60037-[anonymous] USER 'anonymous' logged in.
[I 2017-08-10 09:51:49] 192.168.20.15:60037-[anonymous] RETR
C:\TFTP\IR809\ir800-universalk9-bundle.SPA.155-3.M5.bin completed=0 bytes=131072 seconds=0.0
[I 2017-08-10 09:51:49] 192.168.20.15:60037-[anonymous] FTP session closed (disconnect).
[I 2017-08-10 09:51:49] 192.168.20.15:21570-[] FTP session opened (connect)
[I 2017-08-10 09:51:49] 192.168.20.15:21570-[anonymous] USER 'anonymous' logged in.
[I 2017-08-10 09:51:49] 192.168.20.15:21570-[anonymous] RETR
C:\TFTP\IR809\ir800-universalk9-bundle.SPA.155-3.M5.bin completed=0 bytes=131072 seconds=0.0
[I 2017-08-10 09:51:49] 192.168.20.15:21570-[anonymous] FTP session closed (disconnect).
[I 2017-08-10 09:51:49] 192.168.20.15:27592-[] FTP session opened (connect)
[I 2017-08-10 09:51:49] 192.168.20.15:27592-[anonymous] USER 'anonymous' logged in.
[I 2017-08-10 09:53:57] 192.168.20.15:27592-[anonymous] RETR
C:\TFTP\IR809\ir800-universalk9-bundle.SPA.155-3.M5.bin completed=1 bytes=144167728 seconds=127.969
[I 2017-08-10 09:53:57] 192.168.20.15:27592-[anonymous] FTP session closed (disconnect).
IR800#sh arp Protocol Address Age (min) Hardware Addr Type Interface
Internet 192.168.20.15 - 00a3.8e44.184f ARPA GigabitEthernet0
IR800#ping 192.168.20.9
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.20.9, timeout is 2 seconds:
.....
Success rate is 0 percent (0/5)

! permit ping and ftp through windows firewall!

IR800#ping 192.168.20.9
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.20.9, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/1/2 ms
IR800#copy ftp://anonymous@192.168.20.9 flash:
Address or name of remote host [192.168.20.9]?
Source filename []? ir800-universalk9-bundle.SPA.155-3.M5.bin
Destination filename [ir800-universalk9-bundle.SPA.155-3.M5.bin]?
Accessing ftp://*@192.168.20.9/ir800-universalk9-bundle.SPA.155-3.M5.bin...
Loading ir800-universalk9-bundle.SPA.155-3.M5.bin
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

[OK - 144167728/4096 bytes]

144167728 bytes copied in 129.516 secs (1113127 bytes/sec)

IR800#

Other switches/options for the command line implementation of PyFTPdLib are:

E:\DougsProgs>python -m pyftpdlib -help
Usage: python -m pyftpdlib [options]

Start a stand alone anonymous FTP server.

Options:
-h, --help
show this help message and exit
-i ADDRESS, --interface=ADDRESS
specify the interface to run on (default all interfaces)

-p PORT, --port=PORT
specify port number to run on (default 2121)

-w, --write
grants write access for the anonymous user (default read-only)

-d FOLDER, --directory=FOLDER
specify the directory to share (default current directory)

-n ADDRESS, --nat-address=ADDRESS
the NAT address to use for passive connections

-r FROM-TO, --range=FROM-TO
the range of TCP ports to use for passive connections (e.g. -r 8000-9000)

-D, --debug
enable DEBUG logging evel

-v, --version
print pyftpdlib version and exit

One of my supervisors at GCI told me, "Anytime I have to do the same operation on different data, it is worth looking at how to script it." (thanks Mike)

I'm in IT. I'm not meant to make things easy. Please don't tell anyone.

Doug