CCIE Security Lab, Part 2 – MPLS Core

Today the fun starts, as I will start by building up the MPLS core, which will serve as the connecting element between the three/four sites in the topology.

R1 will be the provider router, R2, R3, and Prov1 will be the PE routers. So I’ll quickly go through the basic IP connectivity, IGP (OSPF), MPLS and BGP configuration, before looking at the best way to secure the individual components.

If you are not familiar with MPLS, then please go and buy my book; MPLS for Cisco Networks. It is a good place to start learning MPLS and covers, in much more depth, the stuff I will whizz through.

Just to re-iterate previous post, I won’t be dwelling on MPLS security. It’s not explicitly stated on the blueprint, and it does not feature on the INE workbook either. Which means its a pretty good bet that it won’t feature in the exam.

Let’s start with the basic IP configuration:

R1(config)#int gi 0/0
R1(config-if)#desc Connection to R2
R1(config-if)#ip add 134.20.1.1 255.255.255.252
R1(config-if)#no shu
R1(config-if)#do ping 134.20.1.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 134.20.1.2
.!!!!
Success rate is 80 percent (4/5)
R1(config-if)#int gi 0/1
R1(config-if)#desc Link to R3
R1(config-if)#ip add 134.20.1.5 255.255.255.252
R1(config-if)#no shu
R1(config-if)#int gi 0/2
R1(config-if)#desc Link to Prov1
R1(config-if)#ip add 134.20.1.9 255.255.255.252
R1(config-if)#no shu
R1(config-if)#int lo0
R1(config-if)#ip add 1.1.1.1 255.255.255.255
R1(config-if)#int lo8
R1(config-if)#ip add 8.8.8.8 255.255.255.255
R1(config-if)#do ping 134.20.1.6
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 134.20.1.6
.!!!!
Success rate is 80 percent (4/5)
R1(config-if)#do ping 134.20.1.10
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 134.20.1.10
.!!!!
Success rate is 80 percent (4/5)
R1(config-if)#

R2(config)#int gi 0/0
R2(config-if)#desc Connection to R1
R2(config-if)#ip add 134.20.1.2 255.255.255.252
R2(config-if)#no shut
R2(config-if)#
R2(config-if)#int lo0
R2(config-if)#ip add 2.2.2.2 255.255.255.255
R2(config-if)#

R4(config)#int gi 0/1
R4(config-if)#desc Link to R1
R4(config-if)#ip add 134.20.1.6 255.255.255.252
R4(config-if)#no shu
R4(config-if)#
R4(config-if)#int lo0
R4(config-if)#ip add 4.4.4.4 255.255.255.255
R4(config-if)#

Prov1(config)#int gi 0/0
Prov1(config-if)#desc Link to R1
Prov1(config-if)#ip add 134.20.1.10 255.255.255.252
Prov1(config-if)#no shu
Prov1(config-if)#
Prov1(config-if)#int lo0
Prov1(config-if)#ip add 10.10.10.10 255.255.255.255
Prov1(config-if)#

I am going to use OSPF as my IGP, so let’s configure that…

R1(config-if)#exi
R1(config)#router ospf 1
R1(config-router)#router-id 1.1.1.1
R1(config-router)#network 0.0.0.0 0.0.0.0 area 0
R1(config-router)#

R2(config-if)#router ospf 1
R2(config-router)#router-id 2.2.2.2
R2(config-router)#network 134.20.1.0 0.0.0.3 area 0
R2(config-router)#net 2.2.2.2 0.0.0.0 area 0
R2(config-router)#

R4(config-if)#router ospf 1
R4(config-router)#router-id 4.4.4.4
R4(config-router)#net 134.20.1.4 0.0.0.3 ar 0
R4(config-router)#net 4.4.4.4 0.0.0.0 a 0
R4(config-router)#

Prov1(config-if)#router ospf 1
Prov1(config-router)#router-id 10.10.10.10
Prov1(config-router)#net 134.20.1.10 0.0.0.0 a 0
Prov1(config-router)#net 10.10.10.10 0.0.0.0 a 0
Prov1(config-router)#

R1(config-router)#do sh ip ospf neigh

Neighbor ID     Pri  State     Dead Time Address     Interface
10.10.10.10       1  FULL/BDR  00:00:34  134.20.1.10 GigabitEthernet0/2
4.4.4.4           1  FULL/BDR  00:00:33  134.20.1.6  GigabitEthernet0/1
2.2.2.2           1  FULL/DR   00:00:37  134.20.1.2  GigabitEthernet0/0
R1(config-router)#

Because we are running OSPF, we can use the command “mpls ldp autoconfig”:

R1(config-router)#mpls ldp autoconfig 
R1(config-router)#

R2(config-router)#mpls ldp autoconfig
R2(config-router)#

R4(config-router)#mpls ldp autoconfig
R4(config-router)#

Prov1(config-router)#mpls ldp autoconfig
Prov1(config-router)#

R1(config-router)#
%LDP-5-NBRCHG: LDP Neighbor 2.2.2.2:0 (1) is UP
%LDP-5-NBRCHG: LDP Neighbor 4.4.4.4:0 (2) is UP
%LDP-5-NBRCHG: LDP Neighbor 10.10.10.10:0 (3) is UP
R1(config-router)#

Following a couple of best practices, we really should hard-code our label switching method, and our LDP router-id. At the moment the R1 will be using 8.8.8.8 as it’s router ID, whereas I want to use 1.1.1.1:

R1(config-router)#exi  
R1(config)#mpls label protocol ldp 
R1(config)#mpls ldp router-id lo0 force 
R1(config)#

R2(config-router)#mpls label protocol ldp
R2(config)#mpls ldp router-id lo0 force
R2(config)#

R4(config)#mpls label protocol ldp
R4(config)#mpls ldp router-id lo0 force
R4(config)#

Prov1(config-router)#mpls label protocol ldp
Prov1(config)#mpls ldp router-id lo0 force
Prov1(config)#

Now we can configure MP-BGP:

R2(config)#router bgp 1
R2(config-router)#bgp router-id 2.2.2.2
R2(config-router)#no bgp def ipv4-unicast 
R2(config-router)#neigh 4.4.4.4 remote 1
R2(config-router)#neigh 10.10.10.10 remote 1
R2(config-router)#neigh 4.4.4.4 update lo0
R2(config-router)#neigh 10.10.10.10 update lo0
R2(config-router)#address-family vpnv4 
R2(config-router-af)#neigh 4.4.4.4 activate
R2(config-router-af)#neigh 10.10.10.10 activ
R2(config-router-af)#neigh 4.4.4.4 send-community extended 
R2(config-router-af)#neigh 10.10.10.10 send-community extended 
R2(config-router-af)#

R4(config)#router bgp 1
R4(config-router)#bgp router-id 4.4.4.4
R4(config-router)#no bgp def ipv4
R4(config-router)#neigh 2.2.2.2 remote 1    
R4(config-router)#neigh 10.10.10.10 remote 1
R4(config-router)#neigh 2.2.2.2 update lo0
R4(config-router)#neigh 10.10.10.10 update lo0
R4(config-router)#add vpnv4
R4(config-router-af)#neigh 2.2.2.2 activ
R4(config-router-af)#neigh 10.10.10.10 activ
R4(config-router-af)#neigh 2.2.2.2 send-community extended 
R4(config-router-af)#neigh 10.10.10.10 send-community extended 
R4(config-router-af)#

Prov1(config)#router bgp 1
Prov1(config-router)#bgp router-id 10.10.10.10
Prov1(config-router)#no bgp def ipv4 
Prov1(config-router)#neigh 2.2.2.2 remote 1
Prov1(config-router)#neigh 4.4.4.4 remote 1
Prov1(config-router)#neigh 2.2.2.2 update lo0
Prov1(config-router)#neigh 4.4.4.4 update lo0
Prov1(config-router)#add vpnv4
Prov1(config-router-af)#neigh 2.2.2.2 activ
Prov1(config-router-af)#neigh 4.4.4.4 activ
Prov1(config-router-af)#neigh 2.2.2.2 send-comm ext
Prov1(config-router-af)#neigh 4.4.4.4 send-comm ext
Prov1(config-router-af)#

R2#sh bgp vpnv4 uni all sum
BGP router identifier 2.2.2.2, local AS number 1
BGP table version is 1, main routing table version 1

Neighbor      V  AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
4.4.4.4       4  1       4       4        1    0    0 00:02:25        0
10.10.10.10   4  1      13      14        1    0    0 00:10:30        0
R2#

Prov1#sh bgp vpnv4 uni all sum
BGP router identifier 10.10.10.10, local AS number 1
BGP table version is 1, main routing table version 1

Neighbor      V  AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
2.2.2.2       4  1      14      13        1    0    0 00:10:52        0
4.4.4.4       4  1       7       6        1    0    0 00:04:15        0
Prov1#

So far so good, now we need to set up our VRF. I will only be using one (at least for the moment):

R2(config)#ip vrf 802101
R2(config-vrf)#rd 1:1
R2(config-vrf)#route-target bo 1:1
R2(config-vrf)#

R4(config-router-af)#ip vrf 802101
R4(config-vrf)# rd 1:1
R4(config-vrf)# route-target export 1:1
R4(config-vrf)# route-target import 1:1
R4(config-vrf)#

Prov1(config)#ip vrf 802101
Prov1(config-vrf)# rd 1:1
Prov1(config-vrf)# route-target export 1:1
Prov1(config-vrf)# route-target import 1:1
Prov1(config-vrf)#

Next we need to assign the relevant interfaces to the VRF:

R2(config-vrf)#int gi 0/1
R2(config-if)#ip vrf for 802101
R2(config-if)#ip add 128.2.2.2 255.255.255.252
R2(config-if)#desc Link to R3
R2(config-if)#no shu
R2(config-if)#

R4(config-vrf)#int gi 0/0
R4(config-if)#ip vrf for 802101
R4(config-if)#ip add 198.240.5.1 255.255.255.252
R4(config-if)#desc Link to CUSTFW01
R4(config-if)#no shu               
R4(config-if)#

Prov1(config-vrf)#int gi 0/1
Prov1(config-if)#ip vrf for 802101          
Prov1(config-if)#ip add 10.1.1.1 255.255.255.0
Prov1(config-if)#desc Link to ProvSW
Prov1(config-if)#no shu
Prov1(config-if)#

And finally we add the VRF to BGP:

R2(config-if)#router bgp 1
R2(config-router)#add ipv4 vrf 802101
R2(config-router-af)#

R4(config-if)#router bgp 1
R4(config-router)#add ipv4 vrf 802101
R4(config-router-af)#

Prov1(config)#router bgp 1
Prov1(config-router)#add ipv4 vrf 802101
Prov1(config-router-af)#

When we look at adding the sites together, we’ll need to do redistribution between R3 and R2, CUSTFW01 and R4, and our HQ ASAs and the provider (Prov1), but it is not the intention to go that far just yet. Instead we’ll now look at how we can secure the MPLS environment.

So, what can we, or should we secure? Our biggest danger, as it currently stands, is that someone could plug a router into the network, and it would not take them long to form an adjacency with us on OSPF or LDP. To gain access to BGP then they would have to perform some kind of man-in-the-middle attack and place themselves on the connecting wire – i.e. between R1 and R2, and then they would have to impersonate R2. This could easily be done through packet sniffing initially.

The simplest way in which we can protect ourselves is to implement some passwords. We will do this first on R2, below, and we can see that adding a password on it’s own is good, but clearly not foolproof – if you gain access to the router, or to the configuration backups, then you can see that the password is stored in cleartext, unless you enable “service password-encryption”:

R2(config)#router bgp 1
R2(config-router)#neigh 4.4.4.4 password 0 802101-Secrets
R2(config-router)#do sh run | i password
no service password-encryption
 neighbor 4.4.4.4 password 802101-Secrets
R2(config-router)#service password-encryption
R2(config)#do sh run | i password     
service password-encryption
 neighbor 4.4.4.4 password 7 135D47405A5C556718212B21303600
R2(config)#router bgp 1
R2(config-router)#neigh 10.10.10.10 password 0 802101-Secrets
R2(config-router)#do sh run | i password
service password-encryption
 neighbor 4.4.4.4 password 7 135D47405A5C556718212B21303600
 neighbor 10.10.10.10 password 7 154A5B5E557A7A691B363630161305
R2(config-router)#

R4(config)#router bgp 1
R4(config-router)#neigh 2.2.2.2 password 802101-Secrets
R4(config-router)#neigh 10.10.10.10 password 802101-Secrets
R4(config-router)#service password-encryption
R4(config)#

Prov1(config)#router bgp 1
Prov1(config-router)#neigh 2.2.2.2 password 802101-Secrets
Prov1(config-router)#neigh 4.4.4.4 password 802101-Secrets
Prov1(config-router)#service password-encryption
Prov1(config)#

Let’s turn our attention to our MPLS configuration. We are not done with BGP security completely, we’ll revisit it in a later post, where we’ll look at ttl-security, which can only be done through eBGP peers.

We can do a number of things to secure our MPLS configuration from prying eyes. We can set a restriction on the route target values that we will import (and export):

R2(config)#ip extcommunity-list 101 permit RT:1:1
R2(config)#route-map ImportMap perm 10
R2(config-route-map)#match extcommunity 101
R2(config-route-map)#exit
R2(config)#route-map ExportMap perm 10
R2(config-route-map)#match extcommunity 101
R2(config-route-map)#ip vrf 802101
R2(config-vrf)#export map ExportMap
R2(config-vrf)#import map ImportMap
R2(config-vrf)#

R4(config)#ip extcommunity-list 101 permit RT:1:1
R4(config)#route-map ImportMap perm 10
R4(config-route-map)#match extcommunity 101
R4(config-route-map)#route-map ExportMap perm 10
R4(config-route-map)#match extcommunity 101
R4(config-route-map)#ip vrf 802101
R4(config-vrf)#export map ExportMap
R4(config-vrf)#import map ImportMap
R4(config-vrf)#

Prov1(config)#ip extcommunity-list 101 permit RT:1:1
Prov1(config)#route-map ImportMap perm 10
Prov1(config-route-map)#match extcommunity 101
Prov1(config-route-map)#route-map ExportMap perm 10
Prov1(config-route-map)#match extcommunity 101
Prov1(config-route-map)#ip vrf 802101
Prov1(config-vrf)#export map ExportMap
Prov1(config-vrf)#import map ImportMap
Prov1(config-vrf)#

The extended community list will match our route target (1:1), and permit it. The default deny rule will catch anything else, and this is then applied inbound and outbound to our VRF.

We can also set an LDP neighbor password. This is done below, and password encryption is turned on:

R1(config)#mpls ldp neigh 4.4.4.4 password 0 80201-Secret
R1(config)#mpls ldp neigh 2.2.2.2 password 0 80201-Secret
R1(config)#mpls ldp neigh 10.10.10.10 password 0 80201-Secret
R1(config)#do sh run | i password
no service password-encryption
mpls ldp neighbor 4.4.4.4 password 80201-Secret
mpls ldp neighbor 2.2.2.2 password 80201-Secret
mpls ldp neighbor 10.10.10.10 password 80201-Secret
R1(config)#service password-encryption
R1(config)#do sh run | i password     
service password-encryption
mpls ldp neighbor 4.4.4.4 password 7 135D47405B5D49192E273A3621
mpls ldp neighbor 2.2.2.2 password 7 025E54095B574212494D1B1C11
mpls ldp neighbor 10.10.10.10 password 7 04035B545F70017D0C1A171206
R1(config)#

R2(config)#mpls ldp neighbor 1.1.1.1 password 0 802101-Secret 
R2(config)#

R4(config-vrf)#mpls ldp neighbor 1.1.1.1 password 0 802101-Secret
R4(config)#

Prov1(config-vrf)#mpls ldp neighbor 1.1.1.1 password 0 802101-Secret
Prov1(config)#

Another best practice is to “hide” our MPLS network from our CE devices (should they do a trace route), the below command will do this:

R1(config)#no mpls ip propagate-ttl 
R1(config)#

OSPF, similarly, can be password protected using MD5, this will have the immediate effect of the OSPF speakers losing their adjacencies, but I have omitted those messages:

R1(config)#router ospf 1
R1(config-router)#area 0 authentication message-digest 
R1(config-router)#int gi 0/0
R1(config-if)#ip ospf authentication message-digest 
R1(config-if)#ip ospf message-digest-key 1 md5 0 802101-Secret
R1(config-if)#int g0/1
R1(config-if)#ip ospf authentication message-digest 
R1(config-if)#ip ospf message-digest-key 1 md5 0 802101-Secret
R1(config-if)#int gi 0/2
R1(config-if)#ip ospf authentication message-digest    
R1(config-if)#ip ospf message-digest-key 1 md5 0 802101-Secret
R1(config-if)#

R2(config)#router ospf 1
R2(config-router)#area 0 authentication message-digest
R2(config-router)#int gi 0/0
R2(config-if)#ip ospf authentication message-digest
R2(config-if)#ip ospf message-digest-key 1 md5 0 802101-Secret
R2(config-if)#
%OSPF-5-ADJCHG: Process 1, Nbr 1.1.1.1 on GigabitEthernet0/0 from LOADING to FULL, Loading Done
R2(config-if)#

R4(config)#router ospf 1
R4(config-router)#area 0 authentication message-digest
R4(config-router)#int gi 0/1
R4(config-if)#ip ospf authentication message-digest
R4(config-if)#ip ospf message-digest-key 1 md5 0 802101-Secret
R4(config-if)#
%OSPF-5-ADJCHG: Process 1, Nbr 1.1.1.1 on GigabitEthernet0/1 from LOADING to FULL, Loading Done
R4(config-if)#

Prov1(config)#router ospf 1
Prov1(config-router)#area 0 authentication message-digest
Prov1(config-router)#int gi 0/0
Prov1(config-if)#ip ospf authentication message-digest
Prov1(config-if)#ip ospf message-digest-key 1 md5 0 802101-Secret
Prov1(config-if)#
%OSPF-5-ADJCHG: Process 1, Nbr 1.1.1.1 on GigabitEthernet0/0 from LOADING to FULL, Loading Done
%BGP-5-NBR_RESET: Neighbor 4.4.4.4 active reset (BGP Notification sent)
%BGP-5-ADJCHANGE: neighbor 4.4.4.4 Up 
%BGP-5-NBR_RESET: Neighbor 2.2.2.2 active reset (BGP Notification sent)
%BGP-5-ADJCHANGE: neighbor 2.2.2.2 Up 
Prov1(config-if)#

OK, all looks fine so far. But what happened after OSPF got torn down and the neighborships reestablished? LDP wouldn’t come up. The passwords were there, but the message (Invalid MD5 digest) indicates that the password is wrong.

R1(config-router)#do sh run | i password     
service password-encryption
mpls ldp neighbor 4.4.4.4 password 7 135D47405B5D49192E273A3621
mpls ldp neighbor 2.2.2.2 password 7 025E54095B574212494D1B1C11
mpls ldp neighbor 10.10.10.10 password 7 04035B545F70017D0C1A171206
R1(config-router)#do sh ip ospf neigh

Neighbor ID     Pri   State           Dead Time   Address         Interface
10.10.10.10       1   FULL/DR         00:00:39    134.20.1.10     GigabitEthernet0/2
4.4.4.4           1   FULL/DR         00:00:33    134.20.1.6      GigabitEthernet0/1
2.2.2.2           1   FULL/DR         00:00:38    134.20.1.2      GigabitEthernet0/0
R1(config-router)#exit
R1(config)#logging con
R1(config)#
%TCP-6-BADAUTH: Invalid MD5 digest from 2.2.2.2(13861) to 1.1.1.1(646) tableid - 0
%TCP-6-BADAUTH: Invalid MD5 digest from 4.4.4.4(19675) to 1.1.1.1(646) tableid - 0
%TCP-6-BADAUTH: Invalid MD5 digest from 10.10.10.10(16183) to 1.1.1.1(646) tableid - 0
%TCP-6-BADAUTH: Invalid MD5 digest from 2.2.2.2(13861) to 1.1.1.1(646) tableid - 0
%TCP-6-BADAUTH: Invalid MD5 digest from 4.4.4.4(39459) to 1.1.1.1(646) tableid - 0
%TCP-6-BADAUTH: Invalid MD5 digest from 10.10.10.10(16183) to 1.1.1.1(646) tableid - 0

So what is happening here?

Well, in one of those “can’t see the wood for the trees” moments, I fat-fingered the configuration on R1. It took me running the password through a password cracker to see the difference. Just goes to prove you should pick a password that makes spotting mistakes easy to do. Alternatively, a much better approach is to do it all on one router, and then copy the encrypted password from the “master” to the other routers – using “mpls ldp neigh <neighbor> password 7 <encrypted password>”. Below you can see that once thew password was copied from R1 onto R2, the error cleared and LDP came up.

The full compare, replace and contrast sequence is below:

%LDP-5-NBRCHG: LDP Neighbor 2.2.2.2:0 (1) is UP
%TCP-6-BADAUTH: Invalid MD5 digest from 10.10.10.10(16183) to 1.1.1.1(646) tableid - 0
%TCP-6-BADAUTH: Invalid MD5 digest from 4.4.4.4(39459) to 1.1.1.1(646) tableid - 0
%TCP-6-BADAUTH: Invalid MD5 digest from 10.10.10.10(49475) to 1.1.1.1(646) tableid - 0
%TCP-6-BADAUTH: Invalid MD5 digest from 10.10.10.10(49475) to 1.1.1.1(646) tableid - 0
%TCP-6-BADAUTH: Invalid MD5 digest from 4.4.4.4(60395) to 1.1.1.1(646) tableid - 0
%TCP-6-BADAUTH: Invalid MD5 digest from 4.4.4.4(60395) to 1.1.1.1(646) tableid - 0
%TCP-6-BADAUTH: Invalid MD5 digest from 10.10.10.10(49475) to 1.1.1.1(646) tableid - 0
R1(config)#no logging con
R1(config)#

R2(config-if)#do sh run | i password
service password-encryption
mpls ldp neighbor 1.1.1.1 password 7 09141E5B4855465F380907382E30
 neighbor 4.4.4.4 password 7 135D47405A5C556718212B21303600
 neighbor 10.10.10.10 password 7 154A5B5E557A7A691B363630161305
R2(config-if)#mpls ldp neighbor 1.1.1.1 password 7 025E54095B574212494D1B1C11
R2(config)#
%LDP-5-PWDCFG: Password configuration changed for 1.1.1.1:0
%LDP-5-NBRCHG: LDP Neighbor 1.1.1.1:0 (1) is UP

R4(config)#do sh run | i password
service password-encryption
mpls ldp neighbor 1.1.1.1 password 7 1016594B544743463F012939213C
 neighbor 2.2.2.2 password 7 0757711E1F5948482417081E013E38
 neighbor 10.10.10.10 password 7 065E5F731D1E585436121119091039
R4(config)#mpls ldp neighbor 1.1.1.1 password 7 135D47405B5D49192E273A3621
R4(config)#
%LDP-5-PWDCFG: Password configuration changed for 1.1.1.1:0
R4(config)#
%LDP-5-NBRCHG: LDP Neighbor 1.1.1.1:0 (1) is UP

Prov1(config)#do sh run | i password
service password-encryption
mpls ldp neighbor 1.1.1.1 password 7 135D47405A5C556718212B213036
 neighbor 2.2.2.2 password 7 09141E5B4855465F380907382E303B
 neighbor 4.4.4.4 password 7 1016594B544743463F012939213C20
Prov1(config)#neighbor 1.1.1.1 password 7 04035B545F70017D0C1A171206          
Prov1(config)#
%LDP-5-PWDCFG: Password configuration changed for 1.1.1.1:0
Prov1(config)#
%LDP-5-NBRCHG: LDP Neighbor 1.1.1.1:0 (1) is UP   
Prov1(config)#

R1#sh mpls ldp neigh | i Ident
    Peer LDP Ident: 2.2.2.2:0; Local LDP Ident 1.1.1.1:0
        Addresses bound to peer LDP Ident:
    Peer LDP Ident: 4.4.4.4:0; Local LDP Ident 1.1.1.1:0
        Addresses bound to peer LDP Ident:
    Peer LDP Ident: 10.10.10.10:0; Local LDP Ident 1.1.1.1:0
        Addresses bound to peer LDP Ident:
R1#

Not a bad start. I learnt something (about properly using password encryption), and I have a basis for the network to start to evolve.

I am currently reading “MPLS VPN Security”, which is pretty good, lot’s of theory and explanation, but a little light on configuration. Still, definitely a good purchase so far.

Cisco MPLS VPN Security best book

There is a good inclusion on access-lists, below is one with would permit BGP, OSPF, and LDP:

access-list 110 permit tcp host x.x.x.x host loopback eq bgp
access-list 110 permit ospf host x.x.x.x host 224.0.0.5
access-list 110 permit ospf host x.x.x.x host 224.0.0.6
access-list 110 permit ospf host x.x.x.x host local_ip
access-list 110 permit tcp address mask any eq 646
access-list 110 permit udp address mask any eq 646

I think I will save this for later on though, when all the tunnels are in place. The next post will either be about transparent firewalls, or Multiple-context firewalls.