Guide

How to Configure SSH on a Cisco Router or Switch (Step by Step)

Telnet sends your username, password, and every command in clear text, so it has no place on a device you actually care about. SSH replaces it with an encrypted management session and is one of the first hardening steps you'll configure on real Cisco gear — and one CCNA candidates are expected to know cold. Here's the full flow on Cisco IOS: prep the device so the key will generate, lock every vty range down to SSH only, and verify it's actually working end to end — a good one to run on real IOS and check your config against an answer key rather than just memorizing the command list.

Step 1 — Set a hostname, domain name, and generate the RSA key

crypto key generate rsa has exactly one hard prerequisite: ip domain-name must be configured. Skip it and IOS refuses outright with an explicit "% Please define a domain-name first." — it does not fail silently, and the error tells you exactly what's missing.

Set a real hostname too — it's good practice, and it's what tags the generated key's FQDN (R1.lab.local instead of Router.lab.local) and shows up in your prompt from here on. But hostname is not what gates key generation: a router left on the default hostname "Router" will still generate a key just fine as long as a domain name is set. Even a made-up domain like lab.local is enough for a training rig.

With both set, generate the key with a 2048-bit modulus. This is the command that actually creates the SSH server on the box; skip it and the vty lines will have nothing to negotiate with.

R1(config)# hostname R1
R1(config)# ip domain-name lab.local
R1(config)# crypto key generate rsa modulus 2048

Step 2 — Create a local user and lock every vty range down to SSH

SSH needs something to authenticate against, so create a local user with a secret (not a plaintext password) and enough privilege to be useful.

Before you touch the vty lines, check how many actually exist — don't assume vty 0 4 is the whole story. Plenty of IOS-XE images and every Catalyst switch provision vty 0 15 (16 lines) by default, and some platforms go higher. Run show run | section ^line vty (do show run | section ^line vty works right from config mode) or line vty ? to see every range configured on the device.

Then apply login local and transport input ssh to EVERY range you find, not just 0 4. Any range you skip keeps whatever transport-input it already had — often transport input telnet or transport input all — so Telnet (or the platform default) can still succeed on those lines even after 0 4 is locked down. transport input ssh is what actually retires Telnet, but only on the lines you apply it to.

R1(config)# do show run | section ^line vty
R1(config)# username admin privilege 15 secret StrongPass123!
R1(config)# line vty 0 4
R1(config-line)# login local
R1(config-line)# transport input ssh
R1(config-line)# exit
R1(config)# line vty 5 15
R1(config-line)# login local
R1(config-line)# transport input ssh
R1(config-line)# exit

Step 3 — Force SSH version 2, save, and verify end to end

SSHv1 has known weaknesses, so explicitly force version 2 rather than leaving the router to negotiate whatever the client offers.

Save the config immediately after — the RSA key is not written to NVRAM automatically, and a reload without a save means regenerating it (and re-establishing the SSH host key trust on every client that already connected).

show ip ssh confirms the server is up and running version 2, and show ssh lists any active sessions — but both only prove the server side is listening. To confirm a client can actually authenticate, log in from a separate device: ssh -l admin <R1's-mgmt-ip>, using the account from Step 2. If that succeeds, you've verified the whole chain — key, vty transport, and local auth — not just that R1 says it's ready.

R1(config)# ip ssh version 2
R1(config)# end
R1# copy running-config startup-config
R1# show ip ssh
R1# show ssh
! From a separate PC or device, confirm end-to-end login:
! ssh -l admin 10.0.0.1

Common problems (and the fix)

crypto key generate rsa refuses with "% Please define a domain-name first." — you forgot ip domain-name, and that's the only hard gate. A default hostname of "Router" will NOT block key generation by itself; set a real hostname anyway since it shows up in the key's FQDN, but don't waste time chasing the hostname if the key still won't generate — check ip domain-name first.

You can no longer reach the device over SSH after saving — check for login local with no matching username configured; without a local account there's nothing to authenticate against and the session is rejected.

Telnet still works on some sessions after you thought you disabled it — you probably only fixed vty 0 4. Run show run | section ^line vty to see every range on the box (Catalyst switches and many IOS-XE platforms default to vty 0 15), and confirm transport input ssh — not telnet or all — is applied to each one, not just the first five lines.

The key regenerates (and every client throws a host-key-changed warning) after a reload — you configured SSH but never ran copy running-config startup-config, so the RSA key was never saved.

ssh -l admin <ip> hangs or is refused outright from the client — that's usually reachability, not SSH config: confirm you can reach the management IP and that no access-class or ACL on the vty lines is blocking the client's source address.

Frequently asked questions

SSH version 1 vs version 2 — why force v2, and does anything break?

SSHv1 has known cryptographic weaknesses and should never be enabled; version 2 is the only version you should allow, which is why 'ip ssh version 2' is a required hardening step. Left unset, IOS may fall back to 1.99 compatibility and accept both versions, leaving the weaker protocol reachable. Forcing v2 only blocks ancient clients, and every modern SSH client speaks v2, so nothing you'd actually use stops working.

What RSA key size should I use, and why did SSHv2 reject my key?

The modulus you pick at 'crypto key generate rsa' matters: SSH version 2 requires a key of at least 768 bits, and 2048 is the common real-world minimum. If you generated a smaller key before turning on SSHv2, the session negotiation fails, so delete and regenerate with 'crypto key generate rsa modulus 2048'. Larger keys are stronger but take longer to build and add slight per-session CPU cost.

Why isn't a vty line password enough for SSH like it is for Telnet?

SSH on IOS authenticates by username and password, so a bare shared line password (the Telnet style) will not work — the vty lines need 'login local' with a local user account or AAA. That is why the config creates a local user and points the lines at local login. Without a username-based method the router rejects SSH logins even when the key and version 2 are both correct.

How do I restrict which source IPs are allowed to SSH into the device?

Build a standard access list permitting only your management subnet or jump host, then apply it to the vty lines with 'access-class <acl> in'. A standard ACL filters on source address, which is exactly what vty access control needs. This is separate from forcing SSH-only transport and adds a second layer, so a valid credential still can't be used from an unapproved source.

Should I practice this in Packet Tracer or on real IOS?

Packet Tracer is a simulator and only some features behave like real IOS, so for SSH it's best to verify on actual IOS images, which is what Cisco Modeling Labs (CML) runs. CML ships as a virtual appliance you run in a hypervisor such as VMware Workstation (now free for personal use) rather than a native desktop install, and VirtualBox isn't a supported CML host. Packet Tracer can still grade you inside pre-authored .pka activities, but real IOS gives you closer-to-exam behavior.

Practice this on graded Cisco labs

Reading is step one — build Device Security & SSH on real Cisco IOS and grade your own config, or try a free sample lab first.