VRFing 103, Using NAT Virtual Interfaces for Global Reachability

The last few technical articles I’ve written have been around the topic of VRFs. VRF, short for Virtual Routing an Forwarding, is basically a way to carve out areas of isolation in your router. The way this is accomplished is a fairly heavy handed approach. In some ways, I would actually consider it more imposing than how a firewall does segmentation. The true intent of VRF instances is isolation of routing instances.

Those who enjoy VRFing 101, 102 and 103 will also find the following series on Layer 3 Segmentation with VRFs useful.

https://packetu.com/2017/01/29/segmenting-layer-3-networks-vrfs/

Last week we saw that there are ways to allow traffic to break out of a VRF and access the Internet. Specifically, we allowed dynamic nat overload (aka PAT) for traffic originating in a VRF. Those who are familiar with IOS NAT operations, realize the importance of passing traffic between two opposing NAT interface (i.e. between “ip nat inside” and “ip nat outside”). In our example, the global interface was tagged as “ip nat outside”. Likewise the “red” and “blue” VRFs were both tagged as “ip nat inside”.

Passing traffic from an interface tagged as “ip nat inside” to another interface also tagged as “ip nat inside” does not invoke NAT. This article will demonstrate the use of NAT Virtual Interfaces to provide outbound connectivity as well as Global Reachability for services published via static NAT entries.

Challenge–Looking at the diagram below, create a multitenant environment using two VRFs. The business that is connected to VRF “blue” also desires to offer services from 192.168.1.2. As the service provider, it is our responsibility to make this private address appear as 192.0.2.200 to the rest of the Internet (including all other customers who share the same router). As with our challenge last week, both VRFs must be able to access the Internet.

Starting with IOS version 12.3.14T, Cisco offered a new configuration construct for nat called NAT Virtual Interface (NVI). This removed the requirement to configure an interface as nat ‘inside’ or ‘outside’. Using NVI, NAT is simply enabled or not enabled on each interface. This is crucial to solving our challenge.

With our challenge well understood, let’s start out by configuring R1 for NAT Overload. Unlike our approach last week, this week we will use NVI. Most of the configuration is very similar. However, there are no inside or outside paramaters in any of the commands for NVI.

R1 Base Configuration

//create the VRFs
R1(config)#ip vrf red
R1(config)#ip vrf blue

//configure the interface and assign the VRF 
R1(config-subif)#int fa0/0.10 
R1(config-subif)#encapsulation dot1Q 10 
R1(config-subif)#ip vrf forwarding red 
R1(config-subif)#ip address 192.168.1.1 255.255.255.0 

//configure the interfaces and assign the VRF 
R1(config-subif)#int fa0/0.20 
R1(config-subif)#encapsulation dot1Q 20 
R1(config-subif)#ip vrf forwarding blue 
R1(config-subif)#ip address 192.168.1.1 255.255.255.0

Just like our challenge last week, we need to configure a link to the upstream router and route traffic for our the two VRFs. The initial interface configuration is typical.

R1(config)#int fa0/1
R1(config-if)#ip address 192.0.2.2 255.255.255.0
R1(config-if)#no shut

Since I like to test things as I go, let’s make sure R1 can reach the next hop Internet router. Because we are using an address that is reachable from the global routing table, this requires only the standard ping command.

R1(config-if)#do ping 192.0.2.1
Type escape sequence to abort. 
Sending 5, 100-byte ICMP Echos to 192.0.2.1, timeout is 2 seconds: 
..!!! 
Success rate is 60 percent (3/5), round-trip min/avg/max = 1/2/4 ms R1(config-if)#

Last week we learned that Cisco had a special configuration syntax that is required when routing packets from a VRF to the global address spaces. Either of these options should work for our configuration.

Two Options for Routing into a different VRF

//interface in the route command
R1(config)#ip route vrf red 0.0.0.0 0.0.0.0 fa0/1 192.0.2.1
R1(config)#ip route vrf blue 0.0.0.0 0.0.0.0 fa0/1 192.0.2.1

-or-

//global keyword on the route command
R1(config)#ip route vrf red 0.0.0.0 0.0.0.0 192.0.2.1 global
R1(config)#ip route vrf blue 0.0.0.0 0.0.0.0 192.0.2.1 global

Now we can start with the NVI Configuration.

Enable Nat on the Interfaces

//enable NAT on the three interfaces
//notice we are using "ip nat enable"
//as opposed to doing "ip nat inside | outside

R1(config)#int fa0/0.10
R1(config-subif)#ip nat enable

R1(config)#int fa0/0.20
R1(config-subif)#ip nat enable  

R1(config)#int fa0/1
R1(config-if)#ip nat enable

The NAT pools are created the same way for NVI as for traditional NAT.

NAT Pools

//NAT pool RED 192.0.2.10 (later used for vrf red)
R1(config)#ip nat pool RED 192.0.2.10 192.0.2.10 prefix-length 24

//NAT pool BLUE 192.0.2.20 (later used for vrf blue)
R1(config)#ip nat pool BLUE 192.0.2.20 192.0.2.20 prefix-length 24

Next we need to create the ACLs to define Interesting Traffic. Again, this is the same as in the traditional NAT configuration we looked at last week.

NAT ACLs

//to be used for vrf red
R1(config)#ip access-list extended REDNAT
R1(config-ext-nacl)#permit ip 192.168.1.0 0.0.0.255 any

//to be used for vrf blue
R1(config)#ip access-list extended BLUENAT
R1(config-ext-nacl)#permit ip 192.168.1.0 0.0.0.255 any

The final step required to allow outbound access is the actual NAT statements. There are only subtle differences with NVI, but these are very important.

NVI NAT Statements

ip nat source list BLUENAT pool BLUE vrf blue overload
ip nat source list REDNAT pool RED vrf red overload
//note the exclusion of "inside" immediately following "nat"

Now we are ready to test our outbound access.

Enable NAT Debugging on R1

R1(config)#do debug ip nat
IP NAT debugging is on

Test Outbound from R2

R2(config)#do ping 1.1.1.1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 1.1.1.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/4/4 ms
R2(config)#

Test Outbound from R3

R3(config)#do ping 1.1.1.1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 1.1.1.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/3/4 ms
R3(config)#

Review NAT Debugs on R1

R1(config)#
Jul  7 04:24:51.375: NAT*: s=192.168.1.2->;192.0.2.10, d=1.1.1.1 [257]
Jul  7 04:24:51.375: NAT: s=1.1.1.1, d=192.0.2.10->;192.168.1.2 [257]
Jul  7 04:24:51.379: NAT*: s=192.168.1.2->;192.0.2.10, d=1.1.1.1 [258]
Jul  7 04:24:51.379: NAT: s=1.1.1.1, d=192.0.2.10->;192.168.1.2 [258]

Jul  7 04:25:06.087: NAT*: s=192.168.1.2->;192.0.2.20, d=1.1.1.1 [178]
Jul  7 04:25:06.091: NAT: s=1.1.1.1, d=192.0.2.20->;192.168.1.2 [178]
Jul  7 04:25:06.091: NAT*: s=192.168.1.2->;192.0.2.20, d=1.1.1.1 [179]
Jul  7 04:25:06.091: NAT: s=1.1.1.1, d=192.0.2.20->;192.168.1.2 [179]

As we can see, we have outbound translations for both VRFs. Even though we could have easily done this using the method outlined last week, this is only one part of this week’s challenge. The other item mentioned in the challenge was to make 192.168.1.2 in VRF “blue” accessible globally. As the service provider, we were planning to use 192.0.2.200. A major concern was making sure that users in the “red” VRF could also reach 192.0.2.200. NVI static translations should make this a cleaner configuration.

Now we can add the static translation to R1’s NAT configuration.

NVI Static NAT Translation

R1(config)#ip nat source static 192.168.1.2 192.0.2.200 vrf blue
//again, note the exclusion of "inside" after the word "inside"

Now let’s test our configuration.

Enable ICMP Debugs on R3. This will allow us to see the source translation of packets leaving the “red” vrf.

ICMP Debugs

R3#debug ip icmp
ICMP packet debugging is on
R3#

We can now test by sending ICMP Echoes from R2.

R2#ping 192.0.2.200

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.0.2.200, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 4/4/4 ms
R2#

Since we have NAT debugs still running on R1, we can take a look at those.

R1(config)#do debug ip nat                                  
IP NAT debugging is on
R1(config)#
Jul  7 04:32:15.859: NAT*: s=192.168.1.2->;192.0.2.10, d=192.0.2.200 [272]
Jul  7 04:32:15.859: NAT*: s=192.0.2.10, d=192.0.2.200->;192.168.1.2 [272]
Jul  7 04:32:15.859: NAT*: s=192.168.1.2->;192.0.2.200, d=192.0.2.10 [272]
Jul  7 04:32:15.863: NAT*: s=192.0.2.200, d=192.0.2.10->;192.168.1.2 [272]
Jul  7 04:32:15.863: NAT*: s=192.168.1.2->;192.0.2.10, d=192.0.2.200 [273]
Jul  7 04:32:15.863: NAT*: s=192.0.2.10, d=192.0.2.200->;192.168.1.2 [273]
Jul  7 04:32:15.863: NAT*: s=192.168.1.2->;192.0.2.200, d=192.0.2.10 [273]
Jul  7 04:32:15.863: NAT*: s=192.0.2.200, d=192.0.2.10->;192.168.1.2 [273]

R1(config)#

//noteworthy in this is the fact that 192.168.1.2 
// in the red VRF is being translate to 192.0.2.10 
//per its outbound configuration. 
//The destination is 192.0.2.200.

//in the second line, we can see the destination 
//of 192.0.2.200 translated as the packet flows 
//into the blue vrf.

Reviewing the ICMP debugs on R3, we can see that it is responding to 192.0.2.10. This was the address from the NAT pool for the “red” VRF.

R3#debug ip icmp
ICMP packet debugging is on
R3#
Jul  7 04:32:16.199: ICMP: echo reply sent, src 192.168.1.2, dst 192.0.2.10
Jul  7 04:32:16.203: ICMP: echo reply sent, src 192.168.1.2, dst 192.0.2.10
Jul  7 04:32:16.207: ICMP: echo reply sent, src 192.168.1.2, dst 192.0.2.10
Jul  7 04:32:16.211: ICMP: echo reply sent, src 192.168.1.2, dst 192.0.2.10
Jul  7 04:32:16.215: ICMP: echo reply sent, src 192.168.1.2, dot 192.0.2.10

When using NVI, the output of “show ip nat translations” no longer works. With NVI, it is necessary to use “show ip nat nvi translation”. Since we are using VRFs, we also have to specify the one we want to see the translations for.

NVI Version of “show ip nat translations”

//show ip nat translations--shows us nothing
R1#show ip nat translations
Pro Inside global      Inside local       Outside local      Outside global

//show ip nat nvi trans vrf red--shows us a dynamic translation
R1#show ip nat nvi translations vrf red
Pro Source global      Source local       Destin  local      Destin  global
icmp 192.0.2.10:54     192.168.1.2:54     192.0.2.200:54     192.168.1.2:54

//show ip nat nvi trans vrf blue--notice the static translation
R1#show ip nat nvi translations vrf blue
Pro Source global      Source local       Destin  local      Destin  global
icmp 192.0.2.200:54    192.168.1.2:54     192.0.2.10:54      192.168.1.2:54
--- 192.0.2.200        192.168.1.2        ---                ---

This article has demonstrated the use of NVI to overcome some of the challenges in a complex NAT environment. This allowed us to create a solution to a more realistic design requirement. In future articles, we will continue digging deeper into how VRFs can be used to allow for highly flexible network designs that overcome complex challenges.

As always, if you have article or content suggestions, you can use the “contact us” page. I love hearing from PacketU readers.

No related content found.

About Paul Stewart, CCIE 26009 (Security)

Paul is a Network and Security Engineer, Trainer and Blogger who enjoys understanding how things really work. With over 15 years of experience in the technology industry, Paul has helped many organizations build, maintain and secure their networks and systems.
This entry was posted in How-To and tagged . Bookmark the permalink.

12 Responses to VRFing 103, Using NAT Virtual Interfaces for Global Reachability

  1. Gauthier says:

    Hello,

    Thank you for your really interesting article.

    Just one question, is it possible to apply an ACL to the NVI Static NAT Translation? For example, to permit only certain tcp ports.

    Or maybe there is an other way to follow?

    Thank you!

    • Paul Stewart says:

      Unfortunately, I do not believe you can do that with NVI. I’ve never seen the option to use acl’s or route-maps with NVI configuration. You might be able to do something really ugly like policy route traffic that isn’t to be NATted over to a loopback that doesn’t have “ip nat enable”. Even if that worked, it’d be a kludge (and I probably wouldn’t recommend it).

      Now you can do port level static translations with NVI like this–

      ip nat source static tcp x.x.x.x port y.y.y.y port

      Or you can do dynamic translation using acl’s. I just don’t think you can do static translations with route-maps or acls. Sorry.

      • Gauthier says:

        Thank you for your quick answer!

        The problem of he command line you indicated is not possible for vrf.

        I would like to do a port level static translations but in a vrf. I checked the options of ip nat source static and didn’t find any solution..

        Gauthier

  2. Carlos Moraes says:

    hello Paul, how you been?

    man, I’m trying to apply this configuration below, but it is not working, could you guide me where is the error?

    Router’s configuration:

    !
    interface Loopback0
    no ip address
    !
    interface Multilink1
    ip address 189.56.149.114 255.255.255.252
    ppp multilink
    ppp multilink group 1
    !
    interface GigabitEthernet0/0
    no ip address
    shutdown
    duplex auto
    speed auto
    !
    interface GigabitEthernet0/1
    description Trunk para Switch interno
    no ip address
    duplex auto
    speed auto
    !
    interface GigabitEthernet0/1.1
    description Dados – VLAN 1
    encapsulation dot1Q 1 native
    ip address 152.141.112.1 255.255.255.128
    ip helper-address 152.141.112.127
    !
    interface GigabitEthernet0/1.40
    description VoIP – VLAN 40
    encapsulation dot1Q 40
    ip address 10.1.4.1 255.255.255.128
    ip helper-address 10.1.4.127
    !
    interface GigabitEthernet0/1.255
    description ADGUEST – VLAN 255
    encapsulation dot1Q 255
    ip address 172.17.42.1 255.255.255.0
    ip helper-address 172.17.42.255
    !
    interface Serial0/0/0
    description MPLS 110005686102591
    no ip address
    encapsulation ppp
    ppp multilink
    ppp multilink group 1
    no clock rate 2000000
    !
    router bgp 65000
    bgp router-id 152.141.112.94
    bgp log-neighbor-changes
    neighbor 189.56.149.113 remote-as 10429
    !
    address-family ipv4
    no synchronization
    network 10.1.4.0 mask 255.255.255.128
    network 152.141.112.0 mask 255.255.255.128
    neighbor 189.56.149.113 activate
    neighbor 189.56.149.113 route-map defaultonly in
    neighbor 189.56.149.113 route-map localonly out
    no auto-summary
    exit-address-family
    !

    NVI’s configuration:

    ip vrf adguest
    !
    int GigabitEthernet0/1.255
    ip vrf forwarding adguest
    !
    int GigabitEthernet0/1.255
    ip nat enable
    !
    ip nat pool ADGUEST 152.141.112.126 152.141.112.126 prefix-length 24
    !
    ip access-list extended ADGUESTNAT
    permit ip 172.17.42.0 0.0.0.255 any
    !
    ip nat source list ADGUESTNAT pool ADGUEST vrf adguest overload
    !

    Regards Carlos Moraes

    • Paul Stewart says:

      i think the primary issue is that “ip nat enable” isn’t on the source and destination interface. You would probably need to make sure you have a route that jumps the packet from one vrf to the other as well.

  3. Wei Jen Yeh says:

    Thanks for the post. A couple of questions:

    1. Is it required to have separate non-overlapping NAT pools between VRFs?
    2. Does IOS have a command that can dump the NAT translation information given *only* the NAT’ed IP, w/o the VRF ID?

    Regards.
    –Wei Jen

  4. Pingback: Segmenting Layer 3 Networks with VRFs - PacketU

  5. Andrew says:

    Hi, These are excellent examples. Thanks.

    However, in each of these articles there is the assumption that on the Internet or outside interfaces there are routed IP’s in use. i.e the destination outside, knows how to get back to them.

    I’m trying to figure out how to have several vrf’s behind a single WAN IP. And I can’t quite piece that together from your examples.

    So for example:
    WAN IP real, and is a /30, terminates on a physical interface. gi0/0
    For this example let’s say that IP is 10.250.250.62 / 30 and the ISP end is 10.250.250.61
    Inside we have a single Gi0/1 interface, and the need for X ‘tenants’ – lets say 2 but it might be 10 or more.

    To separate the tenants networks sub interfaces on the inside can be used (or VLANs if they are switch ports) lets assume sub-interfaces and dot1q for this example.

    tenant-1 gi0/1.101 IP network: 192.168.101.0/24 Gateway: 192.168.101.254
    tenant-2 gi0/1.102 IP network: 192.168.102.0/24 Gateway: 192.168.102.254

    I’d like to get NAT working such that traffic inside each tenant network leaves towards the internet from the 10.250.250.61 address so that it can return.

    ip vrf TENANT-1
    ip vrf TENANT-2
    !
    int gi0/0
    desc OUTSIDE to ISP
    ip address 10.250.250.61 255.255.255.252
    ip nat outside
    !
    int gi0/1.101
    encapsulation dot1q 101
    ip vrf forwarding TENANT-1
    ip address 192.168.101.254 255.255.255.0
    ip nat inside
    !
    int gi0/1.102
    encapsulation dot1q 102
    ip vrf forwarding TENANT-2
    ip address 192.168.102.254 255.255.255.0
    ip nat inside
    !
    ip nat pool TENANT-1 10.250.250.62 10.250.250.62 prefix-length 24
    ip nat pool TENANT-2 10.250.250.62 10.250.250.62 prefix-length 24
    ip nat inside source list TENANT-1-NAT pool TENANT-1 vrf TENANT-1 overload
    ip nat inside source list TENANT-2-NAT pool TENANT-2 vrf TENANT-2 overload
    !
    ip route 0.0.0.0 0.0.0.0 10.250.250.61
    ip route vrf TENANT-1 0.0.0.0 0.0.0.0 10.250.250.62 global
    ip route vrf TENANT-2 0.0.0.0 0.0.0.0 10.250.250.62 global
    !
    ip access-list extended TENANT-1-NAT
    permit ip 192.168.101.0 0.0.0.255 any
    ip access-list extended TENANT-2-NAT
    permit ip 192.168.102.0 0.0.0.255 any
    !

    I’m not sure if I can use the ip nat pool start/end IP address twice like this? Is that valid?

    • That’s a really good question. I think I’d try just creating the pool once. And calling it with 2 nat statements (one for each vrf). I really don’t know for sure if it’ll behave as expected or not. In any case you could ultimately have an outside address that is in one vrf and is in another after a translation timeout. Not sure the use but it’s definitely an interesting question.

      • Andrew says:

        Hi Paul,

        So, turns out it seems to confuse NAT because if traffic from both vrf networks are heading to the same outside destination, on the same protocol and port at the same time. only one host sees the return traffic.

        At one point I had both internal networks pining the same destination, so ICMP seems to deal with it. But when I tried something tcp based (an iperf test to the same server/port outside) only one works at a time.

        The reason is – you might have a multi-tenant network where you’re providing shared internet access to a group of customers. Initially VLAN’s none-overlapping IP subnets and ACL’s allow for easy separation of those networks.

        And whilst the customers don’t need mappings to internal servers or access from the internet being all on separate VLAN’s and IP subnets behind NAT works perfectly well.

        Then you get a customer wanting a dedicated WAN IP. This shifts you to using VRF’s as you can NAT the VRF traffic behind that WAN IP. But what about the rest? Using VRF’s behind WAN IP’s seems to be a an all or nothing model. So now you suddenly need WAN IP’s for all your customers to shift them over.

        Also, if you want to offer over-lapping customer IP space, i.e. given them all 192.168.1.0/24 or something – you’re forced to use VRF’s to allow for that – and you’re right back needing individual WAN IP’s.

        I don’t think I can achieve what I want inside a single physical router, as I need to establish a transport network that allows VRF traffic to NAT to a known shared IP range, and then that IP range etc can either be routed to the world or again NAT’d behind a common WAN IP to share.

        Cheers,

      • Thanks for the feedback. I can see how a shared address range could be a challenge for this. I could also create challenges if someone blacklisted some of those addresses. Thanks again for the feedback on your findings.

  6. Joseph says:

    Hello Paul,

    This group of VRF articles are amazing and thank you!. Could you write out the syntax in the correct scenario for the port level Nat so that services could be reached from then internet? Meaning most statements that were written had the vrf “name” then the statement. so for example: does this statement need the VRF name in it?

    ip nat source static tcp x.x.x.x port y.y.y.y port

Comments are closed.