CCNP / Learning Path
E06 ENCOR Core · Medium · 70-95 min · 3x IOSv, 1x IOSvL2

Management-Plane Security

Difficulty 70-95 min 3x IOSv, 1x IOSvL2
Lab brief & addressing
E06 topology card

Topology Open full size ↗

The Mission

R1 is a production router and right now anyone who can reach it can log in over cleartext Telnet with no real authentication. By the end, R1 must accept SSH only, from the trusted subnet only — and you must prove with real sessions that ADMIN gets in over SSH, Telnet is refused, and ROGUE is turned away at the VTY door while it can still ping R1. That last part is the whole lesson: locking the management door must not break the network the router carries.

You'll be able to

  • Replace Telnet with SSHv2 and store every credential as a hash, not plaintext.
  • Force authentication on the VTY lines with login local — and explain why no login is a back door.
  • Restrict who can even reach the VTYs with an access-class ACL, so a wrong source IP is dropped before the password prompt.

Before you start

  • Finished E05 (you can read show run sections and gather evidence).
  • Three IOSv routers: R1 is the device you harden; ADMIN and ROGUE are IOSv test stations that stand in for admin workstations — unlike a VPCS host, an IOS device can actually originate an ssh and a telnet session, so every proof in this lab is a real login you run, not a screenshot. One l2switch (SW1) forms the trusted management LAN.
  • ADMIN sits on the trusted subnet through SW1; ROGUE hangs off R1's second interface on a separate, untrusted subnet. R1 routes between the two, so before you harden anything every station can already ping R1. Hardening must change who can log in without changing who can ping.

Addressing plan

Device / InterfaceAddress (/mask)Role
R1 Gi0/0 (to SW1)10.80.99.1 / 24device being hardened
R1 Gi0/1 (to ROGUE)10.80.66.1 / 24gateway for the untrusted subnet
ADMIN Gi0/010.80.99.10 / 24, gw .1allowed to reach VTY
ROGUE Gi0/010.80.66.66 / 24, gw .1must be denied VTY access

The one idea behind this lab

The management plane is the path you use to log in to a device — the VTY lines, the credentials, the protocol that carries them. It is not how the router forwards packets; it is how you drive the router. That makes it a prime target: crack the front door and you own the box.

Hardening it is defense in depth on one door, in four independent layers: (1) carry the session over an encrypted transport (SSH, not Telnet); (2) store credentials as hashes so a captured config leaks nothing usable; (3) require authentication on every VTY line (login local); and (4) restrict who may even open a VTY at all (access-class). Each layer survives the failure of the others — that is the whole point.

See & Do Turn Telnet into SSH-only on R1

Type these on R1 exactly. After each block, read the output panel before moving on — the goal is to connect a command to the protection it adds.

Lay the groundwork SSH needs (name, domain, key)

R1> enable
R1# configure terminal
R1(config)# hostname R1
R1(config)# ip domain name lab.local   ! hostname + domain = the key's name
R1(config)# crypto key generate rsa modulus 2048
The name for the keys will be: R1.lab.local
% Generating 2048 bit RSA keys, keys will be non-exportable...
[OK] (elapsed time was 2 seconds)

*Jun 29 14:02:11.733: %SSH-5-ENABLED: SSH 1.99 has been enabled
Why this order? SSH encrypts with an RSA key, and IOS names that key hostname.domain. No hostname or no domain name and crypto key generate is refused. The %SSH-5-ENABLED log line is your proof the key exists and the SSH server woke up.

Create hashed credentials and pin SSH to version 2

R1(config)# enable secret S3cret-Enable!   ! privileged-mode password, stored hashed
R1(config)# username admin privilege 15 secret S3cret!   ! local account, also hashed
R1(config)# ip ssh version 2   ! refuse the weaker SSHv1
R1(config)# service password-encryption   ! masks any remaining type-7 passwords too
Read it like this: secret (not password) means the credential is stored as a one-way hash — a stolen config shows $1$... or $9$..., never the word you typed. privilege 15 drops admin straight into enable mode on login. ip ssh version 2 closes the downgrade path to SSHv1.

Lock the VTY lines to SSH and require a real login

R1(config)# line vty 0 4
R1(config-line)# transport input ssh   ! drop Telnet entirely
R1(config-line)# login local   ! authenticate against the username database
R1(config-line)# end
What just changed: the VTYs now accept only SSH, and every session must present a username/password from the local database. transport input ssh alone refuses Telnet; login local alone closes the "press enter to get in" hole. You need both.

Read the evidence (this is the skill, not the typing)

R1# show ip ssh
SSH Enabled - version 2.0
Authentication methods:publickey,keyboard-interactive,password
Authentication timeout: 120 secs; Authentication retries: 3

Now jump to the ADMIN station (10.80.99.10) and open a real SSH session — an IOS device is its own SSH client:

ADMIN# ssh -l admin 10.80.99.1
Password: ! S3cret!
R1#                       ! privilege 15 -> straight into enable mode

From the same station, plain Telnet is refused — R1 no longer listens on port 23 at all:

ADMIN# telnet 10.80.99.1
Trying 10.80.99.1 ...
% Connection refused by remote host   ! transport input ssh -> nothing answers on tcp/23
Both proofs in hand, from a real session: show ip ssh says SSH Enabled - version 2.0 (encrypted transport, no v1), and the live test shows SSH in / Telnet refused. Because you ran these from an actual device, the refusal is the router's own TCP reset, not a claim — transport input ssh means tcp/23 is simply not open.

Now You (guided) Restrict who can reach the VTYs

SSH-only stops the wrong protocol. It does nothing about the wrong source — right now anyone with SSH and a stolen password can try, from anywhere. Close that with an access-class ACL that only lets the management subnet even open a VTY. You write the lines; I'll give you the target.

  1. Build a standard named ACL MGMT-IN that permits the management subnet 10.80.99.0/24 (and nothing else — the implicit deny does the rest).
  2. Apply it to the VTY lines with access-class MGMT-IN in under line vty 0 4 — note it's access-class, not ip access-group, because VTYs are lines, not interfaces.

Target to hit — three things at once: SSH from ADMIN (10.80.99.10) still works; an SSH attempt from ROGUE (10.80.66.66) is dropped before the password prompt; and ROGUE can still ping 10.80.99.1. That last one is the proof you did management-plane filtering, not a blunt interface ACL — the router still routes the rogue's data, it just refuses to let it log in.

Stuck? Reveal the MGMT-IN config
R1(config)# ip access-list standard MGMT-IN
R1(config-std-nacl)# permit 10.80.99.0 0.0.0.255
R1(config-std-nacl)# exit
R1(config)# line vty 0 4
R1(config-line)# access-class MGMT-IN in   ! filter inbound VTY sessions by source IP
R1(config-line)# end

The wildcard 0.0.0.255 matches the whole /24. There is no explicit deny line — the implicit deny at the end of every ACL turns away every other source, including 10.80.66.0/24. Note it is applied to line vty, not to an interface: that is why it filters logins but not routed traffic.

What "correct" looks like
ADMIN# ssh -l admin 10.80.99.1        ! source 10.80.99.10 - allowed
Password:
R1#

ROGUE# ssh -l admin 10.80.99.1        ! source 10.80.66.66 - denied at the VTY
% Connection refused by remote host

ROGUE# ping 10.80.99.1                 ! ...but data-plane reachability is untouched
Sending 5, 100-byte ICMP Echos to 10.80.99.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/8 ms

Read the pair of ROGUE results together. The SSH is refused before any password prompt — brute-forcing the password is off the table for any source outside 10.80.99.0/24. Yet the ping still returns !!!!!: the router happily forwards the rogue's packets, it just won't let that source open a VTY. Filtering the who-can-log-in without touching who-can-be-routed is exactly what access-class on a line does — and exactly what an ip access-group on the interface would not do (that would drop the ping too).

On R1 you can watch it: show ip access-lists MGMT-IN shows the permit hit count climb on good sessions and stay flat for the rogue — the rogue's SSH never counted as a permit.

Solo Challenge No commands this time

Do this from memory

Add three more hardening controls to R1's management plane, and for each one state the command and the attack it mitigates:

  • An idle session timeout on the VTY lines, so an abandoned SSH session can't sit logged in.
  • Brute-force protection that locks out login attempts after repeated failures within a window.
  • Logging of login activity so failed and successful logins leave a record.

You pass when all three are true:

  • You can name the VTY-line command for an idle timeout and say what it limits (hint: it lives under line vty and takes minutes and seconds).
  • You can name the global command that throttles repeated failed logins and the two login commands that make those events show up in the log.
  • You can say, in one sentence each, the threat each control blunts — a forgotten open session, a password-guessing flood, and a silent intrusion with no audit trail.
Check your reasoning (open only after you've done it)

Idle timeout — under line vty 0 4: exec-timeout 5 0 closes any session idle for 5 minutes. Mitigates an admin who walks away leaving an authenticated SSH session open for someone else to hijack.

Brute-force protection — globally: login block-for 120 attempts 5 within 60 means "after 5 failed logins in 60 seconds, refuse all login attempts for 120 seconds." Mitigates an automated password-guessing flood by making it pause and crawl.

Logging — globally: login on-failure log and login on-success log (paired with a logging host 10.80.99.10 to ship them off-box). Mitigates a silent intrusion — without a record, you never learn the front door was rattled or opened.

Together these turn a quiet door into a watched, rate-limited, self-closing one. None of them replaces SSH, hashes, login local, or the access-class — they stack on top. That stacking is defense in depth.

Break & Fix Re-open the front door, on purpose

Now create the exact misconfiguration you'll find on neglected gear, so you know its fingerprint on sight. On R1, undo the transport and authentication controls on the VTY lines:

R1(config)# line vty 0 4
R1(config-line)# transport input all   ! Telnet is back on the menu
R1(config-line)# no login   ! and no password is required at all

From ADMIN, Telnet now connects straight to a prompt — no username, no password:

ADMIN# telnet 10.80.99.1
Trying 10.80.99.1 ... Open


R1>                       ! straight in, cleartext, unauthenticated

The access-class MGMT-IN is still in place, so ROGUE is still turned away here — but that is luck, not design. On real neglected gear the access-class is usually missing too, and then this exact door is open to every source that can route to R1.

Read the fingerprint in the config itself:
R1# show run | section line vty
line vty 0 4
 no login
 transport input all
The teaching point: this is an open, cleartext management plane — transport input all permits Telnet (every keystroke and password in plaintext on the wire), and no login removes authentication entirely. Either one alone is dangerous; together they mean anyone with a route to R1 owns it. This is the single most common real-world management-plane failure.

Now fix it — restore all three controls and confirm Telnet dies and the rogue is denied again:

R1(config)# line vty 0 4
R1(config-line)# transport input ssh
R1(config-line)# login local
R1(config-line)# access-class MGMT-IN in
R1(config-line)# end

Done check

Close this lab when, with the hardened config restored, all of these are true:

Run / testProof you want
show ip ssh on R1SSH Enabled - version 2.0
ssh -l admin 10.80.99.1 from ADMINLogs in to R1#
telnet 10.80.99.1 from ADMIN% Connection refused by remote host
show run | section line vty on R1Shows transport input ssh, login local, access-class MGMT-IN in
ssh -l admin 10.80.99.1 from ROGUEDenied at the VTY — no password prompt
ping 10.80.99.1 from ROGUE!!!!! — data plane still works; only login is filtered

Takeaway for your notes: "Encrypt the transport, hash the credentials, require the login, restrict the source — four independent layers on one door, and the front door is the whole device."

Reset this lab?

Restore its GNS3 project to the original unsolved topology.

All saved device configuration in this lab will be erased. Every node must be stopped first.