In my previous post, we saw the theory behind hub-and-spoke VPN. We saw how H/S involves multiple VRFs with cross-importation between them, and we traced the basic flow of a route advertised from one spoke to another.
Next, we are going to look at two options for configuring H/S VPNs. In this post, I will cover using BGP as the PE-CE routing protocol without independent route reflectors. In my next post, I will cover OSPF. Finally, I will return to BGP and examine the issues that come up when we use independent route reflectors with hub and spoke VPN.


To review, let’s examine our setup. R5 is the hub PE, which has two separate links to the Hub CE, R2. These can be physically separate or different logical units on the same physical interface. In my lab, they are two physical interfaces. We have two spokes in this lab, although there is no reason you can’t use more. Each spoke has a PE and a CE router.
Note: This is part of a larger lab, but I have extracted only the relevant part. This is why the router numbering does not start at 1. Also note that in my labs, the last octet of the router’s IP address equals the router number. This should help in decoding the outputs.

For my initial configuration, I have MPLS enabled with RSVP, and LSPs are established between R5 and the spoke PEs. Since H/S VPN does not allow spoke-to-spoke traffic, I don’t bother with a spoke-to-spoke LSP. R5 is acting as a route-reflector for the spokes, but notice that it is in the path of the traffic flow. We’ll see that there are some more issues when the RR is not in the path. Although not strictly necessary, we are going to look at the worst case, with the hub CE and both spokes all being in the very same AS.

Configuring the spokes

To begin, I configure my Spoke 1 CE to peer with its PE via BGP, exporting its loopback, which will be our test prefix:

Note: You do not need to set type “internal” or “external” explicitly. Junos will determine that based on the local and remote AS numbers.

Next, we define a VRF on the Spoke 1 PE router, and peer via BGP to the CE:

Now this configuration should be familiar if you have worked with MPLS VPNs. If you haven’t, you need to review them before reading this article. Assuming that’s not the case, you will know that this config will not commit because we need to define a few more things:

I’m configuring things a bit out of order so you can see that the VRF configuration is pretty basic. For an ordinary VRF, you could use a vrf-target instead of an import/export statement, but I recommend you always use import/export for layer 3 VPN on the JNCIE lab exam, since you will probably need to do some customization and tweaking of your policies. Regardless, for H/S VPN you must use import/export policies. The really interesting part of the H/S config is in the policy-options stanza:

Here we can see the cross-importation that was described in the previous article. This VRF imports routes carrying a different community than it uses to export. We import “hub” routes but export “spoke” routes. You will, of course, want to be sure the community values are the same across all hub and spoke routers. All spoke routers will be tagged using the same spoke community, i.e., there is not a different community for each spoke.
Note: Note well that while there is only one VRF target-type community for both spokes, if we do Site-of-Origin filtering we will need to have additional origin-type communities, which will be unique to the particular spoke.
As you can imagine, the configuration for Spoke 2 is identical, other than the IP addresses. Remember, we are using AS 65100 at all sites, hub or spoke. (The “provider” network is using AS 100.)

Configuring the hub

Recall that the hub has not one, but two VRFs. We’ll begin the hub configuration with the policy-options, which I’ll show in “set” format here:

A few things to notice:

1. We created a policy-statement called “null” that just rejects everything. It will be used in both VRFs.
2. The spoke-in policy is for the spoke VRF. Notice at the hub that we import routes with the spoke community. Do you remember what community we used on the spokes to export? Spoke. So the routes exported by the spokes will be imported into this VRF.
3. The hub-out policy is for the hub VRF. As we will see, and as we saw in the last article, the hub VRF learns routes from the Hub CE via PE-CE BGP. It does not import any routes from MBGP. The routes it learns are advertised back to the spokes. What do the spokes import? Routes with the “hub” community, of course!

Now we will define our VRFs. Let’s start with the spoke VRF:

Note that the configuration check succeeds because we have already defined our policies. This is a basic VRF configuration with a catch: While we import spoke-tagged routes, we export nothing. Next we need to define a BGP peering in this VRF:

This is the PE-CE peering to the Hub CE. Remember that the Hub CE has two interfaces connecting it to the Hub PE; one of them learns routes from the PE, the other sends routes to the PE. Now, on to the hub VRF.

This is another basic VRF, but now the import is null and the export is hub-out. Notice that I defined a second BGP peering. This is a peering to the exact same CE router, just on a different interface and in a different VRF! I repeat myself often so that you’ll learn.

On the Hub CE, we’ll configure a single BGP group with two peerings, yes, to the same PE router:

Looking at the results

We’ve now done the basic config, but as we’ll see, it won’t work yet. We’ll start at spoke 1 and trace our sample route, through the network. Remember, this route should be advertised as follows:

Spoke 1 CE->Spoke 1 PE->Hub PE->Hub CE->Hub PE->Spoke 2 PE->Spoke 2 CE

Our Spoke 1 PE sees the route from its CE:

Next, we can see that our Hub PE receives it and is pointing out the correct LSP:

So far so good. Next, we expect to see it on the Hub CE:

Not so good. What happened? Recall that in this example, we are using the same ASN for all three sites. Why are we doing this? Well, it might be that way on a test. BGP is smart enough not to advertise the route back to the Hub CE since it is in the same AS (65100) that originated the route. The easiest solution is simply to have the PE rewrite the ASN with its own:

And now we see it on r2, the hub CE:

Now, we expect the route will be advertised from the hub CE to the hub PE, but something’s amiss:

What’s going on here? Well, once again we are running into AS looping problems. Our hub CE knows full well that its neighbor is in AS 100 and would drop any route that arrives via BGP with the same ASN. So, r2 does the kindly thing and doesn’t bother to advertise it. We can change this behavior with the advertise-peer-as option:

So, the route is now being advertised from our CE back to the hub PE. We should see it there, right?

No, repeat after me: nothing comes easy with hub and spoke VPN. Look at the previous example, where the route is visible on R2. AS 100 is in the path twice, which means it looks like a loop. BGP will not use this route. In order to make this work, we need to tell Junos it’s ok to have loops:

Note that we had to reset our BGP neighbor for this to work. I could have reset it individually, but I was lazy and did all of them. I need to apply this configuration on all of the service provider routers; otherwise, the spokes will reject the route.

We have one last thing to do before our route makes it to the Spoke 2 CE—we have to enable as-override on the Spoke 2 PE. Remember, we are using the same ASN at all sites, and this route has 65100 in the AS path. After enabling it, we can see our route has made it all the way through:

Now in order to have bidirectional traffic, of course, R8 needs to advertise its route(s) back in exactly the same way, so we have to make sure we replicate what we did going the other way. (E.g., Spoke 1 PE needs as-override.)

On the Hub CE, using the monitor traffic interface command, with the “b” option, we can see the traffic flowing in one interface and out the other:

Cleaning it up

Most descriptions of H/S VPN recommend a step which I haven’t implemented here. To prevent routing loops, they say you should use the Site-of-Origin community to filter routes from a spoke that were originated there. My setup works fine without SoO, but there is in fact an oddity without it:

Here we can see that R10, the Spoke 1 PE, has two routes to the network that is being advertised by its own CE. This is because the route has been re-advertised at the hub into the hub VRF, which is the VRF that our spokes are importing from. The router doesn’t select it because its AS path is too long, but it potentially could be a problem. We can modify the spoke policy to block this and save ourselves trouble. Here is our complete policy options stanza with this done.

We need, of course, to do the same thing on spoke 2.

Interface routes

In my case I only advertised a single loopback address from each spoke. In the JNCIE lab, you will need to advertise a lot more. Be sure to read their instructions carefully, and pay special attention to the interface routes. Even if they don’t specifically tell you to advertise them, you would always do well to include them when constructing your routing policies.


Hub and spoke VPN is complex, and we’ve covered a lot in this article. If it seems confusing, I recommend you review the first, high-level article and then come back to this one. The actual hub and spoke scenario you might face in the lab will assuredly be more complex than this, but if you practice this scenario several times, it should be easy to extrapolate to a more complex scenario. My next article will cover hub and spoke with OSPF as the routing protocol.

To wrap-up:
• We configured basic BGP as our PE-CE protocol on the hub and spokes, and defined basic VRFs on the PEs.
• On the spoke PE’s, we defined special import/export policies such that the hubs import routes tagged with the hub community but export with the spoke policy.
• We configured two VRFs on the hub PE router, one of which imported spoke-tagged routes, while the other exported hub-tagged routes.
• We configured as-override, advertise-peer-as, and AS loops to overcome the difficulty of using the same AS in three different places.
• We configured SoO to prevent the routes from looping.