How to use 464xlat in OpenWrt

I have already compiled the 464xlat module in my fw:

4950 CONFIG_PACKAGE_464xlat=y
4951 # CONFIG_PACKAGE_6in4 is not set
4952 # CONFIG_PACKAGE_6rd is not set
4953 CONFIG_PACKAGE_6to4=y

And I tried to use it to build a topology environment with WAN as IPv6 and LAN as IPv4, which is the key content of my configuration file:


config interface 'wan'
        option type 'bridge'
        option mtu '1500'
        option ipv6 '1'
        option disabled '0'
        option proto 'dhcp'
        option dnstype 'auto'
        option peerdns '1'
        option ifname 'eth0'

config interface 'wan6'
        option ifname 'br-wan'
        option proto 'dhcpv6'
        option dnstype 'auto'
        option auto_mtu '1'
        option mtu_v6 '64000'
        option PD_enable '1'
        option keepalive_enable '1'
        option keepalive '3 30'
        option redial '30'

config interface 'vlan1'
        option ifname 'eth1 eth2 '
        option force_link '1'
        option type 'bridge'
        option proto 'static'
        option ipaddr '192.168.250.1'
        option netmask '255.255.255.0'
        option ieee1905managed '1'
        option dhcp_mode 'Server'
        option ipv6 '0

config interface 'wan6_4'
        option proto '464xlat'
        option ip6prefix '2001:db8:85a3::/96'
        option ip6addr '2001:db8:85a3::2'
        option tunlink 'wan6'
        option zone 'wan'

When I run network restart, the log I added in the netifd-proto.sh script will prompt:

ubus -S call network.interface notify_proto { "action": 6, "host": "::", "ifname": "wan6", "interface": "wan6_4" }
ubus  call network.interface notify_proto { "action": 3, "error": [ "CLAT_CONFIG_FAILED" ], "interface": "wan6_4" }
Command failed: Not found
ubus  call network.interface notify_proto { "action": 4, "interface": "wan6_4" }
Command failed: Not found

This seems to indicate that my 464xlat has not been successfully configured, but I have not found a standard configuration example. Here are some of my parameter information, so who can help me answer my question? Thank you.


root@router:~# ifstatus wan
{
        "up": false,
        "pending": true,
        "available": true,
        "autostart": true,
        "dynamic": false,
        "proto": "dhcp",
        "device": "br-wan",
        "data": {

        }
}
root@router:~# ifstatus wan6
{
        "up": true,
        "pending": false,
        "available": true,
        "autostart": true,
        "dynamic": false,
        "uptime": 8802,
        "l3_device": "br-wan",
        "proto": "dhcpv6",
        "device": "br-wan",
        "metric": 0,
        "delegation": true,
        "ipv4-address": [

        ],
        "ipv6-address": [
                {
                        "address": "2001:db8:85a3::f7c4",
                        "mask": 128,
                        "preferred": 34396,
                        "valid": 34396
                }
        ],
        "ipv6-prefix": [

        ],
        "ipv6-prefix-assignment": [

        ],
        "route": [
                {
                        "target": "2001:db8:85a3::",
                        "mask": 64,
                        "nexthop": "::",
                        "metric": 256,
                        "valid": 43156,
                        "source": "::\/0"
                },
                {
                        "target": "::",
                        "mask": 0,
                        "nexthop": "fe80::163f:c3ff:fe00:1d1e",
                        "metric": 512,
                        "valid": 256,
                        "source": "2001:db8:85a3::f7c4\/128"
                }
        ],
        "dns-server": [
                "2001:db8:85a3::8a2e:370:7334",
                "2001:db8:85a3::8a2e:370:7334"
        ],
        "dns-search": [
                "router001d1e.com"
        ],
        "inactive": {
                "ipv4-address": [

                ],
                "ipv6-address": [

                ],
                "route": [

                ],
                "dns-server": [

                ],
                "dns-search": [

                ]
        },
        "data": {
                "passthru": "001800120c726f7574657230303164316503636f6d000017002020010db885a3000000008a2e0370733420010db885a3000000008a2e03707334"
        }
}
root@router:~# ifstatus wan6_4
Interface wan6_4 not found
root@router:~# 

It is designed to work without configuration (though apparently there are also ways to configure it directly). I just install the package and it starts up an interface named 464-wan6_4 automatically. It becomes the default v4 route. v4 packets sent there will be CLAT translated to v6 and routed out to the ISP.

For 464 to work there must be a DNS64 and a PLAT. Both of these are usually provided by the ISP though there are public DNS64. The 464 package detects the necessary prefix to reach the PLAT by looking up ipv4only.arpa which if an AAAA record exists it will have the prefix. Technically the DNS64 is only necessary for initial startup as once the CLAT is in place, legacy v4 only operation is possible.

Thanks, So are all operations simplified as netifd operations? Can you share your configuration file?

Yes there is a netifd script in the package (/lib/netifd/proto/464xlat.sh), which calls a userspace program 464xlatcfg which configures the kernel module kmod-nat46.

In its simplest installation there is no mention of 464 in the network config. The configuration file is not special. I have a wan6 interface which is v6 only and a dual-stack lan interface. Without any configuration, a 464 interface is started automatically and installed as the v4 default route (otherwise there would be no v4 default route as there is no v4 wan).

It generally works well but if the wan ipv6 address changes it will break. I think this is because kmod-nat46 uses a static source address (loaded at startup) instead of using whatever exists on the wan at the time.

Are you using the ISP as the other side of 464 or are you also building your own PLAT?

I applied the ISP to the other end of 464xlat, and on my device, the WAN only has IPv6 addresses, while the LAN remains pure IPv4. However, it seems that 464xlat has not started, so I am not sure if it is a configuration file issue.

Test the DNS64:
nslookup ipv4only.arpa
This should return both v4 and v6 records. The v4 is unimportant here. The first 96 bits of the v6 result are the prefix for outgoing 46, often the standard 64:ff9b:: but it could be some other prefix specific to the ISP.
There are probably ways to work around not having DNS64 by manually configuring the prefix but I'm not sure how. DNS64 is important to have in a 464 environment anyway as it makes v6 compatible endpoint applications able to reach the v4 legacy Internet "directly" as v6.

Then test the PLAT, using the prefix found above:
ping 64:ff9b::0101:0101
This makes a translated ping using the ISP's PLAT to the v4 IP 1.1.1.1. The pings should be answered as that is a Cloudflare server which answers pings.

These tests do not use the 464 CLAT so they won't tell if it is up. To test 464 itself, make a v4 ping to an Internet site. There isn't much visible status that 464 has started, other than the existence of a 464 interface and its inclusion into the v4 routing table.

1 Like

I modified the interface in the configuration file

config interface 'wan6_4'
        option proto '464xlat'
        option ifname 'br-wan'
        option ip6prefix '64:ff9b::/96'
        option ip6addr '2001:db8:aaaa::/96'
        option tunlink 'wan'
        option zone 'wan'

In the/lib/netifd/pro/464xlat.sh script, I found that ip6addd=$(464xlatcfg "$link" "$undev" "$ip6prefix" $ip6addr) is always empty, which prevents the interface from being created. Therefore, I added a delay. It seems that the interface has been created, but it is not working as I expected

root@router:/lib/netifd/proto# ifstatus wan6_4
{
        "up": true,
        "pending": false,
        "available": true,
        "autostart": true,
        "dynamic": false,
        "uptime": 2979,
        "l3_device": "464-wan6_4",
        "proto": "464xlat",
        "updated": [
                "routes",
                "data"
        ],
        "metric": 0,
        "delegation": true,
        "ipv4-address": [

        ],
        "ipv6-address": [

        ],
        "ipv6-prefix": [

        ],
        "ipv6-prefix-assignment": [

        ],
        "route": [
                {
                        "target": "240a:4281:fe00:3f42:d1f0:846d:eb24:5f6a",
                        "mask": 128,
                        "nexthop": "::",
                        "table": 128,
                        "source": "::\/0"
                },
                {
                        "target": "0.0.0.0",
                        "mask": 0,
                        "nexthop": "0.0.0.0",
                        "metric": 2048,
                        "source": "0.0.0.0\/0"
                }
        ],
        "dns-server": [

        ],
        "dns-search": [

        ],
        "inactive": {
                "ipv4-address": [

                ],
                "ipv6-address": [

                ],
                "route": [

                ],
                "dns-server": [

                ],
                "dns-search": [

                ]
        },
        "data": {
                "firewall": [
                        {
                                "type": "nat",
                                "target": "SNAT",
                                "family": "inet",
                                "snat_ip": "192.0.0.1"
                        },
                        {
                                "type": "rule",
                                "family": "inet6",
                                "proto": "all",
                                "direction": "in",
                                "dest": "wan",
                                "src": "wan",
                                "src_ip": "240a:4281:fe00:3f42:d1f0:846d:eb24:5f6a",
                                "target": "ACCEPT"
                        },
                        {
                                "type": "rule",
                                "family": "inet6",
                                "proto": "all",
                                "direction": "out",
                                "dest": "wan",
                                "src": "wan",
                                "dest_ip": "240a:4281:fe00:3f42:d1f0:846d:eb24:5f6a",
                                "target": "ACCEPT"
                        }
                ],
                "zone": "wan"
        }
}
root@router:/lib/netifd/proto# ifconfig 
464-wan6_4 Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          UP POINTOPOINT RUNNING NOARP  MTU:16384  Metric:1
          RX packets:12658 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:890778 (869.9 KiB)  TX bytes:0 (0.0 B)

If I access the network on a LAN device, there will be a log:

[ 6818.569614] [nat46] Could not translate v4->v6
[ 6818.576100] [nat46] Could not translate v4->v6

So I think my problem may not be with DNS64, because the current device 464 has not been successfully created, it should be related to the 464xlat.sh script. According to the debug log I added, it actually has many errors on my device:

root@router:/lib/netifd/proto# cat 464xlat.sh 
#!/bin/sh
# 464xlat.sh - 464xlat CLAT
#
# Copyright (c) 2015 Steven Barth <cyrus@openwrt.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

[ -n "$INCLUDE_ONLY" ] || {
    echo "$@" > /dev/console
    . /lib/functions.sh
    . /lib/functions/network.sh
    . ../netifd-proto.sh
    init_proto "$@"
}
echo "[DEBUG] all par:  $@" > /dev/console

proto_464xlat_setup() {
    echo "[DEBUG] proto_464xlat_setup: $@" > /dev/console
    local cfg="$1"
    local iface="$2"
    local link="464-$cfg"

    echo "[DEBUG] Starting proto_464xlat_setup" > /dev/console
    echo "[DEBUG] cfg: $cfg, iface: $iface, link: $link" > /dev/console

    local ip6addr ip6prefix tunlink zone
    json_get_vars ip6addr ip6prefix tunlink zone

    echo "[DEBUG] Parsed JSON variables:" > /dev/console
    echo "[DEBUG] ip6addr: $ip6addr, ip6prefix: $ip6prefix, tunlink: $tunlink, zone: $zone" > /dev/console

    [ -z "$zone" ] && zone="wan"
    echo "[DEBUG] Zone set to: $zone" > /dev/console

    ( proto_add_host_dependency "$cfg" "::" "$tunlink" )
    echo "[DEBUG] Added host dependency for cfg: $cfg, tunlink: $tunlink" > /dev/console

    if [ -z "$tunlink" ] && ! network_find_wan6 tunlink; then
        echo "[ERROR] No WAN6 link found" > /dev/console
        proto_notify_error "$cfg" "NO_WAN_LINK"
        return
    fi
    echo "[DEBUG] tunlink: $tunlink" > /dev/console

    network_get_device tundev "$tunlink"
    # tundev=$(uci get network.wan6_4.tunlink)

    echo "[DEBUG] tundev: $tundev" > /dev/console
    sleep 10
    echo "cmd=464xlatcfg "$link" "$tundev" "$ip6prefix" $ip6addr" >> /tmp/464xlatcfg.log
    #ip6addr=$(464xlatcfg "$link" "$tundev" "$ip6prefix" 192.0.0.1 $ip6addr)
    ip6addr=$(464xlatcfg "$link" "$tundev" "$ip6prefix" $ip6addr)
    echo "ret=$?, ip6addr=$ip6addr" >> /tmp/464xlatcfg.log
    echo "[DEBUG] ip6addr after 464xlatcfg: $ip6addr" > /dev/console

    if [ -z "$ip6addr" ]; then
        echo "[ERROR] CLAT configuration failed" > /dev/console
        proto_notify_error "$cfg" "CLAT_CONFIG_FAILED"
        proto_block_restart "$cfg"
        return
    fi

    proto_init_update "$link" 1
    echo "[DEBUG] Initialized proto update for link: $link" > /dev/console

    proto_add_ipv4_route "0.0.0.0" 0 "" "" 2048
    echo "[DEBUG] Added IPv4 route" > /dev/console

    proto_add_ipv6_route $ip6addr 128 "" "" "" "" 128
    echo "[DEBUG] Added IPv6 route for ip6addr: $ip6addr" > /dev/console

    proto_add_data
    echo "[DEBUG] Adding data to proto" > /dev/console

    [ "$zone" != "-" ] && json_add_string zone "$zone"
    echo "[DEBUG] Added zone: $zone" > /dev/console

    json_add_array firewall
        json_add_object ""
            json_add_string type nat
            json_add_string target SNAT
            json_add_string family inet
            json_add_string snat_ip 192.0.0.1
        json_close_object
        echo "[DEBUG] Added NAT firewall rule" > /dev/console

        json_add_object ""
            json_add_string type rule
            json_add_string family inet6
            json_add_string proto all
            json_add_string direction in
            json_add_string dest "$zone"
            json_add_string src "$zone"
            json_add_string src_ip $ip6addr
            json_add_string target ACCEPT
        json_close_object
        echo "[DEBUG] Added IPv6 inbound rule" > /dev/console

        json_add_object ""
            json_add_string type rule
            json_add_string family inet6
            json_add_string proto all
            json_add_string direction out
            json_add_string dest "$zone"
            json_add_string src "$zone"
            json_add_string dest_ip $ip6addr
            json_add_string target ACCEPT
        json_close_object
        echo "[DEBUG] Added IPv6 outbound rule" > /dev/console
    json_close_array

    proto_close_data
    echo "[DEBUG] Closed proto data" > /dev/console

    proto_send_update "$cfg"
    echo "[DEBUG] Sent proto update for cfg: $cfg" > /dev/console
}

proto_464xlat_teardown() {
    echo "[DEBUG] Tearing down 464xlat for cfg: $1" > /dev/console
    464xlatcfg "464-$1"
}

proto_464xlat_init_config() {
    echo "[DEBUG] Initializing 464xlat config" > /dev/console
    no_device=1
    available=1

    proto_config_add_string "ip6prefix"
    proto_config_add_string "ip6addr"
    proto_config_add_string "tunlink"
    proto_config_add_string "zone"
}

[ -n "$INCLUDE_ONLY" ] || {
    echo "[DEBUG] Adding protocol 464xlat" > /dev/console
    add_protocol 464xlat
}

Restart network log:

root@router:/lib/netifd/proto# /etc/init.d/network restart
[ 5137.215511] br-vlan1: port 1(eth1) entered disabled state
[ 5137.223026] IPv6: ADDRCONF(NETDEV_UP): br-vlan1: link is not ready
[ 5137.223056] IPv6: force enable br-vlan1 ipv6
[ 5137.228871] device eth1 left promiscuous mode
[ 5137.232975] br-vlan1: port 1(eth1) entered disabled state
[ 5137.245951] IPv6: ADDRCONF(NETDEV_UP): eth1: link is not ready
[ 5137.246387] device eth2 left promiscuous mode
[ 5137.250851] br-vlan1: port 2(eth2) entered disabled state
[ 5137.264370] IPv6: ADDRCONF(NETDEV_UP): eth2: link is not ready
[ 5137.369764] br-wan: port 1(eth0) entered disabled state
[ 5137.377214] IPv6: ADDRCONF(NETDEV_UP): br-wan: link is not ready
[ 5137.377357] device eth0 left promiscuous mode
[ 5137.382486] br-wan: port 1(eth0) entered disabled state
[ 5137.394279] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
[DEBUG] all par:   dump
[DEBUG] Adding protocol 464xlat
[DEBUG] Initializing 464xlat config
[ 5140.924971] device eth1 entered promiscuous mode
[ 5141.132211] device eth2 entered promiscuous mode
[ 5141.338585] device eth0 entered promiscuous mode
[ 5141.339904] IPv6: ADDRCONF(NETDEV_UP): br-wan: link is not ready
464xlat setup wan6_4 {"proto":"464xlat","ifname":"br-wan","ip6prefix":"2001:db8:85a3::\/96","ip6addr":"2001:db8:85a3::2","tunlink":"wan","zone":"wan"}
[DEBUG] all par:  464xlat setup wan6_4 {"proto":"464xlat","ifname":"br-wan","ip6prefix":"2001:db8:85a3::\/96","ip6addr":"2001:db8:85a3::2","tunlink":"wan","zone":"wan"}
[DEBUG] Adding protocol 464xlat
[DEBUG] proto_464xlat_setup: wan6_4 
[DEBUG] Starting proto_464xlat_setup
[DEBUG] cfg: wan6_4, iface: , link: 464-wan6_4
[DEBUG] Parsed JSON variables:
[DEBUG] ip6addr: 2001:db8:85a3::2, ip6prefix: 2001:db8:85a3::/96, tunlink: wan, zone: wan
[DEBUG] Zone set to: wan
464xlat teardown wan6_4 {"proto":"464xlat","ifname":"br-wan","ip6prefix":"2001:db8:85a3::\/96","ip6addr":"2001:db8:85a3::2","tunlink":"wan","zone":"wan"}
[DEBUG] all par:  464xlat teardown wan6_4 {"proto":"464xlat","ifname":"br-wan","ip6prefix":"2001:db8:85a3::\/96","ip6addr":"2001:db8:85a3::2","tunlink":"wan","zone":"wan"}
[DEBUG] Adding protocol 464xlat
[DEBUG] Tearing down 464xlat for cfg: wan6_4
[ 5143.954614] br-vlan1: port 1(eth1) entered forwarding state
[ 5143.959312] br-vlan1: port 1(eth1) entered forwarding state
[ 5145.694581] br-wan: port 1(eth0) entered forwarding state
[ 5145.699276] br-wan: port 1(eth0) entered forwarding state
[ 5145.710029] IPv6: ADDRCONF(NETDEV_CHANGE): br-wan: link becomes ready
proto_dhcpv6_setup: wan br-wan
[ 5145.954458] br-vlan1: port 1(eth1) entered forwarding state
[ 5147.694462] br-wan: port 1(eth0) entered forwarding state```