Have you ever found yourself in a strange situation where:

  • you had a Juniper device with a factory default JunOS
  • it came with no-export version -> just telnet available, no SSH
  • you have the fxp0 or em0 interface configured for remote access
  • you do not have the device next to you and need to upgrade its software so that you can finally have full functionality and SSH?

Let’s say that with a big of creativity you can always find a way in. Here we go:

Table of Contents

Method 1 - FTP

I won’t detail this one here but just the idea. Stop the telnet service if you also have console access. Bind the FTP service of JunOS on port 22. Upload your image via FTP.

Method 2 - netcat - it does not exist, you would need to disable veriexec (which on newer versions is quite a headache)

If you would manage to do it, then you would pipe the file through netcat between your PC and the Juniper device.

Older JunOS had a more simple way to disable veriexec if you would be able to jump into the debugger:

  • set system debugger-on-break
  • send JunOS a break signal via your favorite terminal
  • disable veriexec as per below (Occam JunOS does not allow this anymore)
db> write
mac_veriexec_state 0x0
mac_veriexec_state                  0x7       =              0
db> continue

Method 3 - awk script

Time required: 2-3h / 2 GB iso.

#JunOS side
vim script.sh
echo "open 172.17.185.26"
sleep 2
echo "jtac"
sleep 1
echo "8453-Juniper!"
sleep 1
echo "start shell"
sleep 1
echo "tee | base64 -d > test-mihai"

#Client side
cat junos-install-mx-x86-64-16.1R4.7.tgz   | base64 -b 1000 | awk '{ print "echo \47" $0 "\47" }'  >> script1.sh
	echo echo "'"'^D'"'"  >> script1.sh

This causes a memory leak / swap full after 1G transferred => we do with AWK and after each 60000 lines, we sleep 10 seconds, exit the csh, sleep 10 seconds (this clears the memory), enter it again

cat junos-install-mx-x86-64-16.1R4.7.tgz   | base64 -b 1000 | awk '{ print "echo echo \42\47\42\47 " $0 "\47\42\47\42\47" " >> suge \47"; if ((NR %25000) == 0) printf("sleep 10\necho \42exit\42\nsleep 2\necho \42start shell\42\nsleep 2\n ") }' >> script1.sh

then ./script.sh | telnet

on receiving side:
cat /var/tmp/suge | base64 -d > /var/tmp/junos-install-mx-x86-64-16.1R4.7.tgz

Method 4 - just tee

$ cat script5.sh
#!/bin/bash

if [ $# -lt 6 ]
then
        echo "Usage : $0 <host> <port> <user> <pass> <local file> <remote file>"
        exit
fi

host=$1
port=$2
user=$3
pass=$4
localfile=$5
remotefile=$6

echo "open $host $port"
sleep 2
echo " "
sleep 1
echo "$user"
sleep 1
echo "$pass"
sleep 1
echo "start shell"
sleep 1
echo "tee | base64 -d > $remotefile"
sleep 1
base64 -b 1000 -i $localfile | awk '{ print $0 }'
sleep 2

$ ./script5.sh 172.16.10.94 23 mihai sug1-pula junos-install-mx-x86-64-16.1R4.7.tgz /var/tmp/g2.tgz | telnet > /dev/null

Method 5 - Perl

Time required for a 2 GB ISO = 1h
#!/usr/bin/perl -W

use strict;
use Expect;


my($host, $port, $user,$pass, $lfile, $rfile) = @ARGV;

my $t = 10;
my $magic = 'skljdfhaksjhfewkljhfliwuhlwjkfhakjsdhf';


if ( !defined $rfile ) {
        print STDERR "Usage: $0 <host> <port> <user> <pass> <local file> <remote file>\n";
        exit 1;
}

die "file '$lfile' does not exist.\n" if !-r $lfile;

my $e = Expect->spawn("telnet", $host, $port) or die "Failed to exec telnet";

$e->expect($t, "word:");
$e->send("\n");
$e->expect($t, "login:");
$e->send("$user\n");
$e->expect($t, "word:");
$e->send("$pass\n");
$e->expect($t, ">");
$e->send("start shell\n");
$e->expect($t, "%");
$e->send("tee | base64 -d > $rfile\n");
$e->log_user(0);

open(F,"base64 -b 1000 -i $lfile |");
while(<F>) { $e->send($_); }
close(F);

$e->log_user(1);

$e->send("\cD");
$e->expect(100, "%");
$e->send("exit\n");
$e->expect($t, ">");
$e->send("quit\n");
$e->soft_close();