I would like to allow inbound IPv6 traffic on ports 80/443 for a globally routable web server on my home network. What's the best way to do this with OpenWrt, which by default blocks incoming IPv6 traffic (as a good firewall should)?

My ISP (Comcast) assigns me a /60 prefix for delegation via DHCPv6. It sometimes changes. The web server (Ubuntu) gets a global IPv6 address via SLAAC from the OpenWrt router.

As per https://wiki.openwrt.org/doc/uci/firewall#port_accept_for_ipv6 you can set up a traffic rule to allow this kind of traffic:

To open port 80 so that a local webserver at 2001:db8:42::1337 can be reached from the Internet:

config rule
        option src       wan
        option proto     tcp
        option dest      lan
        option dest_ip   2001:db8:42::1337
        option dest_port 80
        option family    ipv6
        option target    ACCEPT

Easy enough, except.... the destination IP is hard-coded!

How might one set up this type of rule when the destination IP is potentially changing? (due to changes in the delegated prefix from my ISP). Presumably, it has to be updated periodically.... Has anyone attempted this and if so, what works well / doesn't work well?


I encountered the same problem and dead end as you. I wrote a quick and dirty script to automate the firewall changes for me.


# the prefix is the prefix of all the firewall rules that should be changed

# get current IPv6 prefix from WAN
. /lib/functions/network.sh
network_get_prefix6 prefix6 wan6
prefix6=$(echo $prefix6 | cut -d/ -f1)
prefix_len=$(expr ${#prefix6} - 1)

name=$(uci get firewall.@rule[$index].name 2> /dev/null)
while [ "$name" != "" ]; do

    # if the prefix matches, determine whether to change the firewall rules
    if [ "$subname" == "$PREFIX" ]; then
            dest_ip=$(uci get firewall.@rule[$index].dest_ip 2> /dev/null)
            host_addr=$(echo $dest_ip | awk -F: 'BEGIN { OFS=":"; } { print $5,$6,$7,$8 }')

            # if the firewall rule and prefix mismatch, update the firewall
            if [ "$dest_network" != "$prefix6" ]; then
                    uci set firewall.@rule[$index].dest_ip=$new_ip
                    uci commit firewall

    # advance to the next firewall rule
    index=$(expr $index + 1)
    name=$(uci get firewall.@rule[$index].name 2> /dev/null)

# if changes were detected, then reload the firewall
if [ $changed -eq 1 ]; then
    /etc/init.d/firewall reload 2> /dev/null

To use the script:

  1. Create your firewall rules using the PREFIX in the script.
  2. Schedule the script to run using cron.

Known Issue: The script is limited to full IPv6 addresses and can't use the :: short hand. (e.g., 2600:dead:beef:cafe:0:0:0:1 instead of 2600:dead:beef:cafe::1).

The script is far from perfect, so be kind. I offer the script in hopes you will find it useful. :)

| improve this answer | |
  • For this answer to be useful, you should at least try and explain what the script does. Read it yourself answers are not very useful, on a Q&A site, and they are surely frowned up on StackExchange. – MariusMatutiae Jul 28 '16 at 11:47

Check out Dynamic Prefix Forwarding as it has a trick where you can use negative numbers for the prefix.

Configure a static DHCPv6 lease and add a forwarding rule:

uci add firewall rule
uci set firewall.@rule[-1].name="Forward-IPv6"
uci set firewall.@rule[-1].src="wan"
uci set firewall.@rule[-1].dest="lan"
uci set firewall.@rule[-1].dest_ip="::123/-64"
uci set firewall.@rule[-1].family="ipv6"
uci set firewall.@rule[-1].proto="tcpudp"
uci set firewall.@rule[-1].target="ACCEPT"
uci commit firewall
/etc/init.d/firewall restart
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.