NAT64 DNS64
Problem this snippet solves:
Contributed by: nat at f5.com Last update: June 15, 2010 15:35PM (US Pacific Time)
This is a solution that allows client from IPv6 network to communicate to IPv4 network through BIG-IP. It actually contains 2 iRules:- NAT64 and DNS64 iRule (see iRule source section below).
Here is how it works:-
- Suppose IPv6 client is going to connect to www.f5.com which resides in IPv4 network
- First, IPv6 client performs DNS resolution. IPv6 client sends DNS AAAA query to BIG-IP.
- BIG-IP transforms AAAA to A query by DNS64 iRule
- BIG-IP forwards A query from previous step to DNS pool in IPv4 domain
- DNS server in IPv4 domain replies to BIG-IP
- BIG-IP performs appropriate transformation such as changing from A to AAAA query and changing IPv4 address to IPv6 address before forwarding DNS answer back to IPv6 client. BIG-IP uses fix 96-bit prefix address concatenate with 32-bit IPv4 address to form new dynamic IPv6 address. This steps is once again done by DNS64 iRule.
- Once IPv6 client gets the answer to AAAA query (as IPv6 destination address). It opens connection to the IPv6 destination address. Traffic to the IPv6 destination must be routed through BIG-IP
- BIG-IP receives IPv6 traffic from client, perform src and dst address translation, and forwards to IPv4 network. This step is done by NAT64 iRule.
Please be noted. This iRule is still in experimental stage and it may contains redundant routine. Any comment/feedback is welcome.
Code :
# virtual server configuration virtual dns64 { pool dns64 destination 2001:123::1.domain ip protocol udp rules dns64 } virtual nat64 { translate address enable snat automap destination 2002:123::.any mask ffff:ffff:ffff:ffff:ffff:ffff:: rules nat64 } # Pool for DNS server in IPv4 domain pool dns64 { members 172.27.4.209:domain {} } # NAT64 iRule when CLIENT_ACCEPTED { node [string range [IP::addr [IP::local_addr] mask ::ffff:ffff] 0 end] } # DNS64 iRule when RULE_INIT { set static::prefix "200201230000000000000000" } when CLIENT_DATA { binary scan [UDP::payload] SSSSSS id flags qdcount ancount nscount arcount # Total Header length = 12 bytes set index 12 # Question Section: it is usually 1 (qdcount=1), we may not need to loop here actually. # also assume no pointer (dns compression) here while { $qdcount > 0 } { binary scan [UDP::payload] @${index}c count while { $count != 0 } { incr index [expr $count + 1] binary scan [UDP::payload] @${index}c count } incr index binary scan [UDP::payload] @${index}SS qtype qclass # change to A record if { $qtype == 28 } { UDP::payload replace ${index} 2 [binary format S 1] } incr index 4 incr qdcount -1 } } when SERVER_DATA { binary scan [UDP::payload] SSSSSS id flags qdcount ancount nscount arcount # Total Header length = 12 bytes set index 12 # Question Section: it is usually 1 (qdcount=1), we may not need to loop here actually. while { $qdcount > 0 } { binary scan [UDP::payload] @${index}c count while { $count != 0 } { incr index [expr $count + 1] binary scan [UDP::payload] @${index}c count } incr index binary scan [UDP::payload] @${index}SS qtype qclass # change A(1) to AAAA(28) record if { $qtype == 1 } { UDP::payload replace ${index} 2 [binary format S 28] } incr index 4 incr qdcount -1 } # The Answer, Authority and Additional Sections while { $ancount > 0 || $nscount > 0 || $arcount > 0} { binary scan [UDP::payload] @${index}cc count pointer set loop 0 while { $count != 0 and $loop < 30 } { incr loop set pointer_prefix [expr ($count >> 6) & 0x3] set pointer_index [expr (($count &0x3f)<<8) | $pointer ] if { $pointer_prefix == 3 } { incr index 2 break } else { incr index [expr $count + 1] binary scan [UDP::payload] @${index}cc count pointer } } binary scan [UDP::payload] @${index}SSIS qtype qclass ttl rdlength incr index 10 if { $qtype == 1 } { # change A to AAAA record binary scan [UDP::payload] @${index}cccc a b c d # change length from 4 to 6 set rdlength 16 # change IPv4 to IPv6 UDP::payload replace [expr ${index} - 10] 14 [binary format SSISH24cccc 28 \ $qclass $ttl $rdlength $static::prefix $a $b $c $d] } incr index $rdlength if { $ancount > 0 } { incr ancount -1 } elseif { $nscount > 0 } { incr nscount -1 } else { incr arcount -1 } } }
Published Mar 18, 2015
Version 1.0Nat_Thirasuttakorn
Employee
Joined September 25, 2004
Nat_Thirasuttakorn
Employee
Joined September 25, 2004
No CommentsBe the first to comment