Junos IPv6 to IPv4 NAT

Recently I took the JNCIE-SEC lab (that will be another post) and wanted to cover one of the study points that I initially struggled with, IPv4<->IPv6 NAT on a Juniper SRX device. This configuration is actually “relatively” simple once you understand it, yet most of the examples I found out there made it difficult to understand. My hope here is to put it in a format to help you understand how to configure it on a Juniper SRX device (this lab used vSRX on EVE-NG).

Before we get into the start of the config, please be aware that Site1 and Site2 SRX’s have been placed into packet mode. This mode makes them a router and not a security device, so no security policies will be required on these devices. The main SRX is still in flow mode and will require security policies to permit the traffic. For this lab, I will be using a simple global any/any/any policy.

Site1 & Site2 packet mode config:
set security forwarding-options family inet6 mode packet-based
set security forwarding-options family mpls mode packet-based
set security forwarding-options family iso mode packet-based
Global Security Policy on the SRX:
root@SRX-NAT> show configuration security policies 
 global {
     policy PERMIT-ALL {
         match {
             source-address any;
             destination-address any;
             application any;
             from-zone [ IPV4 IPV6 ];
             to-zone [ IPV4 IPV6 ];
         }
         then {
             permit;
         }
     }
 }

Below is our lab topology. In the BLUE box on the left, we have our IPv4 only site using a subnet of 192.168.100.0/24. The host is assigned the IP of 192.168.100.2 and the SRX is assigned an IP of 192.168.100.1. On the SRX, will call this security zone IPV4

In the RED box on the right, we have our IPv6 network using 2001:db8::/64 for the subnet. The host is assigned 2001:db8::2/64 and the SRX has an IP of 2001:db8::1. On the SRX we will call this security zone IPV6.

In order for IPv4 to talk to an IPv6 network and IPv6 to talk to IPv4, we will need to perform source NAT as well as destination NAT. Source NAT will be used to NAT traffic from one zone to an interface and subnet in the other zone.

Destination NAT will be used so that the IPv4 host can initiate traffic towards the IPv6 host via an IPv4 NAT address. In the same fashion, we will have an IPv6 NAT address for the IPv6 host to initiate traffic towards the IPv4 host.

For the IPv4 host to generate traffic towards the IPv6 host we will use an IPv4 NAT address of 192.168.100.254. For the IPv6 host to generate traffic to the IPv4 host, we will use an IPv6 NAT of 2001:db8::254. This will make a bit more sense once we perform the configuration.

Ok – quick recap of all the information mentioned so far:

Global Security Policies
Source          - Any
Destination     - Any
Application     - Any
Zones           - IPV4 IPV6

IPv4 Information
Subnet          - 192.168.100.0/24
SRX ge-0/0/0    - 192.168.100.1/24
Host ge-0/0/0   - 192.168.100.2/24
IPv4 - IPv6 NAT - 192.168.100.254/32  
Security Zone   - IPV4

IPv6 Information
Subnet          - 2001:db8::/64
SRX ge-0/0/1    - 2001:db8::1/64
Host ge-0/0/0   - 2001:db8::2/64
IPv6 - IPv4 NAT - 2001:db8::254/128
Security Zone   - IPV6

We will start with our Source NAT configuration. This is a standard source-NAT configuration that is commonly used to traffic from internal networks to the Internet on Juniper firewalls all the time.

In the configuration snippet below we have configured a source nat for all traffic from 192.168.100.0/24 (IPV4) towards 2001:db8::0/64 (IPV6) to be NAT’d to the ge-0/0/1 interface (2001:db8::1).

root@SRX-NAT> show configuration security nat source 
rule-set IPV4-OUT {
     from zone IPV4;
     to zone IPV6;
     rule IPV4-IPV6-NAT {
         match {
             source-address 192.168.100.0/24;
             destination-address 2001:db8::0/64;
         }
         then {
             source-nat {
                 interface;
             }
         }
     }
 }

In the snippet below we configure another source NAT policy for all traffic from 2001:db8::/64 (IPV6) towards 192.168.100.0/24 (IPV4) to be NAT’d to the ge-0/0/0 interface (192.168.100.1).

root@SRX-NAT> show configuration security nat source    
 rule-set IPV6-OUT {
     from zone IPV6;
     to zone IPV4;
     rule IPV6-IPV4-NAT {
         match {
             source-address 2001:db8::/64;
             destination-address 192.168.100.0/24;
         }
         then {                          
             source-nat {
                 interface;
             }
         }
     }
 }

Now that we have a way to translate traffic between the networks we need a way to initiate traffic. This is where the destination NAT addresses of 192.168.100.254 and 2001:db8::254 come into play.

The first thing we will do is configure two destination NAT pools. One pool for each of the hosts we want to talk to. To keep it simple I will use the names IPV4-HOST for 192.168.100.2 and IPV6-HOST for 2001:db8::2. The reason that the pool is the IP address of the destination host is that we will translate our NAT to that IP.

root@SRX-NAT> show configuration security nat destination 
 pool IPv4-HOST {
     address 192.168.100.2/32;
 }
 pool IPv6-HOST {
     address 2001:db8::2/128;
 }

We will start with the IPv4 to IPv6 destination NAT configuration. Here you can see we are specifying the source zone of IPV4 and matching the destination address of 192.168.100.254 (NAT). We are then telling the policy to use the destination-nat pool that references the IPv6 host (2001:db8::2). So what this policy is doing is NATing 192.168.100.254/32 -> 2001:db8::2/128.

root@SRX-NAT> show configuration security nat destination 
 rule-set IPV4-to-IPV6 {
     from zone IPV4;
     rule IPV4-NAT {
         match {
             destination-address 192.168.100.254/32;
         }
         then {
             destination-nat {
                 pool {
                     IPv6-HOST;
                 }
             }
         }
     }
 }

Below we are specifying the source zone of IPV6 now and matching the destination address of 2001:db8::254 (NAT). We are then telling the policy to use the destination-nat pool that references the IPv4 host (192.168.100.2). So what this policy is doing is NATing 2001:db8::254/128 -> 192.168.100.2/32.

root@SRX-NAT> show configuration security nat destination 
 rule-set IPV6-to-IPV4 {
     from zone IPV6;
     rule IPV6-NAT {                     
         match {
             destination-address 2001:db8::254/128;
         }
         then {
             destination-nat {
                 pool {
                     IPv4-HOST;
                 }
             }
         }
     }
 }

Now let’s test PING between the two sites.

root@IPV4-HOST> ping 192.168.100.254 rapid    
 PING 192.168.100.254 (192.168.100.254): 56 data bytes
 …..
 --- 192.168.100.254 ping statistics ---
 5 packets transmitted, 0 packets received, 100% packet loss

root@IPV6-HOST> ping 2001:db8::254 rapid    
 PING6(56=40+8+8 bytes) 2001:db8::2 --> 2001:db8::254
 …..
 --- 2001:db8::254 ping6 statistics ---
 5 packets transmitted, 0 packets received, 100% packet loss

You would think it would work, right? Well, it is not working yet because we are missing a few commands. In order to see what is wrong, we can look at our IPv4 and IPv6 host ARP/Neighbor tables.

root@IPV4-HOST> show arp no-resolve           
 MAC Address       Address         Interface     Flags
 50:00:00:01:00:01 192.168.100.1   ge-0/0/0.0           none

root@IPV6-HOST> show ipv6 neighbors 
 IPv6 Address                 Linklayer Address  State       Exp Rtr Secure Interface
 2001:db8::1                  50:00:00:01:00:02  stale       1083 yes no     ge-0/0/0.0  
 2001:db8::254                none               unreachable 1   yes no      ge-0/0/0.0  

As you can see, we do not have an ARP entry for 192.168.100.254 nor a neighbor entry for 2001:db8::254. This is because the source and destination NAT IPs are on the same subnet and Juniper SRX requires proxy ARP for IPv4 and proxy NDP for IPv6 to be configured.

Here we configure proxy-arp for the 192.168.100.254 address on the IPv4 interface (ge-0/0/0.0) and proxy-ndp for the 2001:db8::254 on the IPv6 interface (ge-0/0/1.0).

root@SRX-NAT> show configuration security nat 
 proxy-arp {
     interface ge-0/0/0.0 {
         address {
             192.168.100.254/32;
         }
     }
 }
 proxy-ndp {
     interface ge-0/0/1.0 {
         address {
             2001:db8::254/128;
         }
     }
 }

Now that we have that configured, let’s initiate a PING from the IPv4 host towards the IPv4 NAT address of 192.168.100.254. As you can see from the output below, the ping succeeds and we now have an ARP entry for the 192.168.100.254 IP.

root@IPV4-HOST> ping 192.168.100.254 rapid    
 PING 192.168.100.254 (192.168.100.254): 56 data bytes
 !!!!!
 --- 192.168.100.254 ping statistics ---
 5 packets transmitted, 5 packets received, 0% packet loss
 round-trip min/avg/max/stddev = 14.687/18.725/20.134/2.048 ms

 root@IPV4-HOST> show arp no-resolve 
 MAC Address       Address         Interface     Flags
 50:00:00:01:00:01 192.168.100.254 ge-0/0/0.0           none

Now let us go look at our NAT rules for this traffic to see if they are actually being matched. We will look at the source IPv4 rule (IPV4-IPV6-NAT) and the destination NAT rule (IPV4-NAT). As you can see in the output below we have Translation hits of 10 on each.

root@SRX-NAT> show security nat source rule IPV4-IPV6-NAT 
 source NAT rule: IPV4-IPV6-NAT          Rule-set: IPV4-OUT
   Rule-Id                    : 1
   Rule position              : 1
   From zone                  : IPV4
   To zone                    : IPV6
   Match
     Source addresses         : 192.168.100.0   - 192.168.100.255
     Destination addresses    : 2001:db8::      - 2001:db8::ffff:ffff:ffff:ffff
   Action                        : interface
     Persistent NAT type         : N/A              
     Persistent NAT mapping type : address-port-mapping 
     Inactivity timeout          : 0
     Max session number          : 0
   Translation hits           : 10
     Successful sessions      : 10
     Failed sessions          : 0
   Number of sessions         : 0

 root@SRX-NAT> show security nat destination rule IPV4-NAT 
 Destination NAT rule: IPV4-NAT               Rule-set: IPV4-to-IPV6
   Rule-Id                    : 1
   Rule position              : 1
   From zone                  : IPV4
     Destination addresses    : 192.168.100.254 - 192.168.100.254
   Action                     : IPv6-HOST
   Translation hits           : 10
     Successful sessions      : 10
     Failed sessions          : 0
   Number of sessions         : 0

Now we can test connectivity from the IPv6 host towards the IPv4 host using the IPv6 NAT (2001:db8::254). As you can see in the output below, it was successful.

root@IPV6-HOST> ping 2001:db8::254 rapid    
 PING6(56=40+8+8 bytes) 2001:db8::2 --> 2001:db8::254
 !!!!!
 --- 2001:db8::254 ping6 statistics ---
 5 packets transmitted, 5 packets received, 0% packet loss
 round-trip min/avg/max/std-dev = 9.519/10.763/14.351/1.805 ms

Now we can look at the IPv6 NAT policies that are used for this traffic. Again we can see we have 10 matches for each policy.

root@SRX-NAT> show security nat destination rule IPV6-NAT                   
 Destination NAT rule: IPV6-NAT               Rule-set: IPV6-to-IPV4
   Rule-Id                    : 2
   Rule position              : 2
   From zone                  : IPV6
     Destination addresses    : 2001:db8::254   - 2001:db8::254
   Action                     : IPv4-HOST
   Translation hits           : 10
     Successful sessions      : 10
     Failed sessions          : 0
   Number of sessions         : 0
 root@SRX-NAT> show security nat source rule IPV6-IPV4-NAT                   
 source NAT rule: IPV6-IPV4-NAT          Rule-set: IPV6-OUT
   Rule-Id                    : 2
   Rule position              : 2
   From zone                  : IPV6
   To zone                    : IPV4
   Match
     Source addresses         : 2001:db8::      - 2001:db8::ffff:ffff:ffff:ffff
     Destination addresses    : 192.168.100.0   - 192.168.100.255
   Action                        : interface
     Persistent NAT type         : N/A              
     Persistent NAT mapping type : address-port-mapping 
     Inactivity timeout          : 0
     Max session number          : 0
   Translation hits           : 10
     Successful sessions      : 10
     Failed sessions          : 0
   Number of sessions         : 0

That about covers the configuration of IPv4 <-> IPv6 NAT. Below is the full configuration from the NAT router for your reference. If you would like to download the configs – the links are below as well as the lab topology for EVE-NG if you want to lab it up yourself.

IPv4 Host Config
IPv6 Host Config
vSRX NAT Config
EVE-NG Lab

root@SRX-NAT> show configuration 
 Last commit: 2019-05-03 00:40:07 UTC by root
 version 17.3R1.10;
 system {
     host-name SRX-NAT;
     root-authentication {
         encrypted-password "postedatfryguy.net"; ## SECRET-DATA
     }
 }
 security {
     nat {
         source {
             rule-set IPV4-OUT {
                 from zone IPV4;
                 to zone IPV6;
                 rule IPV4-IPV6-NAT {
                     match {
                         source-address 192.168.100.0/24;
                         destination-address 2001:db8::0/64;
                     }
                     then {
                         source-nat {
                             interface;
                         }               
                     }
                 }
             }
             rule-set IPV6-OUT {
                 from zone IPV6;
                 to zone IPV4;
                 rule IPV6-IPV4-NAT {
                     match {
                         source-address 2001:db8::/64;
                         destination-address 192.168.100.0/24;
                     }
                     then {
                         source-nat {
                             interface;
                         }
                     }
                 }
             }
         }
         destination {
             pool IPv4-HOST {
                 address 192.168.100.2/32;
             }                           
             pool IPv6-HOST {
                 address 2001:db8::2/128;
             }
             rule-set IPV4-to-IPV6 {
                 from zone IPV4;
                 rule IPV4-NAT {
                     match {
                         destination-address 192.168.100.254/32;
                     }
                     then {
                         destination-nat {
                             pool {
                                 IPv6-HOST;
                             }
                         }
                     }
                 }
             }
             rule-set IPV6-to-IPV4 {
                 from zone IPV6;
                 rule IPV6-NAT {
                     match {
                         destination-address 2001:db8::254/128;
                     }
                     then {
                         destination-nat {
                             pool {
                                 IPv4-HOST;
                             }
                         }
                     }
                 }
             }
         }
         proxy-arp {
             interface ge-0/0/0.0 {
                 address {
                     192.168.100.254/32;
                 }
             }
         }
         proxy-ndp {
             interface ge-0/0/1.0 {
                 address {
                     2001:db8::254/128;
                 }                       
             }
         }
     }
     policies {
         global {
             policy PERMIT-ALL {
                 match {
                     source-address any;
                     destination-address any;
                     application any;
                     from-zone [ IPV4 IPV6 ];
                     to-zone [ IPV4 IPV6 ];
                 }
                 then {
                     permit;
                 }
             }
         }
     }
     zones {
         security-zone IPV4 {
             interfaces {
                 ge-0/0/0.0 {            
                     host-inbound-traffic {
                         system-services {
                             all;
                         }
                         protocols {
                             all;
                         }
                     }
                 }
             }
         }
         security-zone IPV6 {
             interfaces {
                 ge-0/0/1.0 {
                     host-inbound-traffic {
                         system-services {
                             all;
                         }
                         protocols {
                             all;
                         }
                     }
                 }                       
             }
         }
     }
 }
 interfaces {
     ge-0/0/0 {
         unit 0 {
             family inet {
                 address 192.168.100.1/24;
             }
         }
     }
     ge-0/0/1 {
         unit 0 {
             family inet6 {
                 address 2001:db8::1/64;
             }
         }
     }
 }

Cisco Live and Cisco Continuing Education Program

Well, the Cisco Live Scheduler is now open and there is one thing that I forgot to mention. If you are a CCIE, Cisco Live sessions can help you with your recertification by earning you CE credits via the Continuing Education Program. Here are some links to my Original post on the announcement and Review post when I recertified last time using CE credits.

By attending Cisco Live sessions you may be eligible to earn up to 70 credits out of the 100 required to recertify. Now not sure if it’s possible to earn that in one conference or would require a few, you can work out the math on that one based on your schedule.

Below is a table of the current (26-April-2019) credits per level as per the Cisco CEP website.

SessionLevelCredits
Technical Breakout10001
20002
30003
4-Hour Technical Seminar10003
20004
30005
8 Hour Technical Seminar10006
20008
300010
4-Hour Instructor-Led Lab10003
20004
30005
8-Hour Instructor-Led lab10006
20008
300010

If you have not registered yet, earning CE credits is a great reason to! See you there!

Cisco Live 2019 Testing Center

One of the awesome benefits of Cisco Live is the free Cisco Pearson Vue testing (testing center is sponsored once again by Global Knowledge) that takes place during the event. Normally in past years, the testing center has been located at the convention location, yet in recent years the testing center has been located not within the convention center.

It looks like this year is following the same trend for the testing location. The hours and location are:

Marriott Marquis Hotel
South Tower Level 3 / Marina Ballroom
(Next to the San Diego Convention Center)

Sunday, June 9 - 12 PM - 5 PM
Monday, June 10 - 7:30 AM - 7 PM
Tuesday, June 11 - 7:30 AM - 7 PM
Wednesday, June 12 - 8 AM - 6 PM (This is the night of the CAE)
Thursday, June 13 - 8 AM - 4 PM

Mapping it out from the furthest part of the convention center, it looks to be about a 10 to 15-minute walk – not too bad, but something you should at least plan for. Below is a Google map to help you.

Word of advice, try to avoid a late test on Wednesday so you have time to get to the CAE before it starts. Also, avoid an early test on Thursday as you will be tired from the CAE. I heard of many people missing their test due to over-sleeping or failing their Thursday test due to “not feeling well.”

If you are looking for the testing registration link, it was sent to your registered account with the information required. If you do not see it, make sure you selected or add the Certification Exam on your registration. It is a $0 item but has to be added to registration in order to receive the link.

Oh – and be sure to get your Global Knowledge socks after your test!

Again, there is still time to register if you have not – head on over to Cisco Live to register.