on 18-Mar-2015 12:59
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:-
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 } } }