Juniper MX hub and spoke VPN.

This article is about a hub-and-spoke layer 3 VPN on Juniper MX routers. The hub-and-spoke VPN will be built to resemble the following topology:


scenario

There will be three spokes. All spokes will have connectivity with each other. This connectivity will not be the same as in a regular full mesh VPN. In a regular full mesh VPN, devices on each site that is connected to the VPN can communicate directly with other sites in the VPN. The service provider that provides the customer with the VPN will route all traffic directly from one site to another;

scenario

In this case, we will introduce a Hub and Spoke topology. In our Hub and Spoke topology all traffic is forced through the hub like this;

scenario

You may choose to introduce a Hub and Spoke topology for numerous reasons. One reason could be to send all intra-site traffic through firewall for inspection.

My motivations are mainly certification and curiosity. Back to our VPN. All spokes will be able to communicate with each other through the hub. The hub site will have two separate connections to the VPN and will establish a BGP session with the PE across both these connections, like this:


scenario

The Hub CPE will use one of the BGP sessions to learn all the spoke prefixes from the PE router. This link will be used to send traffic towards the different spoke sites. The other BGP session is used to advertise a default route towards the PE router. This BGP session is used to draw all spoke-traffic towards the Hub CPE.

The way this works is not only because of the Hub CPE’s route advertisements to the PE of course. The routing-instances on the PE’s also need to be configured properly. The following picture is an attempt provide additional insight into the routing-instances on the PE routers:


scenario

At the top of the picture, you can see the hub-site. The hub-site is connected to the PE via two links. Both links are placed into a separate VPN. One VPN is the ‘routes-to-spokes’ VPN and the other VPN is the ‘route-to-hub’ VPN. Both of these VPNs serve a different purpose.

The ‘route-to-hub’ VPN is there to learn a default route from the hub site. The hub-site connected PE learns this default route and attaches the hub RT (4:4) before exporting it towards other PE routers. The hub-site connected PE will not import anything into this VPN.

The only purpose of this VPN is to send traffic towards the hub-site. Because spoke-site connected PE’s only import routes with the hub RT into the spoke VPN’s, the spoke sites are connected to a VPN with just 1 route, the default route. This default route enables all the spoke site to send traffic towards the Hub site.

The other VPN that the hub-site is connected to is the ‘routes-to-spokes’ VPN. The goal of this VPN is to enable the hub-site to send traffic towards the spokes. The hub-site connected PE will import all prefixes with the spoke-vpn RT (2:2). These routes are then advertised to the hub-site CPE via BGP. The hub-site connected PE will not export anything from this VPN to other PE routers.

Configuring a Hub and spoke VPN on Juniper MX.

The detailed topology of the example lab used is as follows:


scenario

First, the hub-site connected PE, which is really the most interesting part of the configuration. Let’s start with the vpn that will enable the hub-site to learn about all the spoke sites:


scenario

The configuration of the ‘routes-to-spokes’ instance:

set routing-instances routes-to-spokes instance-type vrf
set routing-instances routes-to-spokes interface xe-0/2/0.1110
set routing-instances routes-to-spokes route-distinguisher 44:44
set routing-instances routes-to-spokes vrf-import spokes-import
set routing-instances routes-to-spokes vrf-export nothing
set routing-instances routes-to-spokes vrf-table-label
set routing-instances routes-to-spokes protocols bgp group towards-hub neighbor 5.1.1.10 peer-as 150

set policy-statement spokes-import term spokes from protocol bgp
set policy-statement spokes-import term spokes from community spokes
set policy-statement spokes-import term spokes then accept
set policy-statement spokes-import term reject-rest then reject
set community spokes members target:2:2                    
                

This instance will export no routing information to other PE’s. The import policy will match on all spoke routes. The BGP neighbor relationship with the hub-site CPE will transfer all these spoke routes, to the hub-site will be able to send packets towards all these locations.

The other instance that the hub-site will be connected to is the following:


scenario

The configuration of the route-to-hub instance is as follows:

set routing-instances route-to-hub instance-type vrf
set routing-instances route-to-hub interface xe-0/2/0.11100
set routing-instances route-to-hub route-distinguisher 4:4
set routing-instances route-to-hub vrf-import nothing
set routing-instances route-to-hub vrf-export hub-to-spokes
set routing-instances route-to-hub vrf-table-label
set routing-instances route-to-hub protocols bgp group from-hub neighbor 1.1.1.90 peer-as 150

set policy-options policy-statement hub-to-spokes term hub from protocol bgp
set policy-options policy-statement hub-to-spokes term hub then community add hub
set policy-options policy-statement hub-to-spokes term hub then accept
set policy-options policy-statement hub-to-spokes term reject-rest then reject

set policy-options community hub members target:4:4                    
                

This instances purpose of distributing the default route towards all spokes is achieved by adding the hub RT towards the default route. The default route is learned from the hub-site via BGP. No routes are imported into this instance, so the PE will not advertise any routes towards the hub-site across this BGP peering session.

Now for the spoke side of things. Since all spokes are the same, I will only look at the configuration of spoke a:


scenario

Spoke a is configured on the Romulus PE in the following way:

set routing-instances spoke-a instance-type vrf
set routing-instances spoke-a interface xe-0/3/0.120
set routing-instances spoke-a route-distinguisher 2:2
set routing-instances spoke-a vrf-import hub-routes
set routing-instances spoke-a vrf-export spoke-to-hub
set routing-instances spoke-a vrf-table-label
set routing-instances spoke-a routing-options static route 16.0.0.1/32 next-hop 2.1.1.5
      
set policy-options policy-statement hub-routes term hub from protocol bgp
set policy-options policy-statement hub-routes term hub from community hub
set policy-options policy-statement hub-routes term hub then accept
set policy-options policy-statement hub-routes term reject-other then reject
set policy-options policy-statement spoke-to-hub term spoke then community add spoke
set policy-options policy-statement spoke-to-hub term spoke then accept
    
set policy-options community hub members target:4:4
set policy-options community spoke members target:2:2                    
                

All spokes can use the same route-distinguisher. The thing that you have to pay attention to is the import and the export policies. The import policy of this routing-instance matches the default route that is advertised by the hub-site VPN. This is achieved by allowing only routes with the hub RT (4:4) to be imported into the routing-instance. The export policy will add the spoke route-target to all routing information in this instance. In our case, this will apply to the static and the direct routes in the routing-instance.

Verifying the Hub and spoke VPN on Juniper MX.

Again a picture of the complete topology, this time including the subnets between the hub-site and the PE connected to the hub:


scenario

To verify that we succeeded in establishing a hub-and-spoke topology, we can start by sending traceroutes between the different spokes. When we send traffic from one spoke to another, we should always see the 1.1.1.88/30 subnet IP addresses followed by the 5.1.1.9/32 address. The 1.1.1.88/30 subnet is crossed because that is the link across which the default route is advertised. The 5.1.1.9/32 address shows up in the traceroutes because this is the link across which all spoke routing information is learned by the hub-cpe.

First, from Remus:

play@MX480-TEST:Remus> traceroute source 16.0.0.1 wait 1 no-resolve 16.0.0.2
traceroute to 16.0.0.2 (16.0.0.2) from 16.0.0.1, 30 hops max, 40 byte packets
 1  2.1.1.6  23.385 ms  4.926 ms  1.005 ms
 2  1.1.1.89  0.647 ms  1.241 ms  1.855 ms
 3  1.1.1.90  3.551 ms  0.558 ms  0.550 ms
 4  5.1.1.9  0.543 ms  0.541 ms  0.520 ms
 5  16.0.0.2  0.923 ms  0.889 ms  0.889 ms

play@MX480-TEST:Remus> traceroute source 16.0.0.1 wait 1 no-resolve 16.0.0.3
traceroute to 16.0.0.3 (16.0.0.3) from 16.0.0.1, 30 hops max, 40 byte packets
 1  2.1.1.6  0.533 ms  0.457 ms  0.446 ms
 2  1.1.1.89  0.544 ms  0.543 ms  0.538 ms
 3  1.1.1.90  0.542 ms  0.541 ms  0.550 ms
 4  5.1.1.9  0.544 ms  0.534 ms  0.530 ms
 5  2.0.0.65  0.640 ms  0.629 ms  0.632 ms
 6  16.0.0.3  0.905 ms  0.879 ms  0.884 ms                    
                

Then, from Septimus:

play@MX480-TEST:Septimus> traceroute source 16.0.0.3 wait 1 no-resolve 16.0.0.1
traceroute to 16.0.0.1 (16.0.0.1) from 16.0.0.3, 30 hops max, 40 byte packets
 1  2.0.0.65  0.564 ms  0.446 ms  1.514 ms
 2  1.1.1.89  0.550 ms  0.537 ms  0.697 ms
 3  1.1.1.90  0.543 ms  0.891 ms  0.534 ms
 4  5.1.1.9  0.543 ms  0.525 ms  0.539 ms
 5  2.1.1.6  0.653 ms  0.616 ms  0.665 ms
 6  16.0.0.1  0.911 ms  0.882 ms  0.893 ms

play@MX480-TEST:Septimus> traceroute source 16.0.0.3 wait 1 no-resolve 16.0.0.2
traceroute to 16.0.0.2 (16.0.0.2) from 16.0.0.3, 30 hops max, 40 byte packets
 1  2.0.0.65  0.552 ms  0.775 ms  0.437 ms
 2  1.1.1.89  0.541 ms  0.542 ms  0.534 ms
 3  1.1.1.90  0.533 ms  0.551 ms  0.537 ms
 4  5.1.1.9  0.549 ms  0.520 ms  0.532 ms
 5  16.0.0.2  0.910 ms  0.878 ms  0.878 ms                    
                

The second thing we can check is the routing information present inside the spoke vpn on the Romulus PE:

play@MX480-TEST:Romulus> show route table spoke-a.inet

spoke-a.inet.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

0.0.0.0/0          *[BGP/170] 01:01:19, localpref 100, from 1.1.1.3
                      AS path: 150 I, validation-state: unverified
                    > to 2.0.0.49 via xe-0/2/0.13, label-switched-path to_Nero
2.1.1.4/30         *[Direct/0] 18:00:24
                    > via xe-0/3/0.120
2.1.1.6/32         *[Local/0] 18:00:24
                      Local via xe-0/3/0.120
16.0.0.1/32        *[Static/5] 05:10:51
                    > to 2.1.1.5 via xe-0/3/0.120                    
                

The only routing information inside the vpn is the default route towards the hub-site and the routes related to the local spoke site. The routing information that the PE is receiving from the route-reflector looks as follows:

play@MX480-TEST:Romulus> show route receive-protocol bgp 1.1.1.3 detail table bgp.l3vpn.0

bgp.l3vpn.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden)
* 4:4:0.0.0.0/0 (1 entry, 0 announced)
     Import Accepted
     Route Distinguisher: 4:4
     VPN Label: 23
     Nexthop: 1.1.1.11
     Localpref: 100
     AS path: 150 I (Originator)
     Cluster list:  1.1.1.3
     Originator ID: 1.1.1.11
     Communities: target:4:4                    
                

The only route received and accepted into the spoke vpn is the default route.

The routing information send towards the route-reflector is the following:

play@MX480-TEST:Romulus> show route advertising-protocol bgp 1.1.1.3 detail table spoke-a.inet.0

spoke-a.inet.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
* 2.1.1.4/30 (1 entry, 1 announced)
 BGP group reflector type Internal
     Route Distinguisher: 2:2
     VPN Label: 18
     Nexthop: Self
     Flags: Nexthop Change
     Localpref: 100
     AS path: [1] I
     Communities: target:2:2

* 16.0.0.1/32 (1 entry, 1 announced)
 BGP group reflector type Internal
     Route Distinguisher: 2:2
     VPN Label: 18
     Nexthop: Self
     Flags: Nexthop Change
     Localpref: 100
     AS path: [1] I
     Communities: target:2:2                    
                

All the advertised routes have the spoke RT attached to it.

The last thing we can check is the hub-site connected PE Nero. First, the route-to-hub VPN. Inside this VPN, we learn the default route from the hub-CPE;

play@MX480-TEST:Nero> show route receive-protocol bgp 1.1.1.90 table route-to-hub.inet.0 detail

route-to-hub.inet.0: 3 destinations, 3 routes (3 active, 0 holddown, 0 hidden)
* 0.0.0.0/0 (1 entry, 1 announced)
     Accepted
     Nexthop: 1.1.1.90
     AS path: 150 I                    
                

After learning the default route from the CPE, the Nero PE will advertise this route towards the route-reflector with the hub RT attached to the route:

play@MX480-TEST:Nero> show route advertising-protocol bgp 1.1.1.3 table route-to-hub.inet.0 detail

route-to-hub.inet.0: 3 destinations, 3 routes (3 active, 0 holddown, 0 hidden)
* 0.0.0.0/0 (1 entry, 1 announced)
 BGP group reflector type Internal
     Route Distinguisher: 4:4
     VPN Label: 23
     Nexthop: Self
     Flags: Nexthop Change
     Localpref: 100
     AS path: [1] 150 I
     Communities: target:4:4                    
                

The route-to-hub instance is configured to import nothing, so the PE is not advertising any routes to the hub CPE across the peering session in this routing-instance;

play@MX480-TEST:Nero> show route advertising-protocol bgp 1.1.1.90

play@MX480-TEST:Nero>                    
                

On the Nero PE, the routes to all the spoke sites exist only in the routes-to-spokes VPN. It is across the BGP session inside this VPN that the PE is updating the hub-site CPE with all spoke routing information:

play@MX480-TEST:Nero> show route advertising-protocol bgp 5.1.1.10

routes-to-spokes.inet.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden)
  Prefix                  Nexthop              MED     Lclpref    AS path
* 2.0.0.64/30             Self                                    I
* 2.1.1.0/30              Self                                    I
* 2.1.1.4/30              Self                                    I
* 16.0.0.1/32             Self                                    I
* 16.0.0.2/32             Self                                    I
* 16.0.0.3/32             Self                                    I                    
                

The routing information that the PE places into the routing-instance is received from the route-reflector:

play@MX480-TEST:Nero> show route receive-protocol bgp 1.1.1.3 table bgp.l3vpn.0 detail

bgp.l3vpn.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden)
* 2:2:2.0.0.64/30 (1 entry, 0 announced)
     Import Accepted
     Route Distinguisher: 2:2
     VPN Label: 20
     Nexthop: 1.1.1.3
     Localpref: 100
     AS path: I
     Communities: target:2:2

* 2:2:2.1.1.0/30 (1 entry, 0 announced)
     Import Accepted
     Route Distinguisher: 2:2
     VPN Label: 299840
     Nexthop: 1.1.1.8
     Localpref: 100
     AS path: I (Originator)
     Cluster list:  1.1.1.3
     Originator ID: 1.1.1.8
     Communities: target:2:2

* 2:2:2.1.1.4/30 (1 entry, 0 announced)
     Import Accepted
     Route Distinguisher: 2:2
     VPN Label: 18
     Nexthop: 1.1.1.6
     Localpref: 100
     AS path: I (Originator)
     Cluster list:  1.1.1.3
     Originator ID: 1.1.1.6
     Communities: target:2:2

* 2:2:16.0.0.1/32 (1 entry, 0 announced)
     Import Accepted
     Route Distinguisher: 2:2
     VPN Label: 18
     Nexthop: 1.1.1.6
     Localpref: 100
     AS path: I (Originator)
     Cluster list:  1.1.1.3
     Originator ID: 1.1.1.6
     Communities: target:2:2

* 2:2:16.0.0.2/32 (1 entry, 0 announced)
     Import Accepted
     Route Distinguisher: 2:2
     VPN Label: 299840
     Nexthop: 1.1.1.8
     Localpref: 100
     AS path: I (Originator)
     Cluster list:  1.1.1.3
     Originator ID: 1.1.1.8
     Communities: target:2:2

* 2:2:16.0.0.3/32 (1 entry, 0 announced)
     Import Accepted
     Route Distinguisher: 2:2
     VPN Label: 20
     Nexthop: 1.1.1.3
     Localpref: 100
     AS path: I
     Communities: target:2:2                    
                

The complete configuration:


Remus, spoke A:
interfaces {
    xe-0/2/0 {
        unit 120 {
            vlan-tags outer 1 inner 20;
            family inet {
                mtu 1500;
                address 2.1.1.5/30;
            }
        }
    }
    lo0 {
        unit 1602 {
            family inet {
                address 16.0.0.1/32;
            }
        }
    }
}
routing-options {
    static {
        route 0.0.0.0/0 next-hop 2.1.1.6;
    }
}
Commodus, spoke B:
interfaces {
    xe-0/2/0 {
        unit 1420 {
            description Caligula-PE;
            vlan-tags outer 14 inner 20;
            family inet {
                mtu 1500;
                address 2.1.1.1/30;
            }
        }
    }
    lo0 {
        unit 1603 {
            family inet {
                address 16.0.0.2/32;
            }
        }
    }
}
routing-options {
    static {
        route 0.0.0.0/0 next-hop 2.1.1.2;
    }
}
Septimus, spoke C:
interfaces {
    xe-0/2/0 {
        unit 17 {
            description Gaius-PE;
            vlan-id 17;
            family inet {
                mtu 1500;
                address 2.0.0.66/30;
            }
        }
    }
    lo0 {
        unit 12 {
            family inet {
                address 16.0.0.3/32;
            }
        }
    }
}
routing-options {
    static {
        route 0.0.0.0/0 next-hop 2.0.0.65;
    }
}
Hadrian, Hub-site CPE:
interfaces {
    xe-0/3/0 {
        unit 1110 {
            description Nero;
            vlan-tags outer 11 inner 10;
            family inet {
                mtu 1500;
                address 5.1.1.10/30;
            }
        }
        unit 11100 {
            description Nero;
            vlan-tags outer 11 inner 100;
            family inet {
                mtu 1500;
                address 1.1.1.90/30;
            }
        }
    }
    lo0 {
        unit 10 {
            family inet {
                address 1.1.1.254/32;
            }
        }
    }
}
protocols {
    bgp {
        group from-ip-vpn {
            neighbor 1.1.1.89 {
                export advertise-default;
                peer-as 1;
            }
            neighbor 5.1.1.9 {
                peer-as 1;
            }
        }
    }
}
policy-options {
    policy-statement advertise-default {
        from protocol static;
        then accept;
    }
}
routing-options {
    static {
        route 0.0.0.0/0 reject;
    }
    autonomous-system 150;
}
Nero, PE-router:
interfaces {
    xe-0/2/0 {
        unit 12 {
            description Augustus;
            vlan-id 12;
            family inet {
                mtu 1500;
                address 2.0.0.46/30;
            }
            family iso;
            family mpls;
        }
        unit 1110 {
            description Hadrian-routes-to-spokes;
            vlan-tags outer 11 inner 10;
            family inet {
                mtu 1500;
                address 5.1.1.9/30;
            }
        }
        unit 11100 {
            description Hadrian-route-to-hub;
            vlan-tags outer 11 inner 100;
            family inet {
                mtu 1500;
                address 1.1.1.89/30;
            }
        }
    }
    lo0 {
        unit 11 {
            family inet {
                address 1.1.1.11/32;
            }
            family iso {
                address 49.0001.0100.0100.1011.00;
            }
        }
    }
}
protocols {
    rsvp {
        interface xe-0/2/0.12;
    }
    mpls {
        no-decrement-ttl;
        label-switched-path to_Caligula {
            to 1.1.1.8;
        }
        label-switched-path to_Romulus {
            to 1.1.1.6;
        }
        label-switched-path to_Gaius {
            to 1.1.1.3;
        }
        interface xe-0/2/0.12;
    }
    bgp {
        group reflector {
            type internal;
            local-address 1.1.1.11;
            hold-time 0;
            family inet {
                unicast;
            }
            family inet-vpn {
                unicast;
            }
            authentication-key "$9$nObmCt0EhyreM7-oZUHPf"; ## SECRET-DATA
            peer-as 1;
            bfd-liveness-detection {
                minimum-interval 500;
            }
            neighbor 1.1.1.3 {
                description Gaius;
            }
        }
    }
    isis {
        traffic-engineering {
            family inet {
                shortcuts;
            }
        }
        interface xe-0/2/0.12 {
            level 1 disable;
        }
        interface lo0.11;
    }
}
policy-options {
    policy-statement hub-to-spokes {
        term hub {
            from protocol bgp;
            then {
                community add hub;
                accept;
            }
        }
        term reject-rest {
            then reject;
        }
    }
    policy-statement nothing {
        then reject;
    }
    policy-statement spokes-import {
        term spokes {
            from {
                protocol bgp;
                community spokes;
            }
            then accept;
        }
        term reject-rest {
            then reject;
        }
    }
    community hub members target:4:4;
    community spokes members target:2:2;
}
routing-instances {
    route-to-hub {
        instance-type vrf;
        interface xe-0/2/0.11100;
        route-distinguisher 4:4;
        vrf-import nothing;
        vrf-export hub-to-spokes;
        vrf-table-label;
        protocols {
            bgp {
                group from-hub {
                    neighbor 1.1.1.90 {
                        peer-as 150;
                    }
                }
            }
        }
    }
    routes-to-spokes {
        instance-type vrf;
        interface xe-0/2/0.1110;
        route-distinguisher 44:44;
        vrf-import spokes-import;
        vrf-export nothing;
        vrf-table-label;
        protocols {
            bgp {
                group towards-hub {
                    neighbor 5.1.1.10 {
                        peer-as 150;
                    }
                }
            }
        }
    }
}
routing-options {
    autonomous-system 1;
}
Romulus, PE-router:
interfaces {
    xe-0/2/0 {
        unit 13 {
            description AUGUSTUS;
            vlan-id 13;
            family inet {
                mtu 1500;
                address 2.0.0.50/30;
            }
            family iso;
            family mpls;
        }
    }
    xe-0/3/0 {
        unit 120 {
            description Remus-spoke;
            vlan-tags outer 1 inner 20;
            family inet {
                mtu 1500;
                address 2.1.1.6/30;
            }
        }
    }
    lo0 {
        unit 6 {
            family inet {
                address 1.1.1.6/32;
            }
            family iso {
                address 49.0001.0100.0100.1006.00;
            }
        }
    }
}
protocols {
    rsvp {
        interface xe-0/2/0.13;
    }
    mpls {
        no-decrement-ttl;
        label-switched-path to_Caligula {
            to 1.1.1.8;
        }
        label-switched-path to_Nero {
            to 1.1.1.11;
        }
        label-switched-path to_Gaius {
            to 1.1.1.3;
        }
        interface xe-0/2/0.13;
    }
    bgp {
        group reflector {
            type internal;
            local-address 1.1.1.6;
            hold-time 0;
            family inet {
                unicast;
            }
            family inet-vpn {
                unicast;
            }
            authentication-key "$9$nObmCt0EhyreM7-oZUHPf"; ## SECRET-DATA
            peer-as 1;
            bfd-liveness-detection {
                minimum-interval 500;
            }
            neighbor 1.1.1.3 {
                description Gaius;
            }
        }
    }
    isis {
        traffic-engineering {
            family inet {
                shortcuts;
            }
        }
        interface xe-0/2/0.13 {
            level 1 disable;
        }
        interface lo0.6;
    }
}
policy-options {
    policy-statement hub-routes {
        term hub {
            from {
                protocol bgp;
                community hub;
            }
            then accept;
        }
        term reject-other {
            then reject;
        }
    }
    policy-statement spoke-to-hub {
        term spoke {
            then {
                community add spoke;
                accept;
            }
        }
    }
    community hub members target:4:4;
    community spoke members target:2:2;
}
routing-instances {
    spoke-a {
        instance-type vrf;
        interface xe-0/3/0.120;
        route-distinguisher 2:2;
        vrf-import hub-routes;
        vrf-export spoke-to-hub;
        vrf-table-label;
        routing-options {
            static {
                route 16.0.0.1/32 next-hop 2.1.1.5;
            }
        }
    }
}
routing-options {
    autonomous-system 1;
}
Caligula, PE-router:
interfaces {
    xe-0/3/0 {
        unit 15 {
            description AUGUSTUS;
            vlan-id 15;
            family inet {
                mtu 1500;
                address 2.0.0.57/30;
            }
            family iso;
            family mpls;
        }
        unit 1420 {
            description Commodus;
            vlan-tags outer 14 inner 20;
            family inet {
                mtu 1500;
                address 2.1.1.2/30;
            }
        }
    }
    lo0 {
        unit 8 {
            family inet {
                address 1.1.1.8/32;
            }
            family iso {
                address 49.0001.0100.0100.1008.00;
            }
        }
    }
}
protocols {
    rsvp {
        interface xe-0/3/0.15;
    }
    mpls {
        no-decrement-ttl;
        label-switched-path to_Romulus {
            to 1.1.1.6;
        }
        label-switched-path to_Nero {
            to 1.1.1.11;
        }
        label-switched-path to_Gaius {
            to 1.1.1.3;
        }
        interface xe-0/3/0.15;
    }
    bgp {
        group reflector {
            type internal;
            local-address 1.1.1.8;
            hold-time 0;
            family inet {
                unicast;
            }
            family inet-vpn {
                unicast;
            }
            authentication-key "$9$nObmCt0EhyreM7-oZUHPf"; ## SECRET-DATA
            peer-as 1;
            bfd-liveness-detection {
                minimum-interval 500;
            }
            neighbor 1.1.1.3 {
                description Gaius;
            }
        }
    }
    isis {
        traffic-engineering {
            family inet {
                shortcuts;
            }
        }
        interface xe-0/3/0.15 {
            level 1 disable;
        }
        interface lo0.8;
    }
}
policy-options {
    policy-statement hub-routes {
        term hub {
            from {
                protocol bgp;
                community hub;
            }
            then accept;
        }
        term reject-other {
            then reject;
        }
    }
    policy-statement spoke-to-hub {
        term spoke {
            then {
                community add spoke;
                accept;
            }
        }
    }
    community hub members target:4:4;
    community spoke members target:2:2;
}
routing-instances {
    spoke-b {
        instance-type vrf;
        interface xe-0/3/0.1420;
        route-distinguisher 2:2;
        vrf-import hub-routes;
        vrf-export spoke-to-hub;
        routing-options {
            static {
                route 16.0.0.2/32 next-hop 2.1.1.1;
            }
        }
    }
}
routing-options {
    autonomous-system 1;
}
Gaius, PE-router and route-reflector:
interfaces {
    xe-0/3/0 {
        unit 7 {
            description AUGUSTUS;
            vlan-id 7;
            family inet {
                mtu 1500;
                address 2.0.0.25/30;
            }
            family iso;
            family mpls;
        }
        unit 17 {
            description SEPTIMUS;
            vlan-id 17;
            family inet {
                mtu 1500;
                address 2.0.0.65/30;
            }
            family iso;
        }
    }
    lo0 {
        unit 3 {
            family inet {
                address 1.1.1.3/32;
            }
            family iso {
                address 49.0001.0100.0100.1003.00;
            }
        }
    }
}
protocols {
    rsvp {
        interface xe-0/3/0.7;
    }
    mpls {
        no-decrement-ttl;
        label-switched-path to_Romulus {
            to 1.1.1.6;
        }
        label-switched-path to_Caligula {
            to 1.1.1.8;
        }
        label-switched-path to_Nero {
            to 1.1.1.11;
        }
        interface xe-0/3/0.7;
    }
    bgp {
        group reflector {
            type internal;
            local-address 1.1.1.3;
            hold-time 0;
            family inet {
                unicast;
            }
            family inet-vpn {
                unicast;
            }
            authentication-key "$9$nObmCt0EhyreM7-oZUHPf"; ## SECRET-DATA
            cluster 1.1.1.3;
            peer-as 1;
            bfd-liveness-detection {
                minimum-interval 500;
            }
            neighbor 1.1.1.6 {
                description Romulus;
            }
            neighbor 1.1.1.11 {
                description Nero;
            }
            neighbor 1.1.1.8 {
                description Caligula;
            }
        }
    }
    isis {
        traffic-engineering {
            family inet {
                shortcuts;
            }
        }
        interface xe-0/3/0.7 {
            level 1 disable;
        }
        interface lo0.3;
    }
}
policy-options {
    policy-statement hub-routes {
        term hub {
            from {
                protocol bgp;
                community hub;
            }
            then accept;
        }
        term reject-other {
            then reject;
        }
    }
    policy-statement spoke-to-hub {
        term spoke {
            then {
                community add spoke;
                accept;
            }
        }
    }
    community hub members target:4:4;
    community spoke members target:2:2;
}
routing-instances {
    spoke-c {
        instance-type vrf;
        interface xe-0/3/0.17;
        route-distinguisher 2:2;
        vrf-import hub-routes;
        vrf-export spoke-to-hub;
        vrf-table-label;
        routing-options {
            static {
                route 16.0.0.3/32 next-hop 2.0.0.66;
            }
        }
    }
}
routing-options {
    autonomous-system 1;
}
Augustus P-router:
interfaces {
    xe-0/2/0 {
        unit 7 {
            description GAIUS;
            vlan-id 7;
            family inet {
                mtu 1500;
                address 2.0.0.26/30;
            }
            family iso;
            family mpls;
        }
        unit 15 {
            description CALIGULA;
            vlan-id 15;
            family inet {
                mtu 1500;
                address 2.0.0.58/30;
            }
            family iso;
            family mpls;
        }
    }
    xe-0/3/0 {
        unit 12 {
            description NERO;
            vlan-id 12;
            family inet {
                mtu 1500;
                address 2.0.0.45/30;
            }
            family iso;
            family mpls;
        }
        unit 13 {
            description ROMULUS;
            vlan-id 13;
            family inet {
                mtu 1500;
                address 2.0.0.49/30;
            }
            family iso;
            family mpls;
        }
    }
    lo0 {
        unit 7 {
            family inet {
                address 1.1.1.7/32;
            }
            family iso {
                address 49.0001.0100.0100.1007.00;
            }
        }
    }
}
protocols {
    rsvp {
        interface all;
    }
    mpls {
        interface all;
    }
    isis {
        traffic-engineering {
            family inet {
                shortcuts;
            }
        }
        interface all {
            level 1 disable;
        }
    }
}

Next will be a hub-and-spoke vpn with a hub site that is connected via only 1 connection. You can find this here.

15-4-2015