Maybe you are interested in giving NAT64 a try which has been committed to the tree a few weeks ago. In my first test I found it works great. Thanks to the developers for their hard work!
Eventually, the following sample config saves you some time while the man pages are in the works, although looking through the commit logs, source code, and conference presentations is always educational. Note that NAT64 is not in 5.0-release, but you need a snapshot which is not older than three weeks or so. The following line in /etc/pf.conf is all which is required to setup a "stateful NAT64" on an OpenBSD box which has one interface in an IPv6 segment, and another interface in an IPv4 segment (private LAN, or even the Internet): pass in log on vic1 inet6 from any to 64:ff9b::/96 \ af-to inet from 192.168.98.74 For my test, I installed OpenBSD i386 snapshot from 3 Nov 11 on ESXi 4.1u1. vic1 is the "inside" interface on a vSwitch that accomodate IPv6 hosts exclusively. The "outside" interface vic0 is in IPv4-only segment and has the IP address 192.168.98.74. The above pf rule translates all ingress IPv6 traffic on vic1, which wants to go to destinations with the special prefix 64:ff9b::/96, to IPv4 with the source (NAT64) address of the outer interface vic0 ingress. pf implicitly takes the IPv4 destination (NAT64) from the lower 32 bits of the IPv6 destination address. This rule creates state, therefore return traffic is translated implicitly, e.g. you should not add any rule for return traffic. I derived this rule from Claudio@'s example in the commit log, which translates from v4 to v6, and where Claudio mentioned that the trailing "to" is optional for NAT64 http://marc.info/?l=openbsd-cvs&m=131853093528864 Besides testing a separate commercial virtual IPAM/DNS appliance from Infoblox to provide DNS64 Application Level Gateway functionality, I have also successfully tested the "totd" DNS proxy which provides similar DNS64 functionality (less DNS resolver and caching). OpenBSD has a package for "totd", so just do "pkg_add totd". As time allows, I might move the virtual NAT64 and DNS64 gateway over to an ALIX board. This portable demonstrator shall eventually gateway IPv6-only clients on its wireless LAN IPv6-only interface to IPv4-only Internet over 3G/UMTS - just for a fun alternative to v6 over v4 tunnels... Regards, Rolf A) /etc/totd.conf : interfaces vic1 #port 53 forwarder 192.168.99.26 prefix 64:ff9b:: retry 300 B) DNS lookup for AAAA resource records of google.com using the DNS64 proxy yields answers with the 64:ff9b::/96 prefix: [root@v6client:etc]# dig @2001:db8:123:64::1 google.com aaaa ; <<>> DiG 9.4.2-P2 <<>> @2001:db8:123:64::1 google.com aaaa ; (1 server found) ;; global options: printcmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30572 ;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 4, ADDITIONAL: 0 ;; QUESTION SECTION: ;google.com. IN AAAA ;; ANSWER SECTION: google.com. 300 IN AAAA 64:ff9b::d155:9468 google.com. 300 IN AAAA 64:ff9b::d155:9467 google.com. 300 IN AAAA 64:ff9b::d155:9469 google.com. 300 IN AAAA 64:ff9b::d155:9493 google.com. 300 IN AAAA 64:ff9b::d155:946a google.com. 300 IN AAAA 64:ff9b::d155:9463 ;; AUTHORITY SECTION: google.com. 8019 IN NS ns3.google.com. google.com. 8019 IN NS ns1.google.com. google.com. 8019 IN NS ns4.google.com. google.com. 8019 IN NS ns2.google.com. ;; Query time: 71 msec ;; SERVER: 2001:db8:123:64::1#53(2001:db8:123:64::1) ;; WHEN: Sun Nov 6 13:25:08 2011 ;; MSG SIZE rcvd: 308 C) ping6 from IPv6-only client to google.com on the IPv4 Internet via the NAT64 gateway works: [root@v6client:etc]# ping6 64:ff9b::d155:9469 PING6(56=40+8+8 bytes) 2001:db8:123:64:20c:29ff:feaf:ad2f --> 64:ff9b::d155:9469 16 bytes from 64:ff9b::d155:9469, icmp_seq=0 hlim=55 time=23.094 ms 16 bytes from 64:ff9b::d155:9469, icmp_seq=1 hlim=55 time=22.825 ms 16 bytes from 64:ff9b::d155:9469, icmp_seq=2 hlim=55 time=22.762 ms ^C --- 64:ff9b::d155:9469 ping6 statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/std-dev = 22.762/22.894/23.094/0.144 ms [root@v64gate:~]# tcpdump -i vic1 -nv icmp6 tcpdump: listening on vic1, link-type EN10MB 14:49:05.583129 2001:db8:123:64:20c:29ff:feaf:ad2f > 64:ff9b::d155:9469: icmp6: echo request (id:7397 seq:0) (len 16, hlim 64) 14:49:05.605904 64:ff9b::d155:9469 > 2001:db8:123:64:20c:29ff:feaf:ad2f: icmp6: echo reply (id:7397 seq:0) (len 16, hlim 55) 14:49:06.589012 2001:db8:123:64:20c:29ff:feaf:ad2f > 64:ff9b::d155:9469: icmp6: echo request (id:7397 seq:1) (len 16, hlim 64) 14:49:06.611583 64:ff9b::d155:9469 > 2001:db8:123:64:20c:29ff:feaf:ad2f: icmp6: echo reply (id:7397 seq:1) (len 16, hlim 55) 14:49:07.588874 2001:db8:123:64:20c:29ff:feaf:ad2f > 64:ff9b::d155:9469: icmp6: echo request (id:7397 seq:2) (len 16, hlim 64) 14:49:07.611396 64:ff9b::d155:9469 > 2001:db8:123:64:20c:29ff:feaf:ad2f: icmp6: echo reply (id:7397 seq:2) (len 16, hlim 55) ^C 7 packets received by filter 0 packets dropped by kernel [root@v64gate:etc]# tcpdump -i vic0 -nv icmp tcpdump: listening on vic0, link-type EN10MB 14:49:05.583206 192.168.98.74 > 209.85.148.105: icmp: echo request (id:7397 seq:0) (DF) (ttl 64, id 14066, len 36) 14:49:05.605850 209.85.148.105 > 192.168.98.74: icmp: echo reply (id:7397 seq:0) (ttl 55, id 60291, len 36) 14:49:06.589070 192.168.98.74 > 209.85.148.105: icmp: echo request (id:7397 seq:1) (DF) (ttl 64, id 45487, len 36) 14:49:06.611531 209.85.148.105 > 192.168.98.74: icmp: echo reply (id:7397 seq:1) (ttl 55, id 60292, len 36) 14:49:07.588931 192.168.98.74 > 209.85.148.105: icmp: echo request (id:7397 seq:2) (DF) (ttl 64, id 65475, len 36) 14:49:07.611349 209.85.148.105 > 192.168.98.74: icmp: echo reply (id:7397 seq:2) (ttl 55, id 60293, len 36) ^C 64 packets received by filter 0 packets dropped by kernel [root@v64gate:etc]# pfctl -ss -v ... all ipv6-icmp 192.168.98.74:5883 (2001:db8:123:64:20c:29ff:feaf:ad2f[5883]) -> 209.85.148.105:8 (64:ff9b::d155:9469[5883]) 0:0 age 00:01:56, expires in 00:00:10, 171421:0 pkts, 7886196:0 bytes, rule 2 ...

