Koenig-solutions.com



IPv6 First Hop SecurityIPv6 First Hop Security is a new topic for CCIE v5. It's important to note that at the time of this writing (June/July 2014), IPv6 FH Security is not supported in IOL, so this cannot be on the CLI-based parts of the lab yet, but it can be in diagnostics or the written.The biggest barrier to understanding IPv6 FH Security is understanding the whole first hop process to begin with. ?IPv6 changes this dramatically from the IPv4 model. First, we will examine IPv6 First Hop and determine where the security problems are.First, let's answer a simple question: How do I receive a routable IPv6 address?ICMP communicates nearly everything regarding IPv6 addressing. It's used for finding a router, building an address (typically), making sure it's unique, finding a DHCP server if necessary, locating other hosts, assigning a default route, etc.That said, IPv6 has a major chicken-or-the-egg problem. You can't run ICMP effectively without having an IPv6 address already, but how can you have an address before... you have an address?Enter link-local addressing. Link local addresses all exist within FE80::/10. Typically, and true on Cisco devices, this address is built as FE80::<address based on MAC address>. It can alternatively (as is done in modern Windows OS) be built from FE80::<random address>. The specific format of the address isn't necessary for my explanation, so I will consider that out-of-scope for this document, and it can be found in hundreds of other places.Since my blog is geared towards the CCIE, and we know we'll be using all Cisco kit, we can assume that the MAC address method is what we'll be using.So we've built our interface a "link local" address of?FE80::FA66:F2FF:FEDE:FF1. This link-local is non-routable, and can only be reached on the local segment. We must immediately run a process called DAD (Duplicate Address Detection) to ensure that we're the only person using this address. When we built the link local address, we also joined a multicast group called a "solicted node multicast", which is a multicast address that's unique for our host. DAD sends a multicast to this solicited node, and if anyone else responds (they shouldn't, if the address is unique), then we drop the address and don't use it.Assuming the address is unique, our next goal is to come up with a routable address in addition to our link local. Now that we have a link-local address, we can send out a Router Solicitation (RS) and ask for the global prefix we should be on. ?Let's say our router's IPv6 address is 2001:100::1/64. The router will fire back a Router Advertisement (RA) to our host that it's prefix is 2001:100::/64. We'll use the same process we used for link-local earlier to assign our globally routable address. Using the same example above, that address would be 2001:100::FA66:F2FF:FEDE:FF1.This process is called StateLess Address AutoConfiguration, or SLAAC. It's important to note that the router must send out an RA with a /64 length, or this process doesn't work.Perhaps more important to our examples, the RA we got the prefix from also hands out the router's IPv6 link local address, which we can optionally use as our default gateway. Just to point out again: this is not a global address. SLAAC's default routing is always done with link-local addresses.Let's look at the rather minor config for this thus far:R1 ("router"):ipv6 unicast-routinginterface Gigabit0/1? ipv6 address 2001:100::1/64R2 ("host"):ipv6 unicast-routing ! May or may not be necessary for a "host", platform-dependent.interface Gigabit0/1? ipv6 address autoconfig defaultOmitting the "default" above would prevent it from installing R1 as a default route.R2(config-if)#do sh ipv6 int br | s GigabitEthernet0/1GigabitEthernet0/1 ? ? ? ? [up/up]? ? FE80::FA66:F2FF:FEDE:FF1? ? 2001:100::FA66:F2FF:FEDE:FF1R2#sh ipv6 route ::/0Routing entry for ::/0? Known via "static", distance 2, metric 0? Route count is 1/1, share count 0? Routing paths:? ? FE80::F2F7:55FF:FE8D:96A2, GigabitEthernet0/1? ? ? Last updated 00:00:10 agoFE80::F2F7:55FF:FE8D:96A2 is R1's link local address.Cisco routers all announce themselves as viable gateways (imagine that), so if you have a "host" router - perhaps a voice gateway or whatnot - you need to tell it not to send router advertisements:R2(config)#int gig0/1R2(config-if)#ipv6 nd ra suppress allThe?suppress?keyword indicates not to send periodic RAs,?suppress all?means don't respond to RSes.An optional feature that's not on all platforms:R2(config-if)#ipv6 address autoconfig prefixThat will make the router insert routes for any other routes on the same segment. So if your neighbor had a second IPv6 address of 13::1, we'd insert a route to it as well.So that gets us a link-local address, global unicast address, and default gateway. What about DNS?Up until very recently, the only real option was to run a stateless DHCPv6 server. Stateless because in this scenario, the DHCPv6 server doesn't actually keep track of anything, it just hands out options: DNS, Call Manager info, etc.R1(config)#ipv6 dhcp pool DHCP-POOLR1(config-dhcpv6)#dns-server 4::4R1(config-dhcpv6)#dns-server 8::8R1(config-dhcpv6)#domain-name R1(config-dhcpv6)#int gig0/1R1(config-if)#ipv6 dhcp server DHCP-POOLR1(config-if)#ipv6 nd other-config-flagThe process on R2 is automatic, but on R1 we create the pool, which is reasonably obvious config, apply it to the interface, and then set the O-flag. This tells clients via RA that it should query for a DHCP server for more information. The DHCP server and the device sending the RA do not need to be the same device.Great! We've got our addresses, default gateway, and DNS. Before we move on to neighbor discovery, let's look at stateful DHCP.You've got a couple options here.Either way we need more info in our DHCP server:R1(config)#ipv6 dhcp pool DHCP-POOLR1(config-dhcpv6)#address prefix 2001:100::/64We'll still get our default gateway through RAs, but we can at least track the addresses that our hosts are using.Our first option is to just recommend to our host that it use stateful DHCP.R1(config-if)#no ipv6 nd other-config-flagR1(config-if)#ipv6 nd managed-config-flagThe M-Flag (Managed Flag) is a?suggestion?to the client that it should use the DHCP server for its host address instead of SLAAC.Since we're using a Cisco client, I need to stop here and advise that I've never been able to get the client to recognize the M-flag. It could be my IOS, I haven't investigated it that much.Since that's a bust, let's look at the other method.R2(config-if)#int gig0/1R2(config-if)#ipv6 address autoconfig default-route ! still need this for the default gatewayR2(config-if)#ipv6 address dhcpR2(config-if)#ipv6 enableI'll explain?ipv6 enable?momentarily.R2(config-if)#do sh ipv6 int br | s GigabitEthernet0/1GigabitEthernet0/1 ? ? ? ? [up/up]? ? FE80::FA66:F2FF:FEDE:FF1? ? 2001:100::2C11:9212:8690:D8FEWe got our address. (Side-note: if you have?ipv6 address dhcp?on an interface and not?ipv6 address autoconfig default-route, you?won't?get a connected route to the local subnet - you get a totally unusable /128 host address and that's it. The workaround is to disable?ipv6 unicast-routing, then you'll get the connected route)R1#sh ipv6 dhcp bindingClient: FE80::FA66:F2FF:FEDE:FF1? DUID: 00030001F866F2DE0FF0? Username : unassigned? IA NA: IA ID 0x00040001, T1 43200, T2 69120? ? Address: 2001:100::2C11:9212:8690:D8FE? ? ? ? ? ? preferred lifetime 86400, valid lifetime 172800? ? ? ? ? ? expires at Jul 02 2014 01:29 AM (172654 seconds)and R1 knows about us - it's?stateful.There's also a new option defined by RFC 6106 that completely eliminates the need for DHCPv6 in relation to DNS. Unfortunately, at the time of this writing, you need bleeding-edge IOS-XE in order to use it. In fact, the hardware lab I'm using (which will be explained later) for this doesn't even support it - I have to turn to CSR1000v:Router(config-if)#ipv6 nd ra dns server ?? X:X:X:X::X ?IPv6 addressThis passes DNS servers as an RA option. I have labbed this previously, it does appear to work from what I can see in Wireshark.I promised an explanation to?ipv6 enable. I bet you've seen this command before, followed by a statically configured address. You actually need this very infrequently. With the exception of the DHCP example I showed above,?the only time you need?ipv6 enable?is if you want a eui-64 derived link-local address without a global unicast address. If you're statically assigning an IPv6 global unicast, or you're getting one via SLAAC, you don't need this command - so cut it out! :)Of course your final option is a statically assigned address:ipv6 address 1::1/64?Link locals can also be statically assigned:ipv6 address FE80::1 link-localNow that we're past "how do we get an address", let's move on to the other big topic of "how do we find our neighbors". As you're probably already aware, IPv6 does not use ARP, instead it uses a Neighbor Solicitation (NS) and Neighbor Advertisement (NA) ICMPv6 messages. This builds the neighbor table instead of the ARP cache.NS and NA map pretty directly in functionality to ARP request and ARP reply in IPv4. I'm not going to go over them in detail, just understanding their function is sufficient for now.If R2 has just gotten it's address and wants to find R3, it would send out an NS.I've reset R2 to SLAAC and setup R3 for SLAAC as well.Addresses:R2: 2001:100::FA66:F2FF:FEDE:FF1R3:?2001:100::C67D:4FFF:FEF9:5340R2#ping 2001:100::C67D:4FFF:FEF9:5340Type escape sequence to abort.Sending 5, 100-byte ICMP Echos to 2001:100::C67D:4FFF:FEF9:5340, timeout is 2 seconds:!!!!!Success rate is 100 percent (5/5), round-trip min/avg/max = 0/3/16 msand some filtered output from?debug ipv6 icmp:ICMPv6: Sent?N-Solicit,?Src=2001:100::FA66:F2FF:FEDE:FF1, Dst=FF02::1:FFF9:5340ICMPv6: Received?N-Advert, Src=2001:100::C67D:4FFF:FEF9:5340, Dst=2001:100::FA66:F2FF:FEDE:FF1There's our NS going out, and NA coming in. It's important to note that the NS also provided R3 with R2's layer 2 address, so there's no need for the reverse process to happen.R2#sh ipv6 neighborIPv6 Address ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Age Link-layer Addr State Interface2001:100::C67D:4FFF:FEF9:5340 ? ? ? ? ? ? ? 0 c47d.4ff9.5340 ?REACH Gi0/1R3#sh ipv6 neighborIPv6 Address ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Age Link-layer Addr State Interface2001:100::FA66:F2FF:FEDE:FF1 ? ? ? ? ? ? ? ?0 f866.f2de.0ff1 ?REACH Gi0/0As you can see, R2 is aware of R3's addresses and vice-versa.Before I move on to pointing out the (somewhat obvious) security problems with this whole process, I'd like to pause and look at a few other features that I felt were of important note, but didn't fit into the explanation thus far.If you have multiple routers on a segment and want to use one or more for failover, you can specify how important their advertisements are:ipv6 nd router-preference med !default (setting this doesn't show in config)ipv6 nd router-preference low !depreffedipv6 nd router-preference high !preffedAlthough, I imagine most of us would just use HSRP.Also, if you set the RA lifetime to 0, hosts won't use it as a default gateway, but it can still be used for SLAAC:?ipv6 nd ra lifetime 0I've previously run production dual-stack IPv6 at home. It was an interesting experiment, but the overwhelming lesson I learned from it is that most content providers are using separate pipes for their IPv6 traffic, and instead of being wide open and unused liked I'd hoped, they were miserably oversubscribed, so when my Windows installation naturally preferred a IPv6 DNS resolution when both IPv6 and IPv4 were available for the same site (Here's looking at you, Youtube!) all I got was slower web traffic. I still have the v6 service on my cablemodem, but I disabled it on the router.One of the more interesting things I learned from it was the sudden realization of what the heck I do without NAT. ?Almost all home networks are setup like so on IPv4:[provider] ---- outside /30 ----> [home router] (NAT) --- private IP range ---> hostsSo if you think about this for a minute... in order to duplicate this on IPv6, which doesn't typically use NAT, you need a routable IPv6 address block on the outside of your home router, and a routable IPv6 address block on the inside of your router too. And since home ISPs don't exactly assign you two blocks of static addresses typically, you're also going to need a way to do this with DHCP or SLAAC.There's a really clever fix for this in IPv6. It's called prefix delegation. The idea is that our provider will delegate an IPv6 block to our router, which will then in turn function as the DHCP server for that block.Let's look at some sample config.ISP router:ipv6 local pool dhcpv6-pool1 2001:DB8:1200::/40 48ipv6 dhcp pool test?prefix-delegation pool dhcpv6-pool1 lifetime 1800 600?dns-server 4::4?dns-server 8::8??domain-name interface GigabitEthernet1/0?ipv6 address 12::1/64?ipv6 nd other-config-flag?ipv6 dhcp server test?Here we've told the ISP router that it should delegate /48 blocks from a larger /40 block to every DHCP server that asks.?Home router:ipv6 dhcp pool MY-DNS ?! we'll use our DNS servers?dns-server 44::44?dns-server 88::88?domain-name interface GigabitEthernet1/0?ipv6 address autoconfig default ?! we want a SLAAC address?ipv6 dhcp client pd FOO ?! we'll collect prefix delegation for the next interfaceinterface GigabitEthernet2/0?ipv6 address FOO ::/64 eui-64 ?! we'll use a /64 out of whatever we got above?ipv6 nd other-config-flag?ipv6 dhcp server MY-DNSSo, lots going on on the home router. ?First, we're going to assign our outside interface - Gig1/0 - an address via SLAAC. ?This gives us the IPv6 equivalent of my "outside /30" ?from my ASCII diagram above, albeit it on a much larger block than a IPv4 /30 :). ?Next, we're going to create a prefix delegation named FOO, and pick up a prefix from our ISP server, which we already know will be a /48 from my explanation above. We'll then go to our inside interface, Gig2/0, and assign ourselves an EUI-64 address from the prefix delegation FOO. We'll of course be sending RAs, so our internal hosts will also use SLAAC to get an address on the inside, delegated subnet.Our end device/host would have a simple config, just running SLAAC and being a stateless DHCP client. In IOS it'd just be:interface GigabitEthernet1/0?ipv6 address autoconfig defaultBack on the ISP server, you get reverse route injection in the form of static IPv6 routes pointing to whomever you delegated the prefix to. These can be redistributed into your IGP or BGP.Now let's look at what security faults all these features potentially have.There's some obvious "for like" issues that IPv4 had, that carried over to IPv6:- An attacker could pose as the stateful DHCP server, handing out either bad information for denial of service (DOS), or handing out an attacker's IPv6 address for a man-in-the-middle attack (MiM).- An attacker could pose as another host. Let's say Host1 is trying to reach Host2, and Host3 is an attacker. ?Host1 could send out a NS for Host2, and Host3 could send an NA masquerading as Host2, and Host1 may accept it as true if timed correctly. A similar process could be done from Host2 -> Host1, with Host3 - inserting itself there as well, and effectively inserting itself into the entire conversation - a MiM attack - with Host1 and Host2 none the wiser.This is where the similarities with IPv4 end. Here are some of the new security concerns:- A router advertisement could be faked, allowing a host to insert itself into a conversation, for a MiM attack.- A router could advertise, from one router to another, a prefix that shouldn't be on the local link. This connected route would be seen as closer than a theoretical downstream router that's legitimately advertising the same prefix.- An attacker could respond to every DAD request from a host, or even from the entire segment, effectively preventing hosts from using their legitimately unique IPv6 addresses, creating a DOS.- An outside host - not one on your local segment - could send traffic in rapid-fire towards a large swath of your available IPv6 space. Many IPv4 segments were either behind NAT or simply weren't all that big, but IPv6 space is really, really large - a /64 - the common LAN segment size - is 18 quintillion addresses. No last-hop router has enough memory to send NS requests for 18 quintillion addresses without running out of memory or CPU, creating a DOS by worst-case crashing the router, best-case busying the CPU out to the point where new requests aren't serviced.For me, the most confusing thing about IPv6 FH Security was that there are, as I understand it, an "old" way of doing things, and a "new" way of doing things. These overlap a lot, and there's no real discussion of this in the documentation, so figuring out when to use what was confusing.We're going to start with the "old" way, which is reasonably well-documented and well-blogged on the Internet, but not particularly thorough, and then move on to the "new" way, which seems more complete.First let's see about tackling invalid RAs.The simplest, non-automatic way to prevent invalid RAs is to write an PACL for them:ipv6 access-list IPv6?deny icmp any any routeradvertisement?permit ipv6 any anyand simply apply it to any device that shouldn't be sending RAs.There's a gotcha here, in that there is a well-known exploit by sending fragmented packets. I'm not going to go into this in detail as hundreds have blogged about this already. The workaround is to add one more deny to the PACL:deny ipv6 any any undeterminedtransportThis will make the ACL drop any IPv6 traffic where the router is unable to determine the transport type (no layer 4 information). Some say this makes for better security than the actual RA Guard feature, but debates like that are out of scope for the CCIE, so I'll leave that to others.This feature is simple and well-documented enough that I'm not going to lab it.Moving on to features we will be labbing, let's look at RA Guard. It's the automated, more granular version of what we just did with the PACL.Here's the diagram we'll work off of for the remainder of the article.As I have in many other blogs, I use GNS3 for diagramming, but I'm using physical gear for the lab. Unfortunately, IPv6 FH Security requires a bleeding-edge IOS or IOS-XE layer 2 device, so labbing it is not so easy. I was lucky enough that some friends were able to lend me a 4948-E running 15.2(1). So, I am running entirely physical gear in this lab, despite what's implied by the diagram above.This is also good and bad, because I'm using a remote lab, I can't recable on the fly. So there are a few scenarios that I didn't lab out as thoroughly as I would've done normally, but the knowledge gained here should still be more than sufficient for what may appear on the lab.R1 will represent our valid router.R2 will (usually) represent our valid host.R3 will represent our attacker.The most common way to set this up is to basically un-trust all ports that shouldn't have a router on them, and trust all the ones that should. This is accomplished with this config:ipv6 nd raguard policy MY_ROUTERS?device-role routeripv6 nd raguard policy MY_HOSTS?device-role host ?! DEFAULTipv6 snooping logging packet drop ?! NEEDED FOR LOGGINGvlan configuration 123 ! all our hosts are on vlan 123? ipv6 nd raguard attach-policy MY_HOSTSint gig1/1? ipv6 nd raguard attach-policy MY_ROUTERSI know the first thing I thought when I saw this was "what the heck is 'vlan configuration XYZ'"?I always did find it a bit strange back on the Catalyst 3560, when I learned it for CCIE v4, that QoS config would be put on an SVI even though the SVI sometimes had no IP address on it - you'd just create it for the QoS config. I guess someone at Cisco thought the same way; so now there's a specific configuration section for VLANs.So in short what we accomplished above was to configure every port in vlan 123 to assume a "host" was attached to it - a host should never be sending RAs. We then overrode that configuration on gig1/1 and told the switch to expect a router there - routers are, of course, OK to hear RAs from. Interface configuration always overrides vlan configuration, and that's true for the rest of the features we'll review in this article, so I'm going to assume that's understood from here on in.We enabled logging via?ipv6 snooping logging packet drop, which will actually turn on the majority of the logging we need for this article. There is one additional command we'll cover later.I instructed R2 and R3 not to send RAs, let's see what output we get if I attempt to enable them on R3.R3-ATTACKER(config-if)#ipv6 nd router-preference high ! Let's attempt to become the preferred routerR3-ATTACKER(config-if)#no ipv6 nd ra suppress allWS-C4948E(config)#*Jul ?3 18:15:58.734: %SISF-4-PAK_DROP: Message dropped A=FE80::C67D:4FFF:FEF9:5340 G=- V=123 I=Gi1/3 P=NDP::RA Reason=Message unauthorized on portThat's the extreme basics, and I did it in long-hand so to speak, here's the shorter way to accomplish the same thing with defaults:ipv6 nd raguard policy MY_ROUTERS?device-role routervlan configuration 123? ipv6 nd raguardint gig1/1? ipv6 nd raguard attach-policy MY_ROUTERSThis is true of just about every filtering command for IPv6 FH Security, if you use just the basic command with no policy, i.e.?ipv6 nd raguard, you get the default untrusted configuration. Here, we just said don't trust any ports' RAs except Gig1/1.Filtering can also be done per-VLAN:?interface GigabitEthernet1/1?switchport trunk allowed vlan 122,123?switchport mode trunk?ipv6 nd raguard attach-policy MY_ROUTERS vlan 123?ipv6 nd raguard vlan 122This hypothetical config would trust RAs on vlan 123, but not vlan 122.There are many other options for RA Guard:ipv6 nd raguard policy SAMPLE?device-role routerOn the 4948, I have four options here: router, host, switch, and monitor.Router and Host we already covered. Switch, I don't understand, and I can't find any documentation explaining what it does. Suffice to say that out-of-the-box it doesn't allow RAs, so if you set it with no other options, you get something similar to "Host". Monitor I found some vague definitions on, but it too has a similar outcome as switch: No RAs.?other-config-flag on?Require the other-config-flat to be set in the RA or the policy will not pass the traffic.?trusted-portPermits RAs -- I can't find any other benefits to it for RA Guard, although the other frameworks (name ND Inspection) preference ports that have trusted-port enabled if they have a conflict.?router-preference maximumSets the highest allowed preference on the port. If you want to enforce a backup router to being "low" or "medium" preference, this will drop the packet if anything higher is advertised.?hop-limit minimum?hop-limit maximum?RAs advertise what hosts should use as a TTL. You can use these two functions to control what the minimum and maximum advertised TTLs should be. Note, if you want to test this with all IOS devices, IOS can only send one of two options for this field - the default, which is 64 (this is NOT noted on the CLI anywhere, I figured it out the hard way) - or "unspecified", which basically means "use whatever you want".If you want to match a specific size, such as 90, you would set minimum and maximum to the same value.?managed-config-flag on?! Ensures the managed config flag ("please get your IPv6 address statefully from DHCPv6") is on, if not, drop the packet.?match ipv6 access-list <ACL>This will match the?link local?address that's advertising the RA. If no match on the access-list, drop the packet. Formatting is as such: permit ipv6 host FE80::F2F7:55FF:FE8D:96A1 any?match ra prefix-list <prefix list>This will match the prefix being advertised in the RA. If no match, drop the packet.Covering each of these options would make the article drag on and on, so I'm going to give one large configuration and comment on it:ipv6 access-list LL-EXAMPLE? Permit ipv6 host FE80::F2F7:55FF:FE8D:96A1 anyipv6 prefix-list PREFIX-EXAMPLE permit 2001:100::/64ipv6 nd raguard policy SAMPLE?device-role router?other-config-flag on?router-preference maximum medium?hop-limit minimum 64?hop-limit maximum 64?match ipv6 access-list LL-EXAMPLE?match ra prefix-list PREFIX-EXAMPLEint gig1/1? ipv6 nd raguard attach-policy SAMPLEThis sample would allow RAs, require the other-config-flag to be enabled, not allow a router preference higher than medium, ensure a strict TTL advertisement of 64, require the RA to be sourced from FE80::F2F7:55FF:FE8D:96A1, and only permit it to advertise 2001:100::/64.DHCP Guard is a tad simpler.We'll setup R1 as a stateful DHCP server, R2 as a DHCP client, and R3 as a malicious stateful DHCP server. I've removed all the RA Guard configuration to decrease the example complexity.R1-ROUTER(config)#ipv6 dhcp pool TEST-POOLR1-ROUTER(config-dhcpv6)#address prefix 2001:100::/64R1-ROUTER(config-dhcpv6)#dns-server 4::4R1-ROUTER(config-dhcpv6)#dns-server 8::8R1-ROUTER(config-dhcpv6)#int gig0/0R1-ROUTER(config-if)#ipv6 dhcp server TEST-POOLR3-ATTACKER(config-if)#ipv6 dhcp pool TEST-POOLR3-ATTACKER(config-dhcpv6)#address prefix 2001:101::/64R3-ATTACKER(config-dhcpv6)#dns-server 2001:101::BADR3-ATTACKER(config-dhcpv6)#int gig0/0R3-ATTACKER(config-if)#ipv6 address 2001:101::BAD/64R3-ATTACKER(config-if)#ipv6 dhcp server TEST-POOLand on our switch:ipv6 prefix-list GOOD-PREFIX seq 5 permit 2001:100::/64 le 128?ipv6 access-list LL?permit ipv6 host FE80::F2F7:55FF:FE8D:96A2 anyipv6 dhcp guard policy TRUSTED?device-role server?match server access-list LL?match reply prefix-list GOOD-PREFIXvlan configuration 123?ipv6 dhcp guard attach-policy TRUSTEDI'm going to treat this a bit differently - I'm going to trust all ports, but require them to match a specific link local source and address range.R2-HOST(config-if)#no ipv6 address autoconfigR2-HOST(config-if)#ipv6 enableR2-HOST(config-if)#ipv6 address dhcpWS-C4948E#*Jul ?3 20:39:34.985: %SISF-4-PAK_DROP: Message dropped A=FE80::C67D:4FFF:FEF9:5340 G=2001:101::68:6AF1:6FC2:5983 V=123 I=Gi1/3 P=DHCPv6::ADV Reason=The source address in the DHCPv6 ADVERTISE packet is not authorized by the DHCP Guard policyR2-HOST#sh ipv6 int br | s GigabitEthernet0/0GigabitEthernet0/0 ? ? ? ? [up/up]? ? FE80::FA66:F2FF:FEDE:FF1? ? 2001:100::F1CB:5AD:3844:CB86We get the correct address from the correct server.Now moving on to a-la-carte Neighbor Discovery Inspection.The first thing to understand about Neighbor Discovery is that it's a control plane feature only - it doesn't inspect actual data traffic, it is only looking at ND ICMP packets, and that's it - so if your users spoof their source address in an actual traffic flow, this doesn't protect against it.IPv6 ND Inspection builds a table based on NS/NA messages. It then enforces the table. The funny thing about it is, with ND/NA, basically the first one it hears becomes the trusted one.WS-C4948E(config)#vlan configuration 123WS-C4948E(config-vlan-config)#ipv6 nd inspectionI really expected DHCP Guard to also populate this table, but the a-la-carte version of ND Inspection and DHCP Guard don't appear to talk to one another, as best I was able to tell. The unified (ipv6 snooping) feature, which we will see next, does populate the neighbor bindings from DHCP, so don't be confused as to why you see DHCP as a population feature in the screen shot.So let's spoof R2 (Gig1/2)'s link local from R3:R3-ATTACKER(config-if)#ipv6 nd dad attempts 0 ?! DAD would prevent the spoofR3-ATTACKER(config-if)#ipv6 address FE80::FA66:F2FF:FEDE:FF1 link-localWS-C4948E#*Jul ?4 14:45:01.109: %SISF-4-PAK_DROP: Message dropped A=FE80::FA66:F2FF:FEDE:FF1 G=- V=123 I=Gi1/3 P=NDP::RA Reason=More trusted entry existsMore trusted entry exists. ?As you'll see above, there is a "Preflevel" numbering system, which I think of as administrative distance for neighbor bindings. The higher the number, the more trusted the entry is. Although I do find the message odd when you try to spoof -- what it really should say is "I already learned this entry from someone else, first come first serve!"The most trusted method is a static entry, which looks like:ipv6 neighbor binding vlan 123 FE80::FA66:F2FF:FEDE:FF1 interface gig1/3 c47d.4ff9.5340You can shorten this up a whole bunch, by omitting the optional VLAN and MAC address, but in my case, I'm trying to override the legitimate link-local of R2 to allow R3 to ping from its link local. Without "fully populating" the table, it still prefs the dynamically learned entry over the static one.We see the static entry with the priority of 100 - let's see if we can ping from R3 now, with our spoofed link-local:R3-ATTACKER#ping FE80::F2F7:55FF:FE8D:96A2 source FE80::FA66:F2FF:FEDE:FF1Output Interface: GigabitEthernet0/0Type escape sequence to abort.Sending 5, 100-byte ICMP Echos to FE80::F2F7:55FF:FE8D:96A2, timeout is 2 seconds:Packet sent with a source address of FE80::FA66:F2FF:FEDE:FF1%GigabitEthernet0/0!!!!!Success rate is 100 percent (5/5), round-trip min/avg/max = 0/0/0 msLet's look at the rest of the features you can optionally put in a policy.ipv6 nd inspection policy TEST-POLICY?limit address-count XThis is relatively obvious, it limits how many addresses are permitted to participate in the ND process on a port. Keep in mind you always need a minimum of 2 if you have a global unicast: you need the link-local as well.?tracking enableThis is liveliness tracking, and is pretty cool. We'll give this it's own paragraph below.?drop-unsecureThere's a cryptographic version of neighbor discovery called SeND. It requires a PKI infrastructure and certificates all the way down to the client. I'm going to call SeND "out of scope" for the CCIE v5 based on complexity. drop-unsecure is regarding SeND, so I'm skipping it.?sec-level minimum?Also used for SeND; out of scope.?device-role?{host | monitor | router}?I'm not really sure what the point is here - I don't know how host or router would differ, and Cisco hasn't documented it.?validate source-macI imagine this validates that the source MAC is appropriate for future ND communication, but it's not documented and I can't lab it without changing wires (my lab is remote, as mentioned above), so unfortunately I haven't got a good explanation on this option.If you enable tracking, as shown above, hosts get probed with an "are you still there?" if no ND packets are heard periodically.WS-C4948E(config)#ipv6 nd inspection policy ND-TESTWS-C4948E(config-nd-inspection)#tracking enableWS-C4948E(config)#vlan configuration 123WS-C4948E(config-vlan-config)#ipv6 nd inspection attach-policy ND-TESTNote the "time left" field on the far right. This is how long until a NS is sent out to the neighbor asking if it's still there. This is useful for two reasons:- Since the table is first-come first-serve, this frees up address space from being held indefinitely if it's actually not in use.- It allows for a host to move - imagine unplugging from one switchport and moving to another on the same switch - we need a way to age out the information reasonably quickly.We see we have 220 and 228 seconds on the two hosts presently in the table until they're probed.If we have an IPv6 address on the appropriate VLAN, we'll send a NS sourced from our IPv6 address.It sure confused me - if we have a pure layer 2 device - how will it send an NS?If we have a link local on the network, we'll send a NS from our IPv6 address. If we don't have an IPv6 address on the VLAN (we're just switching L2 only), we'll send an NS from the IPv6 unspecified address: that's right, the switch will send NSes even if IPv6 routing isn't enabled.If you want probes to go out more frequently than every 300 seconds, you can set it like so:ipv6 nd inspection policy TEST-POLICY?tracking enable reachable-lifetime 15 ! this will set it for 15 seconds.The most confusing feature for me was the "ipv6 snooping" syntax, which accomplishes basically everything we saw above, plus has the option (via source guard and destination guard) to filter data plane traffic as well. The confusing part about it is simple: it has lots of cross-over with all the previous functions, yet it uses a different syntax.The basic concept of ipv6 snooping is to build the neighbor database, similar to what IPv6 ND inspection did, except it uses and enforces more methods all at once.It can use:- Information from DHCP (Default)- Information from ND (Default)- Static bindingsI'm wiping out all prior FH Security functions implemented above, we're starting from scratch with basic addressing. Since this is a large topic, I'm going to give increasingly more complicated examples and explain them one at a time.At it's basics, enabling it is very simple:WS-C4948E(config)#vlan configuration 123WS-C4948E(config-vlan-config)#ipv6 snoopingUnfortunately this totally breaks the network.By default, ipv6 snooping enables its version of RA Guard and ND Inspection, so now RAs won't work any longer.WS-C4948E#*Jul ?5 11:41:42.007: %SISF-4-PAK_DROP: Message dropped A=FE80::F2F7:55FF:FE8D:96A2 G=- V=123 I=Gi1/1 P=NDP::RA Reason=Packet not authorized on portSo let's fix that.WS-C4948E(config)#ipv6 snooping policy TRUST_ROUTERWS-C4948E(config-ipv6-snooping)# security-level gleanWS-C4948E(config-ipv6-snooping)#int gig1/1WS-C4948E(config-if)#ipv6 snooping attach-policy TRUST_ROUTERR2-HOST(config-if)#ipv6 address autoconfig defaultR2-HOST(config-if)#do sh ipv6 int br | s GigabitEthernet0/0GigabitEthernet0/0 ? ? ? ? [up/up]? ? FE80::FA66:F2FF:FEDE:FF1? ? 2001:100::FA66:F2FF:FEDE:FF1Ok great! Now what the heck does "security-level glean" mean? ?Let me tell you, it was a lot of 'fun' to figure out from the near zero explanation the docs give.?glean?learns from DHCP and ND, but doesn't enforce anything. So "glean" basically means "trust this port". There is also a?trusted-port?option on the policy, and on my IOS, it appears to do absolutely nothing (how handy).For purposes of keeping this article a reasonable size, I'm going to go ahead and point out the 1:1 features in common with the a-la-carte ND inspection. By default, when you enable snooping, you're getting integrated ND Inspection. If you don't want it, you would:WS-C4948E(config)#ipv6 snooping policy MY_POLICYWS-C4948E(config-ipv6-snooping)#no protocol ndpIn this case, it would only learn entries from DHCPv6 "Guard" and static entries. Of note, you can do the same thing to disable dhcp inspection:?no protocol dhcpAssuming you left?protocol ndp?on, these features work the same way I explained them above:limit address-count? Make sure you allow at least 2 if you're using global unicast.tracking? Same as before, send NSes to keep the table up to date.So let's look at the default integrated DHCP Guard inspection yet. As mentioned above, this is?on by default?when using IPv6 Snooping.R1-ROUTER(config)#ipv6 dhcp pool DHCP-POOLR1-ROUTER(config-dhcpv6)#address prefix 2001:100::/64R1-ROUTER(config-dhcpv6)#dns-server 4::4R1-ROUTER(config-dhcpv6)#dns-server 8::8R1-ROUTER(config-dhcpv6)#int gig0/0R1-ROUTER(config-if)#ipv6 dhcp server DHCP-POOLNow I've already pre-trusted this port (with the?glean?security level mentioned above), so it's also OK to be a DHCP server.R2-HOST(config)#int gig0/0R2-HOST(config-if)#ipv6 enableR2-HOST(config-if)#no ipv6 address autoconfig defaultR2-HOST(config-if)#ipv6 address dhcpR2-HOST(config-if)#do sh ipv6 int br | s GigabitEthernet0/0GigabitEthernet0/0 ? ? ? ? [up/up]? ? FE80::FA66:F2FF:FEDE:FF1? ? 2001:100::B043:724:FE40:931DWe got our DHCP address.And we now learned a binding via "DH" - DHCP.There are three security models that can be applied to entire VLANs or per-port/per-vlan:WS-C4948E(config-ipv6-snooping)#security-level ?? glean ? ?Glean addresses? guard ? ?inspect and drop un-authorized messages (default)? inspect ?glean and Validate messageWe've discussed glean - it basically trusts the port but still keeps track of the bindings. Guard, as indicated above, is the default, and it's what we're getting when nothing is specified. Guard is, in effect, the same as enabling the a-la-cart DHCP Guard, RA Guard, and ND Inspection: It learns bindings and denies untrusted (non-glean) ports from sending RAs, DHCP offers, invalid DAD, invalid NAs, etc. It's an all-in-one control-plane security enforcer!?Best I can tell, "inspect" enforces ND only (similar to the a-la-carte ipv6 nd inspection feature) but doesn't protect against malicious RAs or DHCP servers. I validated this by enabling it on all interfaces, sending RAs and DHCP off R1, and then attempting to spoof R2's address on R3's interface. Everything was permitted except the R3 spoof of R2, which produced:*Jul ?5 13:38:48.559: %SISF-4-PAK_DROP: Message dropped A=2001:100::9193:876E:7E83:F33C G=- V=123 I=Gi1/3 P=NDP::NA Reason=More trusted entry existson the 4948.That wraps up the control-plane filters, data-plane filters are next, including Source Guard, Destination Guard, and Prefix Guard. IPv6 snooping builds the database that these features use, so it is a prerequisite for everything we'll see from here on.Source guard is very simple. If the data-plane traffic - any traffic?other than?IPv6 ND/RA and DHCP - doesn't match the source address present in the prebuilt binding table, drop the traffic.WS-C4948E(config)#vlan configuration 123WS-C4948E(config-vlan-config)#ipv6 source-guardThe main additional configuration for this is to validate prefixes, which is what's known as Prefix Guard.Far earlier in the article we discussed prefix delegations via DHCP. This is the technology that allows you to sub-lease a prefix from one DHCP server to a downstream DHCP server. I couldn't get this feature to work with my lab, and I believe it's a platform limitation, but unfortunately when you're borrowing high-end switches to lab bleeding-edge functions, beggars can't be choosers.Here is how I think it's supposed to work:! DHCP SERVERipv6 local pool dhcpv6-pool1 2001:100:123::/40 48ipv6 dhcp pool test?prefix-delegation pool dhcpv6-pool1 lifetime 1800 600?dns-server 4::4?dns-server 8::8??domain-name interface GigabitEthernet0/0?ipv6 address 2001:100:123::1/48?ipv6 nd other-config-flag?ipv6 dhcp server test?! CLIENTinterface GigabitEthernet0/0?ipv6 address autoconfig default?ipv6 nd ra suppress all?ipv6 dhcp client pd PREFIX-DELEGATIONinterface Loopback0 ?! I needed something to pretend to be a downstream client?ipv6 address PREFIX-DELEGATION ::/64 eui-64 ??ipv6 enable! SWITCHipv6 snooping policy SNOOPING-POLICY?security-level glean?prefix-glean ?! this learns prefix delegations - this did work for me, it was the filtering that didn't work.ipv6 source-guard policy PREFIX-GUARD?no validate address?validate prefixvlan configuration 123?ipv6 snooping attach-policy SNOOPING-POLICY?ipv6 source-guard attach-policy PREFIX-GUARDAnd after applying all this, my switch shot back at me:WS-C4948E(config)#%warning% This filter is not supported. Vlan - 123, ?mac - any, prefix_length - 64%warning% This filter is not supported. Vlan - 123, ?mac - any, prefix_length - 64%warning% This filter is not supported. Vlan - 123, ?mac - any, prefix_length - 128 ?I tinkered with it for a while, changing the address to another one on Lo0 that I shouldn't be able to use, to no avail. Traffic kept passing. ?So I'm assuming this just can't be accomplished on this hardware or I'm hitting a bug.I did have one other curiosity with source guard (just vanilla source guard, not prefix guard); while it did filter traffic appropriately, sometimes when I disabled the feature, traffic still wouldn't forward. Clearing the database solved the problem:?clear ipv6 neigh bindOur last major topic is Destination Guard, which is pretty darn cool. The recommended prefix size for a LAN segment in IPv6 is a /64, which is 18 quintillion addresses. To put that into perspective, that's 18,446,744,073,709,551,616 addresses in one segment.What would happen if you tried to "arp" (IPv6 NS) for 18,446,744,073,709,551,616 addresses back-to-back??Your router would melt. You'd run out of RAM and CPU very quickly. At a best case this would result in a simple DOS where legitimate NSes couldn't get through for a while, at a worst case the OS might crash. Most of the attacks we've looked at so far require the attacker to have access to the "inside" of your network, what's worse about this attack is that it can be accomplished from the outside of your network - potentially from the Internet.Destination Guard addresses this. Destination Guard is a "last hop" security feature: the attack can be launched from anywhere on a routed network, and the last hop router is the only one that is heavily impacted, because interim routers don't have to NS for the final destination, they just CEF-switch the packet.We're also assuming, for our purposes here, that the last-hop router is a layer 3 switch supporting destination guard.WS-C4948E(config)#vlan configuration 123WS-C4948E(config-vlan-config)#ipv6 destination-guardThere's only one very simple setting you can add if you use a policy:WS-C4948E(config)#ipv6 destination-guard policy FOOWS-C4948E(config-destguard)#enforcement ?? always ? ?Enforced under all conditions (default)? stressed ?Enforced when system is under stressstressed?isn't defined anywhere, but I'm assuming it means only kick this feature in during high CPU load, or perhaps under a great deal of NS.I'll be changing our lab up a bit in order to test this, R1 will be out of the picture, R2 will have a static assignment and will be our "trusted" host, and R3 will be our attacker on the Internet.R2-HOST(config-if)#int gig0/0R2-HOST(config-if)#ipv6 address 2001:600D::2/64 ! my best representation of "GOOD" in hex :)R2-HOST(config)#ipv6 route ::/0 2001:600D::1 ?! the switch's addressR3-ATTACKER(config-if)#int gig0/0R3-ATTACKER(config-if)#ipv6 address 2001:BAD::2/64R3-ATTACKER(config)#ipv6 route ::/0 2001:BAD::1WS-C4948E(config)#ipv6 unicast-routingWS-C4948E(config)#vlan 200WS-C4948E(config-vlan)#exitWS-C4948E(config)#vlan 300WS-C4948E(config-vlan)#exitWS-C4948E(config)#int vlan200WS-C4948E(config-if)#ipv6 address 2001:600D::1/64WS-C4948E(config-if)#no shutWS-C4948E(config-if)#int vlan 300WS-C4948E(config-if)#ipv6 address 2001:BAD::1/64WS-C4948E(config-if)#no shutWS-C4948E(config)#int gig1/2WS-C4948E(config-if)#switchport access vlan 200WS-C4948E(config)#int gig1/3WS-C4948E(config-if)#switchport access vlan 300WS-C4948E(config-if)#vlan configuration 200,300WS-C4948E(config-vlan-config)# ipv6 snoopingWS-C4948E(config-vlan-config)# ipv6 destination-guardNow let's say the "BAD" neighbor, a host on the Internet, tries to hammer away at tens of thousands of addresses on the "GOOD" (600D) network in order to make the router (our 4948) collapse under the NS load.In order to see this security feature take effect, we need to enable one more logging feature:WS-C4948E(config)#ipv6 snooping logging resolution-vetoWhat the heck is resolution veto? If the switch decides it's getting asked to resolve for bogus addresses, it will "veto" the neighbor solicitation.Before I try the attack, I went ahead and verified connectivity from R2 to R3.?R2-HOST(config)#do ping 2001:BAD::2Type escape sequence to abort.Sending 5, 100-byte ICMP Echos to 2001:BAD::2, timeout is 2 seconds:.....That should've worked. What did the 4948 have to say?WS-C4948E(config)#*Jul ?5 16:13:12.774: %SISF-4-RESOLUTION_VETO: Resolution vetoed NS for D=2001:BAD::2 on I=Vl300 reason=Destination not active on linkThis is an important point on this feature: it doesn't know what hosts are valid until it hears from them. So due to my order-of-operations in this scenario, the switch hadn't actually heard from R3 at all yet, and the NS is denied. ?Making R3 speak solves the problem, which would've worked itself out eventually anyway:R3-ATTACKER(config)#do ping 2001:600D::2Type escape sequence to abort.Sending 5, 100-byte ICMP Echos to 2001:600D::2, timeout is 2 seconds:!!!!!Success rate is 100 percent (5/5), round-trip min/avg/max = 0/1/8 msNow let's try our theoretical attack.R3-ATTACKER#ping 2001:600D::100 repeat 1 timeout 0Type escape sequence to abort.Sending 1, 100-byte ICMP Echos to 2001:600D::100, timeout is 0 seconds:.Success rate is 0 percent (0/1)R3-ATTACKER#ping 2001:600D::101 repeat 1 timeout 0Type escape sequence to abort.Sending 1, 100-byte ICMP Echos to 2001:600D::101, timeout is 0 seconds:.Success rate is 0 percent (0/1)R3-ATTACKER#ping 2001:600D::102 repeat 1 timeout 0Type escape sequence to abort.Sending 1, 100-byte ICMP Echos to 2001:600D::102, timeout is 0 seconds:.Success rate is 0 percent (0/1)R3-ATTACKER#ping 2001:600D::103 repeat 1 timeout 0Type escape sequence to abort.Sending 1, 100-byte ICMP Echos to 2001:600D::103, timeout is 0 seconds:.Success rate is 0 percent (0/1)(pretend there are 65,431 hypothetical pings here)R3-ATTACKER#ping 2001:600D::FFFF repeat 1 timeout 0Type escape sequence to abort.Sending 1, 100-byte ICMP Echos to 2001:600D::FFFF, timeout is 0 seconds:.Success rate is 0 percent (0/1)We expected that outcome as these aren't valid hosts, but what happened on the switch?*Jul ?5 16:18:26.226: %SISF-4-RESOLUTION_VETO: Resolution vetoed NS for D=2001:600D::100 on I=Vl200 reason=Destination not active on link*Jul ?5 16:18:34.146: %SISF-4-RESOLUTION_VETO: Resolution vetoed NS for D=2001:600D::101 on I=Vl200 reason=Destination not active on link*Jul ?5 16:18:43.338: %SISF-4-RESOLUTION_VETO: Resolution vetoed NS for D=2001:600D::102 on I=Vl200 reason=Destination not active on link*Jul ?5 16:18:50.418: %SISF-4-RESOLUTION_VETO: Resolution vetoed NS for D=2001:600D::103 on I=Vl200 reason=Destination not active on link.....*Jul ?5 16:18:58.958: %SISF-4-RESOLUTION_VETO: Resolution vetoed NS for D=2001:600D::FFFF on I=Vl200 reason=Destination not active on linkAnd that about sums up destination guard.A few random notes for the wrap-up.Some useful show commands:WS-C4948E#sh ipv6 snooping policiesTarget ? ? ? ? ? ? ? Type ?Policy ? ? ? ? ? ? ? Feature ? ? ? ?Target rangeGi1/2 ? ? ? ? ? ? ? ?PORT ?policy1 ? ? ? ? ? ? ?NDP inspection vlan allThis will show you what policies are applied where.WS-C4948E#sh ipv6 snooping featuresFeature name ? priority stateNDP inspection ? ?160 ? READYSnooping ? ? ? ? ?128 ? READYThis shows which features are enabled.And where is all this in the documentation?Well, at the time of this writing, there's a link to all this directly under the IOS 15.2E, which is what I labbed on! and ... it's a broken link! Uuuuurgh!Best I could come up with that I could drill-down to:Switches ->?3850 ->?Catalyst 3850-12S-E Switch ->?Configuration Guides ->?IPv6 Configuration Library, Cisco IOS XE Release 3SE (Catalyst 3850 Switches) ->?IPv6 First-Hop Security Configuration Guide, Cisco IOS XE Release 3SE (Catalyst 3850 Series)That covers just about everything except Source Guard and Prefix Guard, but let's face it, those two features are pretty easy to understand if you have the rest of it down. ................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download