GL-MT6000 WireGuard Server IPv6 support not working

Hi everyone,

I bought a MT6000 and want to use is at a VPN server providing both IPv4 and IPv6 connectivity among other things. As a disclaimer I'm using the latest stable firmware 4.5.8 and not a preview firmware.

After enabling the IPv6 support on the router, I was happy to notice that the WireGuard Server got assigned IPv6 addresses from fd00:db8:0:abc::/64 subnet in addition to the usual 10.0.0.0/24. What puzzled me quite a bit was that there were no IPv6 packets going through the tunnel even though the configuration all seemed good and the client had the ::/0 route automatically set to their peer configs as well.

Upon further investigation, it turned out that the AllowedIPs section in /tmp/wireguard/wgserver only had the IP address (e.g. 10.0.0.2) included in it and no IPv6 address, meaning all IPv6 packets were blocked on the router. I fixed this using wg set wgserver peer <publicKey> allowed-ips 10.0.0.2,fd00:db8:0:abc::2 and the packets started going through, but even though I had both Remote Access LAN and IP Masquerading enabled in the WireGuard Server Options, I could not access either LAN or WAN from the WireGuard tunnel. I did extensive research on this forum and also reading through the scripts on the router, but couldn't find any documentation, so posting everything I know here in case it's useful for others as well.

I found out that the first issue with the allowed-ips not including the IPv6 address was related to /lib/netifd/proto/wgserver.sh script discarding all IP addresses except for the first one. The config /etc/config/wireguard_server correctly includes option client_ip '10.0.0.2/24,fd00:db8:0:abc::2/64' with both addresses, but /lib/netifd/proto/wgserver.sh line echo "AllowedIPs=${client_ip%%/*}" >> "${wg_cfg}" effectively truncates it into 10.0.0.2.

Related to the masquerading problem, it seems like the problem is in the firewall, particularly in the /etc/firewall.nat6 script. I see it has a special handling for the guest zone in handle_guest_zone function that marks the packets in PREROUTING of the mangle table and then masquerades them in the zone_wan_postrouting chain based on the mark, to allow IPv6 masquerading. I don't even use the guest zone, but I feel something similar should be done for the wgserver, I tried adding a simple ip6tables -t mangle -I PREROUTING -i wgserver -j MARK --set-xmark 0xaa/0xaa entry for the wgserver zone, effectively treating it as a guest zone and all my problems were resolved.

I can send some sample scripts that worked for me in this topic, but I'd like to ask if this is a known issue and if there's a better fix available?

Replying to myself here, but just after posting the original topic, I found the real issue with the /etc/firewall.nat6 script.

Edit: Removed some incorrect information from here, I thought I found an issue with firewall.nat6, but it turns out I was wrong and had just lost track of my own changes. The original message still stands that I've ended up fixing this locally by running the guest network setup for the wgserver zone/interface as well.

@Bruce Could you please check and file to R&D if it's a bug?

2 Likes

Thanks admon and juhovh, notified with R&D

1 Like

Thanks for a super quick response, really appreciate it!

For the first AllowedIPs problem I ended up with going with something like:

        local ip_cidr allowed_ips IFS=","                                                                                   
        for ip_cidr in $client_ip; do                              
                allowed_ips="${allowed_ips:+$allowed_ips,}${ip_cidr%%/*}"                                                    
                config_foreach detect_route_allowed route_rules ${ip_cidr%%/*}  
        done                                                                  
        echo "AllowedIPs=${allowed_ips}" >> "${wg_cfg}"                       

in the load_peers() function of /lib/netifd/proto/wgserver.sh. It's a bit verbose, but does the job and creates a fairly tidy AllowedIPs configuration for me. I might have to reset my router to double-check, but I believe moving the return inside the if and adding the following loop have fixed both issues now for me. I'm mainly just worried things will get mixed up on firmware upgrades.

2 Likes

R&D team have confirmed it, we will check it out and fix it soon. Thank you juhovh in advance.

2 Likes

Thanks Bruce for the updates! Honestly, this customer support experience is making me more likely to recommend GL.iNet products to my friends and family. Hope you find an elegant solution to the NAT6 problem as well, ideally it would route to both WAN and LAN interfaces.

Thanks. May I know any suggestions could you share with us to improve the IPv6 NAT6?

Hey Bruce, sorry for a slow reply, I just wanted to verify that everything works as I expected before posting.

What I personally did was just modify the handle_guest_zone() function of /etc/firewall.nat6 to instead of using hardcoded br-guest interface name instead allow a configurable interface as follows:

handle_guest_zone() {
    zone_name="wan"

    local iface="$1"
    if ! ip6tables -t mangle -C PREROUTING -i "$iface" -j MARK --set-xmark 0xaa/0xaa &>/dev/null; then
        ip6tables -t mangle -I PREROUTING -i "$iface" -j MARK --set-xmark 0xaa/0xaa
    fi

    local postrouting_chain="zone_${zone_name}_postrouting"
    ip6t_add "$postrouting_chain" -t nat \
        -m mark --mark 0xaa/0xaa -m comment --comment "!fw3" -j MASQUERADE

    local input_chain="zone_${zone_name}_input"
    ip6t_add "$input_chain" -t filter -m conntrack --ctstate DNAT \
        -m comment --comment "!fw3: Accept port forwards" -j ACCEPT

    local forward_chain="zone_${zone_name}_forward"
    ip6t_add "$forward_chain" -t filter -m conntrack --ctstate DNAT \
        -m comment --comment "!fw3: Accept port forwards" -j ACCEPT
}

and then in the handle_zone() call it for both guest and wgserver:

    if [ "$(uci -q get glipv6.lan.mode)" == "native" -o "$(uci -q get glipv6.lan.mode)" == "relay" ];then
        if [ "$zone_name" == "guest" ];then
            handle_guest_zone "br-guest"
        fi
        if [ "$zone_name" == "wgserver" ];then
            handle_guest_zone "wgserver"
        fi
        return
    fi

but I'm still not quite certain if this is the best solution. However, if I try to connect to WAN it works just fine, and if I try to connect to LAN it's connecting from the fd00:db8:0:abc::2 address just like it's connecting from the 10.0.0.2/24 when using IPv4. I also have the guest network enabled and haven't seen anything weird there.

Hi, this task now is in the plan of the R&D, and schedule to debug soon, R&D colleague will reply when the issue resolved.

1 Like