Updating My Cisco 4321 Router's IOS over HTTP, FTP and TFTP and More
I recently got my hands on a second-hand Cisco 4321 router. First things first, I want to upgrade to the latest IOS version so I have the latest security patches. Having no experience at all with IOS, these are some things I learned along the way.
Conventions Used in This Post
Router>
is a command prompt that indicates the user in currently in EXEC mode.
Router#
indicates that the user is in privileged EXEC mode. You get from EXEC
to privileged EXEC mode by:
Router>enable
Router#disable
Router>
Depending on your setup, you might need to type a password after enable
.
Every owner of Cisco equipment knows this, but I am one of my own future readers, so I need to keep things simple.
What Version Do I Currently Run?
Router>sh version
That shows:
Cisco IOS XE Software, Version 16.06.04
Cisco IOS Software [Everest], ISR Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.6.4, RELEASE SOFTWARE (fc3)
...
System returned to ROM by Reload Command
System image file is "bootflash:isr4300-universalk9.16.06.04.SPA.bin"
Last reload reason: Reload Command
...
I am running IOS XE 16.06.04 and it got loaded from the file
isr4300-universalk9.16.06.04.SPA.bin
stored on the bootflash
.
Finding an Appropriate IOS Image
Turns out Cisco are dicks difficult about updates. You need a service contract
before you can get a download link.
You can find your router model and navigate to the downloads tab. If you have a support contract, you can log in and presumably download the latest version. Also, Cisco hints that some older version might be available without a contract. But why would you want an old version with lots of security problems to run on an internet-facing router, right?
I do not have a service contract. I did notice the previous owner had a newer version of the firmware on the router’s flash memory:
Router#dir :flash
...
18 -rw- 763905745 Nov 9 2023 15:45:02 +00:00 isr4300-universalk9.17.09.04.SPA.bin
...
Also, it looks like sometimes an IOS release falls off a truck. Search your
favorite search engine for something like intitle:index.of <image-name>
to get a sense of where these trucks drive.
Making Sure You Did Not Just Download Malware
How do I know the firmware I got was not tampered with? Get the MD5 and SHA512 checksums from the Cisco Software Download page when hovering over the filename:
At least they did not hide that information.
Now, let’s verify if the checksum on my router equals to what was published. MD5 is old and broken, so let’s go with SHA512:
Router#verify /sha512 flash:isr4300-universalk9.17.09.04.SPA.bin 34f8eff288bb485c8ca902d2e5c03f9d45a4dc881e919a6ae3f0ca3a52161eecc5c9fc7a7ed90423984ee690695293ad011590fa0e75c65ccf003f7f89b0d5c0
........................................................ <snip> ...Done!
Verified (bootflash:isr4300-universalk9.17.09.04.SPA.bin) = 34f8eff288bb485c8ca902d2e5c03f9d45a4dc881e919a6ae3f0ca3a52161eecc5c9fc7a7ed90423984ee690695293ad011590fa0e75c65ccf003f7f89b0d5c0
verify /sha512 flash:<file>
calculates the checksum for the specified file. If
you provide a checksum yourself with verify /sha512 flash:<file> <checksum>
,
the checksum is verified against your input. In this case, the checksum matches.
Sweet!
Looking at the image name, I can also see that it contains SPA
. According to
Cisco, that stands for an image Signed with key version A meant for
Production use. The file can be verified as follows:
Router#verify flash:isr4300-universalk9.17.09.04.SPA.bin
Verifying file integrity of bootflash:isr4300-universalk9.17.12.04a.SPA.bin...
Embedded Hash SHA1 : 03A19E90D4E58FEDCAC30959192B8CEEDF6D29CC
Computed Hash SHA1 : 03A19E90D4E58FEDCAC30959192B8CEEDF6D29CC
Starting image verification
Hash Computation: 100%Done!
Computed Hash SHA2: 975953771aac683df79da71226460ecb
fead063cf39b9b4f4165e8581dee89fd
733868cc148e407e76ace6c2f912dac9
fb7c95bdbd402b3fffa257c9ba6ebbd4
Embedded Hash SHA2: 975953771aac683df79da71226460ecb
fead063cf39b9b4f4165e8581dee89fd
733868cc148e407e76ace6c2f912dac9
fb7c95bdbd402b3fffa257c9ba6ebbd4
Digital signature successfully verified in file bootflash:isr4300-universalk9.17.12.04a.SPA.bin
Then there is the following command that:
Displays software authenticity-related information for the current ROMmon and the Cisco IOS image file used for booting.
Router#sh software authenticity running
SYSTEM IMAGE
------------
Image type : Production
Signer Information
Common Name : CiscoSystems
Organization Unit : IOS-XE
Organization Name : CiscoSystems
Certificate Serial Number : 675E97D5
Hash Algorithm : SHA512
Signature Algorithm : 2048-bit RSA
Key Version : A
ROMMON
------
... snip ...
You can view more information about the public keys used to verify the signed images:
Router#show software authenticity keys
At this point, I am not sure where my router got these public keys from, so I am happy to just verify the checksum of the firmware image I am downloading on the router. But good to know that there exist more robust ways to verify the firmware actually came from Cisco.
What Transfer Methods Are Available?
Router>enable
Router#copy ?
/erase Erase destination file system.
/error Allow to copy error file.
/noverify Don't verify image signature before reload.
/verify Verify image signature before reload.
bootflash: Copy from bootflash: file system
cns: Copy from cns: file system
flash: Copy from flash: file system
ftp: Copy from ftp: file system
http: Copy from http: file system
https: Copy from https: file system
null: Copy from null: file system
nvram: Copy from nvram: file system
rcp: Copy from rcp: file system
running-config Copy from current system configuration
scp: Copy from scp: file system
startup-config Copy from startup configuration
system: Copy from system: file system
tar: Copy from tar: file system
tftp: Copy from tftp: file system
tmpsys: Copy from tmpsys: file system
usb0: Copy from usb0: file system
webui: Copy from webui: file system
Most of these options look familiar, but some I have never heard of, such as
cns:
and webui:
.
Sneakernet (USB)
My router has a USB A port. When I plug in a USB drive (single partition
formatted as FAT32), it shows up under usb0
. Copy the image to flash memory:
Router#copy usb0:image.bin flash:
But you might not always have a USB drive handy (or a USB port for that matter), so let’s look at some other ways to transfer files.
Using IP
Transfer methods using IP should first have IP configured on the router:
Router>enable
Router#conf t
Router(conf)#int g0/0/0
Router(conf-if)#no shut
Router(conf-if)#ip addr 10.0.0.1 255.255.255.252
Router(conf-if)#end
On the other side, configure 10.0.0.2
. I am assuming Linux:
# ip addr add 10.0.0.2/32 peer 10.0.0.1 dev eth1
Over HTTP
I like to use Busybox’ httpd
for this:
linux$ busybox httpd -vv -f -p 5000
Router#copy http://10.0.0.2:5000/image.img flash:
10.0.0.1:13911: url:/file.txt
10.0.0.1:13911: response:200
10.0.0.1:26393: url:/file.txt
10.0.0.1:26393: response:200
Notice the duplicate requests coming from the router.
That is why I could not get Busybox’ nc
working:
linux$ cat -A res.http
#!/bin/sh
cat <<EOF
HTTP/1.1 200 OK^M$
Content-Type: text/plain^M$
Content-Length: 14^M$
^M$
Hello, world!$
EOF
linux$ chmod u+x res.http
linux$ busybox nc -lk -p 5000 -e ./res.http
connect to 10.0.0.2:5000 from 10.0.0.1:16289 (10.0.0.1:16289)
Wireshark shows nc
sending TCP RSTs after the first HTTP exchange with the
router, whereas maybe the router only tolerates graceful connection termination,
over which we have no control when using nc
. (Same goes for using busybox tcpsvd
which I will discuss later.)
Then again, maybe these duplicate HTTP requests are just an idiosyncrasy of
isr4300-universalk9.16.06.04.SPA.bin
, the version I am trying to upgrade from.
TFTP
linux# busybox udpsvd -vE 10.0.0.2 69 busybox tftpd -u ftp /srv/ftp
Busybox’ tftpd
is meant to be run by inetd
. That daemon would bind
to a port, and when a connection is made to that port, it spawns a process which
runs an executable. It hooks the network stream directly to stdin and stdout of
the process. A big upside is that the process itself does not need to have any
network code in it.
Here, instead of starting inetd
, we take Busybox’ suggestion and run the helper
program called udpsvd
that works much like inetd
but runs as a foreground
process:
Create UDP socket, bind to IP:PORT and wait for incoming packets. Run PROG for each packet, redirecting all further packets with same peer ip:port to it.
We need to run as root to be able to bind to privileged port 69
. tftpd
also
starts as root to be able to chroot
into the specified directory, but then
drops its privileges to access the files as -u <user>
.
On the router we can now transfer files:
Router#copy tftp://10.0.0.2/file.txt flash:
Destination filename [file.txt]?
Accessing tftp://10.0.0.2/file.txt...
Loading file.txt from 10.0.0.2 (via GigabitEthernet0/0/0): !
[OK - 17 bytes]
17 bytes copied in 0.018 secs (944 bytes/sec)
Also, depending on the TFTP software you are using, you might run into this caveat:
Most TFTP applications cannot transfer files larger than 16MB in size. If the Cisco IOS software you install is larger than 16MB, you must use an FTP or RCP server.
I did not have this problem with busybox tftpd
, though.
FTP
Transferring files over FTP works much the same as TFTP. Instead of using UDP, it uses TCP, though, so we have to change the Busybox’ helper program:
linux# busybox tcpsvd -vE 10.0.0.2 21 busybox ftpd -vv -a ftp /srv/ftp
On the router:
Router#copy ftp://10.0.0.2/file.txt flash:
Destination filename [file.txt]?
Accessing ftp://10.0.0.2/file.txt...
Loading file.txt
[OK - 17/4096 bytes]
17 bytes copied in 0.048 secs (354 bytes/sec)
Over a Serial Connection With minicom
On the internet, I read that in ROMMON, you can use something called “xmodem” to
transfer files. minicom
has a “send files” feature where you can choose the
xmodem protocol.
It should work like:
rommon 123 >copy xmodem: flash:image.img
However, after entering ROMMON by booting up the router and pressing Ctrl+A and then F to send a BREAK, I see only the following options:
rommon 1 > help
alias set and display aliases command
boot boot up an external process
confreg configuration register utility
dev list the device table
dir list files in file system
help monitor builtin command help
history monitor command history
meminfo main memory information
repeat repeat a monitor command
reset system reset
set display the monitor variables
showmon display currently selected ROM monitor
sync write monitor environment to NVRAM
token display board's unique token identifier
unalias unset an alias
unset unset a monitor variable
Note there is no copy
command. (Nor an tftpdlnd
command I saw mentioned
elsewhere. That command should, after setting the appropriate environment
variables, download files over TFTP.)
I am not sure at this point if this feature is supposed to be supported by every
Cisco router or not. Maybe I can unlock a privileged mode (akin to enable
in
IOS) or update the ROMMON firmware and get extended options? It would suck for
sure if all you had was ROMMON mode and no way to boot an image or get a working
image in persistent memory.
Speed Considerations
- TFTP is slow, because it uses UDP segments with a payload of 512 bytes each. It is a “lockstep” protocol: each data packet needs to be acknowledged by the receiver before the sender sends the next packet.
- FTP and HTTP use TCP. TCP allows for more payload per segment and many segments can be outstanding before the sender stops to wait for an acknowledgement. The receiver can acknowledge many segments at once, reducing overhead. The receive window size (amount of bytes that can be outstanding at any one time before the sender has to wait for acknowledgement) can grow to many megabytes.
- Sneakernet should be even faster. If the router supports USB 2.0, you should be able to expect around 30+ MiB/s depending on factors such as how fast the router can flush the data to persistent storage.
For example, the transfer of a 700+ MiB image was so tediously long over TFTP, I had to abort. FTP, on the other hand, completed in less that 5 minutes:
776523079 bytes copied in 268.943 secs (2887315 bytes/sec)
Security Considerations
Protocols like HTTP, FTP and TFTP transmit data in plaintext and do not provide any protections against snooping and tampering. While me might not care much about confidentiality when transmitting a router image, we definitely want to make sure we connect to the correct download server and get the correct image loaded in our router. Accidental alterations during transmission, such as bit flips, are caught by transport layer (UDP/TCP) checksums: the faulty UDP/TCP segment is discarded and the download server resends it automatically. Malicious alterations by a MITM can be detected by calculating the digest of the reassembled file on the destination:
On your Linux download server:
linux$ sha512sum isr4300-universalk9.17.09.04.SPA.bin
34f8eff288bb485c8ca902d2e5c03f9d45a4dc881e919a6ae3f0ca3a52161eecc5c9fc7a7ed90423984ee690695293ad011590fa0e75c65ccf003f7f89b0d5c0 isr4300-universalk9.17.09.04.SPA.bin
Compare that output with what you get on the router:
Router#verify /sha512 flash:isr4300-universalk9.17.09.04.SPA.bin 34f8eff288bb485c8ca902d2e5c03f9d45a4dc881e919a6ae3f0ca3a52161eecc5c9fc7a7ed90423984ee690695293ad011590fa0e75c65ccf003f7f89b0d5c0
........................................................ <snip> ...Done!
Verified (bootflash:isr4300-universalk9.17.09.04.SPA.bin) = 34f8eff288bb485c8ca902d2e5c03f9d45a4dc881e919a6ae3f0ca3a52161eecc5c9fc7a7ed90423984ee690695293ad011590fa0e75c65ccf003f7f89b0d5c0
To trust this digest, you need a secure connection to the router, however. This can be a connection via the serial console or over the LAN, for example, or over SSH. If you do not have a secure connection to the destination, you cannot be sure and maybe should not be servicing your router this way. Spend time to set up SSH in this case.
Also, as mentioned at the top,
if the image has something like SPA
in it, it should be digitally signed.
I have not spent much time looking into this, but if you can be certain you have
the correct public key from Cisco, this would provide the strongest guarantee
that the image has not been tampered with.
Specifying Which Image to Run on Startup
Router#conf t
Router(config)#boot system flash isr4300-universalk9.17.12.04a.SPA.bin
Router(config)#end
Router#copy running-config startup-config
Router#reload
Make sure to persist changes by writing the config to flash memory.