Securing the device itself: lines and password types, AAA with TACACS+ vs RADIUS, IPv4/IPv6 ACLs (standard, extended, named, time-based), uRPF strict and loose, Control Plane Policing (CoPP), and IPv6 First-Hop Security — RA Guard, DHCPv6 Guard, ND Inspection, Source Guard, binding table.
3.1 Securing device access — lines, passwords, SSH
The first hardening step is the management plane: who can log in and how. ENARSI assumes you know what to disable and how to enforce SSH-only access with strong password storage.
Lines & what they protect
| Line | Used for | Hardening tip |
|---|---|---|
| console (con 0) | Out-of-band serial | Set login local, exec-timeout 5 0 |
| aux 0 | Modem/aux port | Disable: no exec or transport input none |
| vty 0 4 (or 0 15) | Inbound SSH/Telnet | transport input ssh, ACL access-class, AAA login |
Password storage types — pick the strongest
| Type | Algorithm | Use it? |
|---|---|---|
| 0 | Plaintext | Never — immediately auto-promoted with service password-encryption |
| 7 | Reversible Vigenère-style | No — trivial to crack |
| 5 | MD5 hash | Legacy; avoid for new accounts |
| 8 | PBKDF2 + SHA-256 | Yes |
| 9 | scrypt | Yes — strongest available on IOS |
R1(config)# service password-encryption
R1(config)# username admin privilege 15 algorithm-type scrypt secret CiscoENARSI!
R1(config)# enable algorithm-type scrypt secret EnableSecret!
! SSH only on vty
R1(config)# ip domain name lab.local
R1(config)# crypto key generate rsa modulus 2048
R1(config)# ip ssh version 2
R1(config)# line vty 0 15
R1(config-line)# transport input ssh
R1(config-line)# login local
R1(config-line)# exec-timeout 5 0
R1(config-line)# access-class MGMT_VTY in
3.2 AAA — TACACS+ vs RADIUS
What AAA stands for
- Authentication — Who are you? (verify identity)
- Authorization — What are you allowed to do? (commands, services)
- Accounting — What did you do? (audit logs)
TACACS+ vs RADIUS — the table you must memorize
| Aspect | TACACS+ | RADIUS |
|---|---|---|
| Origin | Cisco proprietary | IETF (RFC 2865) |
| Transport / port | TCP / 49 | UDP / 1812 auth, UDP / 1813 accounting |
| Encryption | Encrypts the entire payload | Encrypts only the password field |
| AAA architecture | Modular — A, A, A independent | Combines authentication + authorization in the access-accept |
| Per-command authorization | Yes — granular | Limited (vendor-specific) |
| Best fit | Device admin (network admin login) | Network access (802.1X, dot1x, VPN) |
AAA configuration template
R1(config)# username fallback privilege 15 algorithm-type scrypt secret Backup!2026
! Define server groups
R1(config)# tacacs server TAC1
R1(config-server-tacacs)# address ipv4 10.0.0.10
R1(config-server-tacacs)# key 7 SuperSecretTAC
R1(config)# aaa group server tacacs+ TAC_GROUP
R1(config-sg-tacacs+)# server name TAC1
! Method lists
R1(config)# aaa authentication login default group TAC_GROUP local
R1(config)# aaa authentication enable default group TAC_GROUP enable
R1(config)# aaa authorization exec default group TAC_GROUP local if-authenticated
R1(config)# aaa authorization commands 15 default group TAC_GROUP local
R1(config)# aaa accounting exec default start-stop group TAC_GROUP
R1(config)# aaa accounting commands 15 default start-stop group TAC_GROUP
R1# test aaa group TAC_GROUP admin Cisco123! new-code
local) as the last method. If TACACS+ is unreachable and the only method is group TAC_GROUP, you lock yourself out.3.3 IPv4 & IPv6 access control lists
ACL types — what matches what
| Type | Numbers | Matches on |
|---|---|---|
| Standard | 1-99, 1300-1999 | Source IP only |
| Extended | 100-199, 2000-2699 | Source/dest IP, protocol, ports, TCP flags, ToS, ICMP type |
| Named | ip access-list standard NAME / extended NAME |
Same as numbered, but editable per-line |
| Time-based | Reference a time-range object |
Activates only during a configured window |
| Reflexive | Created with reflect/evaluate |
Permits return traffic of sessions started inside |
| IPv6 ACL | ipv6 access-list NAME |
Always named & extended-style |
Wildcard mask — the inverse of a subnet mask
- 0 in the wildcard = MUST match; 1 = don’t care.
10.1.1.0 0.0.0.255↔ matches the entire 10.1.1.0/24.host 10.1.1.5shorthand for10.1.1.5 0.0.0.0.anyshorthand for0.0.0.0 255.255.255.255.
Reading rules
- Top-down, first match wins.
- Implicit deny any at the end of every ACL — nothing falls through to permit.
- Apply with
ip access-group NAME { in | out }oripv6 traffic-filter. - Place extended ACLs near the source (drop traffic early); standard ACLs near the destination (so they don’t accidentally block legitimate traffic upstream).
Examples
R1(config)# ip access-list extended FROM_HR
R1(config-ext-nacl)# permit tcp 10.10.0.0 0.0.255.255 host 10.20.0.5 eq 1433
R1(config-ext-nacl)# deny ip any host 10.20.0.5 log
R1(config-ext-nacl)# permit ip any any
R1(config)# interface Gi0/1
R1(config-if)# ip access-group FROM_HR in
! Time-based: SSH allowed only during business hours
R1(config)# time-range BIZ_HOURS
R1(config-time-range)# periodic weekdays 8:00 to 18:00
R1(config)# ip access-list extended VTY_IN
R1(config-ext-nacl)# permit tcp any any eq 22 time-range BIZ_HOURS
! IPv6 ACL: deny rogue prefix, permit ICMPv6 ND, permit established
R1(config)# ipv6 access-list V6_GUARD
R1(config-ipv6-acl)# deny ipv6 2001:DB8:DEAD::/48 any log
R1(config-ipv6-acl)# permit icmp any any nd-na
R1(config-ipv6-acl)# permit icmp any any nd-ns
R1(config-ipv6-acl)# permit tcp any any established
R1(config-ipv6-acl)# permit ipv6 any any
R1(config)# interface Gi0/0
R1(config-if)# ipv6 traffic-filter V6_GUARD in
permit icmp any any nd-na and nd-ns are appended automatically before the implicit deny). However, if you add an explicit deny before the end, you can break ND. Always permit ND messages explicitly when you write a tight v6 ACL.3.4 Unicast Reverse Path Forwarding (uRPF)
uRPF mitigates spoofed source addresses. When a packet arrives, the router checks: does the FIB have a route to that source? If not, drop. uRPF requires CEF.
Strict vs Loose
| Strict mode | Loose mode | |
|---|---|---|
| Test | FIB has a route AND the route’s outgoing interface = the receiving interface | FIB has a route to the source on ANY interface |
| When to use | Symmetric routing (single-homed customer edge) | Asymmetric routing (multihomed ISP edge) |
| Risk | Drops legitimate asymmetric traffic | Doesn’t catch spoofing within prefixes you actually have a route for |
| Command | ip verify unicast source reachable-via rx |
ip verify unicast source reachable-via any |
R1(config)# ip cef
R1(config)# interface Gi0/0
R1(config-if)# ip verify unicast source reachable-via rx allow-default
! Loose mode at an asymmetric ISP edge
R1(config-if)# ip verify unicast source reachable-via any
allow-default keyword permits the source to match the default route 0.0.0.0/0 — useful so that legitimate Internet sources don’t get dropped on a stub router that has only a default route.3.5 Control Plane Policing (CoPP)
The control plane is the route processor itself: BGP/OSPF/EIGRP packets, ARP, ICMP echo to the router, SSH/SNMP/NetFlow management, NTP, etc. A flood of these can melt the CPU even if the data plane is fine. CoPP applies a QoS policy to traffic destined for the route processor, classifying it and policing each class to a known rate.
The four CoPP class buckets
| Class | Examples | Typical action |
|---|---|---|
| Critical | Routing protocols (OSPF, EIGRP, BGP), HSRP/VRRP/GLBP | High rate / no drop |
| Important | SSH, SNMP, NTP, TACACS+/RADIUS | Medium rate / police |
| Normal | ICMP echo to the router, traceroute | Low rate / police hard |
| Undesirable | Telnet from outside, anything unauthorized | Drop |
CoPP configuration steps
- Define ACLs that match each class of traffic.
- Create class-maps that reference those ACLs.
- Build a policy-map binding each class to a policer.
- Apply the policy with
control-plane→service-policy input NAME.
R1(config)# ip access-list extended COPP_CRITICAL
R1(config-ext-nacl)# permit ospf any any
R1(config-ext-nacl)# permit eigrp any any
R1(config-ext-nacl)# permit tcp any any eq bgp
R1(config-ext-nacl)# permit tcp any eq bgp any
R1(config)# ip access-list extended COPP_IMPORTANT
R1(config-ext-nacl)# permit tcp any any eq 22
R1(config-ext-nacl)# permit udp any any eq snmp
R1(config-ext-nacl)# permit udp any any eq ntp
R1(config)# ip access-list extended COPP_NORMAL
R1(config-ext-nacl)# permit icmp any any echo
R1(config-ext-nacl)# permit icmp any any echo-reply
R1(config-ext-nacl)# permit icmp any any ttl-exceeded
R1(config)# ip access-list extended COPP_UNDESIRABLE
R1(config-ext-nacl)# permit tcp any any eq telnet
! Step 2 – class-maps
R1(config)# class-map match-any CRITICAL
R1(config-cmap)# match access-group name COPP_CRITICAL
R1(config)# class-map match-any IMPORTANT
R1(config-cmap)# match access-group name COPP_IMPORTANT
R1(config)# class-map match-any NORMAL
R1(config-cmap)# match access-group name COPP_NORMAL
R1(config)# class-map match-any UNDESIRABLE
R1(config-cmap)# match access-group name COPP_UNDESIRABLE
! Step 3 – policy-map
R1(config)# policy-map COPP_POLICY
R1(config-pmap)# class CRITICAL
R1(config-pmap-c)# police 8000000 conform-action transmit exceed-action transmit
R1(config-pmap)# class IMPORTANT
R1(config-pmap-c)# police 1000000 conform-action transmit exceed-action drop
R1(config-pmap)# class NORMAL
R1(config-pmap-c)# police 100000 conform-action transmit exceed-action drop
R1(config-pmap)# class UNDESIRABLE
R1(config-pmap-c)# drop
! Step 4 – apply
R1(config)# control-plane
R1(config-cp)# service-policy input COPP_POLICY
R1# show policy-map control-plane
class-default with drop at the end — if you forget to permit something legitimate (like your own SSH session) you’ll lock yourself out. Test with conform-action transmit exceed-action transmit first, monitor counters, then tighten.3.6 IPv6 First-Hop Security (FHS)
IPv6 hosts auto-configure with SLAAC using router advertisements (RAs). That’s a juicy attack surface: any rogue device on a VLAN can advertise itself as the gateway. FHS is a family of L2 features that lock down the first hop.
The five FHS pillars
| Feature | What it stops | Where applied |
|---|---|---|
| RA Guard | Rogue Router Advertisements (fake gateway, MITM) | L2 access ports facing hosts — block RAs |
| DHCPv6 Guard | Rogue DHCPv6 server replies / advertisements | L2 ports that are NOT trusted DHCPv6 servers |
| ND Inspection | Spoofed Neighbor Solicitations / Advertisements (cache poisoning) | VLAN-wide; needs IPv6 snooping policy |
| IPv6 Source Guard | Hosts spoofing an IPv6 source address that isn’t theirs | L2 access port; uses binding table |
| Binding Table | Foundation for ND Inspection & Source Guard — the trusted IPv6/MAC/port database | Switch global; populated by snooping |
Configuration template — modern (snooping policy) syntax
SW(config)# ipv6 neighbor binding vlan 10
SW(config)# ipv6 snooping policy SNOOP_HOST
SW(config-ipv6-snooping)# security-level guard
SW(config-ipv6-snooping)# device-role node
SW(config-ipv6-snooping)# protocol ndp
SW(config-ipv6-snooping)# protocol dhcp
! RA Guard policy — block RAs on host ports
SW(config)# ipv6 nd raguard policy RA_HOSTS
SW(config-nd-raguard)# device-role host
! DHCPv6 Guard policy — block server replies on host ports
SW(config)# ipv6 dhcp guard policy DHCPv6_HOSTS
SW(config-dhcp-guard)# device-role client
! Apply on a host-facing access port
SW(config)# interface Gi1/0/5
SW(config-if)# switchport mode access
SW(config-if)# switchport access vlan 10
SW(config-if)# ipv6 snooping attach-policy SNOOP_HOST
SW(config-if)# ipv6 nd raguard attach-policy RA_HOSTS
SW(config-if)# ipv6 dhcp guard attach-policy DHCPv6_HOSTS
SW(config-if)# ipv6 source-guard attach-policy
! Trusted uplink to real router
SW(config)# ipv6 nd raguard policy RA_TRUSTED
SW(config-nd-raguard)# device-role router
SW(config)# interface Gi1/0/24
SW(config-if)# ipv6 nd raguard attach-policy RA_TRUSTED
Verification
SW# show ipv6 snooping policies
SW# show ipv6 nd raguard policy RA_HOSTS
SW# show ipv6 dhcp guard policy DHCPv6_HOSTS
SW# show ipv6 source-guard policy
Hands-on labs (7)
R1(config)# ip domain name lab.local
R1(config)# crypto key generate rsa modulus 2048
R1(config)# service password-encryption
R1(config)# username admin privilege 15 algorithm-type scrypt secret CiscoENARSI!
R1(config)# enable algorithm-type scrypt secret EnableSecret!
R1(config)# ip access-list standard MGMT_VTY
R1(config-std-nacl)# permit 10.10.0.0 0.0.255.255
R1(config-std-nacl)# deny any log
R1(config)# ip ssh version 2
R1(config)# ip ssh time-out 60
R1(config)# ip ssh authentication-retries 3
R1(config)# line con 0
R1(config-line)# login local
R1(config-line)# exec-timeout 5 0
R1(config)# line aux 0
R1(config-line)# no exec
R1(config)# line vty 0 15
R1(config-line)# transport input ssh
R1(config-line)# login local
R1(config-line)# access-class MGMT_VTY in
R1(config-line)# exec-timeout 5 0
R1# show ip ssh
R1# show running-config | section vty
R1(config)# username fallback privilege 15 algorithm-type scrypt secret Backup!2026
R1(config)# tacacs server TAC1
R1(config-server-tacacs)# address ipv4 10.0.0.10
R1(config-server-tacacs)# key Cisco-TAC-Secret
R1(config-server-tacacs)# single-connection
R1(config)# aaa group server tacacs+ TAC_GROUP
R1(config-sg-tacacs+)# server name TAC1
R1(config)# aaa authentication login VTY_AUTH group TAC_GROUP local
R1(config)# aaa authentication enable default group TAC_GROUP enable
R1(config)# aaa authorization exec VTY_EXEC group TAC_GROUP local if-authenticated
R1(config)# aaa authorization commands 15 VTY_CMD group TAC_GROUP local
R1(config)# aaa accounting commands 15 default start-stop group TAC_GROUP
R1(config)# line vty 0 15
R1(config-line)# login authentication VTY_AUTH
R1(config-line)# authorization exec VTY_EXEC
R1(config-line)# authorization commands 15 VTY_CMD
R1# test aaa group TAC_GROUP admin Cisco123! new-code
R1# debug aaa authentication
R1# debug tacacs
R1(config-time-range)# periodic weekdays 8:00 to 18:00
R1(config)# ip access-list extended WAN_IN
R1(config-ext-nacl)# remark RFC1918 anti-spoof
R1(config-ext-nacl)# deny ip 10.0.0.0 0.255.255.255 any
R1(config-ext-nacl)# deny ip 172.16.0.0 0.15.255.255 any
R1(config-ext-nacl)# deny ip 192.168.0.0 0.0.255.255 any
R1(config-ext-nacl)# permit tcp any host 198.51.100.10 eq 443
R1(config-ext-nacl)# permit tcp any host 198.51.100.20 eq 22 time-range BIZ_HOURS
R1(config-ext-nacl)# deny ip any any log
R1(config)# interface GigabitEthernet0/0
R1(config-if)# ip access-group WAN_IN in
R1# show ip access-lists WAN_IN
R1# show time-range
CE(config)# ip cef
CE(config)# interface GigabitEthernet0/1
CE(config-if)# description LAN
CE(config-if)# ip verify unicast source reachable-via rx allow-default
! Multihomed PE (asymmetric) – loose mode
PE(config)# ip cef
PE(config)# interface GigabitEthernet0/0
PE(config-if)# description To ISP-A
PE(config-if)# ip verify unicast source reachable-via any
PE(config)# interface GigabitEthernet0/1
PE(config-if)# description To ISP-B
PE(config-if)# ip verify unicast source reachable-via any
PE# show cef interface gig0/0 | include RPF
PE# show ip traffic | include RPF
R1(config-ext-nacl)# permit ospf any any
R1(config-ext-nacl)# permit eigrp any any
R1(config-ext-nacl)# permit tcp any any eq bgp
R1(config-ext-nacl)# permit tcp any eq bgp any
R1(config-ext-nacl)# permit udp any any eq 1985 ! HSRPv1
R1(config)# ip access-list extended COPP_IMPORTANT
R1(config-ext-nacl)# permit tcp 10.10.0.0 0.0.255.255 any eq 22
R1(config-ext-nacl)# permit udp host 10.10.10.10 any eq snmp
R1(config-ext-nacl)# permit udp any any eq ntp
R1(config)# ip access-list extended COPP_NORMAL
R1(config-ext-nacl)# permit icmp any any echo
R1(config-ext-nacl)# permit icmp any any echo-reply
R1(config-ext-nacl)# permit icmp any any ttl-exceeded
R1(config)# ip access-list extended COPP_BAD
R1(config-ext-nacl)# permit tcp any any eq telnet
R1(config-ext-nacl)# permit tcp any any eq 6667
R1(config)# class-map match-any CRITICAL
R1(config-cmap)# match access-group name COPP_CRITICAL
R1(config)# class-map match-any IMPORTANT
R1(config-cmap)# match access-group name COPP_IMPORTANT
R1(config)# class-map match-any NORMAL
R1(config-cmap)# match access-group name COPP_NORMAL
R1(config)# class-map match-any BAD
R1(config-cmap)# match access-group name COPP_BAD
R1(config)# policy-map COPP
R1(config-pmap)# class CRITICAL
R1(config-pmap-c)# police 8000000 conform-action transmit exceed-action transmit
R1(config-pmap)# class IMPORTANT
R1(config-pmap-c)# police 1000000 conform-action transmit exceed-action drop
R1(config-pmap)# class NORMAL
R1(config-pmap-c)# police 100000 conform-action transmit exceed-action drop
R1(config-pmap)# class BAD
R1(config-pmap-c)# drop
R1(config)# control-plane
R1(config-cp)# service-policy input COPP
R1# show policy-map control-plane
R1# show policy-map control-plane input class CRITICAL
SW(config)# ipv6 neighbor binding vlan 10
SW(config)# ipv6 snooping policy SNOOP_HOST
SW(config-ipv6-snooping)# security-level guard
SW(config-ipv6-snooping)# device-role node
SW(config-ipv6-snooping)# protocol ndp
SW(config-ipv6-snooping)# protocol dhcp
SW(config)# ipv6 nd raguard policy RA_HOSTS
SW(config-nd-raguard)# device-role host
SW(config)# ipv6 nd raguard policy RA_TRUSTED
SW(config-nd-raguard)# device-role router
SW(config)# ipv6 dhcp guard policy DHCPv6_HOSTS
SW(config-dhcp-guard)# device-role client
SW(config)# interface range Gi1/0/1 – 23
SW(config-if-range)# switchport mode access
SW(config-if-range)# switchport access vlan 10
SW(config-if-range)# ipv6 snooping attach-policy SNOOP_HOST
SW(config-if-range)# ipv6 nd raguard attach-policy RA_HOSTS
SW(config-if-range)# ipv6 dhcp guard attach-policy DHCPv6_HOSTS
SW(config-if-range)# ipv6 source-guard attach-policy
SW(config)# interface Gi1/0/24
SW(config-if)# description Uplink to L3 router
SW(config-if)# ipv6 nd raguard attach-policy RA_TRUSTED
SW# show ipv6 neighbor binding
SW# show ipv6 snooping counters interface Gi1/0/5
R1(config-ipv6-acl)# remark Permit ND so SLAAC keeps working
R1(config-ipv6-acl)# permit icmp any any nd-na
R1(config-ipv6-acl)# permit icmp any any nd-ns
R1(config-ipv6-acl)# permit icmp any any router-advertisement
R1(config-ipv6-acl)# permit icmp any any router-solicitation
R1(config-ipv6-acl)# remark Block known-bad prefix
R1(config-ipv6-acl)# deny ipv6 2001:DB8:DEAD::/48 any log
R1(config-ipv6-acl)# remark Permit established TCP
R1(config-ipv6-acl)# permit tcp any any established
R1(config-ipv6-acl)# permit ipv6 any any
R1(config)# interface GigabitEthernet0/0
R1(config-if)# ipv6 traffic-filter V6_GUARD in
R1# show ipv6 access-list V6_GUARD
R1# show ipv6 interface Gi0/0 | include filter
Check Your Understanding
Twenty-five questions on this section. Each answer is explained as you go.
