From 85f07cca35dc73b34902a5568f140dc00f028772 Mon Sep 17 00:00:00 2001 From: Miguel Scapolla Date: Thu, 29 Mar 2018 15:30:00 -0300 Subject: [PATCH] IPv6 Dynamic Prefix Delegation and firewall rules in Mikrotik. --- ...amic-prefix-delegation-update-firewall.txt | 688 ++++++++++++++++++ 1 file changed, 688 insertions(+) create mode 100644 mikrotik/mikrotik-ipv6-dynamic-prefix-delegation-update-firewall.txt diff --git a/mikrotik/mikrotik-ipv6-dynamic-prefix-delegation-update-firewall.txt b/mikrotik/mikrotik-ipv6-dynamic-prefix-delegation-update-firewall.txt new file mode 100644 index 0000000..6a8e0a8 --- /dev/null +++ b/mikrotik/mikrotik-ipv6-dynamic-prefix-delegation-update-firewall.txt @@ -0,0 +1,688 @@ +Mikrotik - Dynamic IPv6 prefix delegation - Update firewall rules +------------------------------------------------------------------ + +### Introduction +----------------- + +This text explains how to configure a Mikrotik router as IPv6 DHCP client in +the WAN interface to fetch a dynamic prefix via Prefix Delegation (PD), and +redistribute it on the LAN(s) interface(s) via Stateless Address +Autoconfiguration (SLAAC). + +Because the IPv6 prefix received for the LAN network is dynamic and can change +in each refresh, there are a script that reconfigure the dst-address in the +IPv6 firewall filter rules every time the prefix changes. This firewall rules +permit (or block) specific traffic to the servers in the LAN network. + +Also, the configuration includes the IPv4 section (DHCP client in the WAN, +and DHCP server in the LAN) for a dual stack network and miscellaneous +configuration. + +This configuration is used typically in a home environment with a cablemodem +internet service provider wich support prefix delegation. + + +### Requirements +----------------- + +* Every LAN network will have a prefix length of 64 (/64 netmask) automatically. + The script not work or have undesirable side effects with others prefix + lengths. + +* Every LAN network must have a only one IPv6 address obtained from a + delegated prefix. You can set a one or more fixed secondary IPv6 address, + but no other obtained from a pool. + +* Every IPv6 firewall filter rule must have the out-interface name configured. + The out-interface name is used to identify the rules to be changed and to + identify which new IPv6 prefix is used. If you need a fixed rule with no + dst-address change, leave the out-interface unconfigured. + +* Tested and working in Mikrotik RouterOS 6.41.3. + + +### Configuration +------------------ + +# +# This configuration is an example. Feel free to make changes based on your +# needs. This example uses a one WAN interface to the cablemodem ISP and +# two LAN interfaces to the PCs and servers. +# + +# +# Names of the interfaces. +# +/interface ethernet +set [ find default-name=ether1 ] name=LAN1 +set [ find default-name=ether2 ] name=LAN2 +set [ find default-name=ether3 ] name=WAN + +# +# Pools for the IPv4 DHCP server. +# +# The IPv4 DHCP server leases the IP from this pools. +# +/ip pool +add name=POOL1 ranges=10.10.10.64/26 +add name=POOL2 ranges=10.20.20.64/26 + +# +# IPv4 DHCP servers for LANs. +# +/ip dhcp-server +add address-pool=POOL1 disabled=no interface=LAN1 lease-time=2h name=DHCP1 +add address-pool=POOL2 disabled=no interface=LAN2 lease-time=2h name=DHCP2 + +# +# Options for the IPv4 DHCP server. +# +/ip dhcp-server network +add address=10.10.10.0/24 dns-server=10.10.10.1 domain=DOMAIN1.MM gateway=10.10.10.1 netmask=24 ntp-server=10.10.10.1 +add address=10.20.20.0/24 dns-server=10.20.20.1 domain=DOMAIN2.MM gateway=10.20.20.1 netmask=24 ntp-server=10.20.20.1 + +# +# Store leases for the IPv4 DHCP server. +# +/ip dhcp-server config +set store-leases-disk=never + +# +# IPv4 address of the LAN interfaces. +# +/ip address +add address=10.10.10.1/24 interface=LAN1 +add address=10.20.20.1/24 interface=LAN2 + +# +# IPv4 DHCP client in the WAN. +# +/ip dhcp-client +add dhcp-options=clientid,hostname disabled=no interface=WAN + +# +# DNS relay. +# +/ip dns +set allow-remote-requests=yes cache-max-ttl=10m cache-size=4096KiB query-total-timeout=4s + +# +# IPv4 bogon (martians) prefixes. +# +# The bogon or martians prefix are prefix no routeables +# or not used in internet. +# +/ip firewall address-list +add address=0.0.0.0/8 list=BOGONv4 +add address=10.0.0.0/8 list=BOGONv4 +add address=100.64.0.0/10 list=BOGONv4 +add address=127.0.0.0/8 list=BOGONv4 +add address=169.254.0.0/16 list=BOGONv4 +add address=172.16.0.0/12 list=BOGONv4 +add address=192.0.0.0/24 list=BOGONv4 +add address=192.0.2.0/24 list=BOGONv4 +add address=192.168.0.0/16 list=BOGONv4 +add address=198.18.0.0/15 list=BOGONv4 +add address=198.51.100.0/24 list=BOGONv4 +add address=203.0.113.0/24 list=BOGONv4 +add address=224.0.0.0/3 list=BOGONv4 + +# +# IPv4 firewall rules: input. +# +# Traffic destined to the router. +# +/ip firewall filter +add action=accept chain=input connection-state=established,related +add action=accept chain=input in-interface=LAN1 +add action=accept chain=input in-interface=LAN2 +add action=drop chain=input in-interface=WAN src-address-list=BOGONv4 +add action=accept chain=input in-interface=WAN dst-port= protocol=tcp <...> +add action=accept chain=input in-interface=WAN dst-port= protocol=udp <...> +add +add action=drop chain=input + +# +# IPv4 firewall rules: forward. +# +# Traffic wich pass through the router. +# +/ip firewall filter +add action=accept chain=forward connection-state=established,related +add action=accept chain=forward in-interface=LAN1 +add action=accept chain=forward in-interface=LAN2 +add action=drop chain=forward in-interface=WAN src-address-list=BOGONv4 +add action=accept chain=forward dst-address= dst-port= in-interface=WAN protocol=tcp <...> +add action=accept chain=forward dst-address= dst-port= in-interface=WAN protocol=udp <...> +add +add action=drop chain=forward + +# +# IPv4 port forward. +# +# Maps the external ports with the internal IPv4 address +# and ports. +# +/ip firewall nat +add action=dst-nat chain=dstnat dst-address-type=local dst-port= protocol=tcp to-addresses= to-ports= +add action=dst-nat chain=dstnat dst-address-type=local dst-port= protocol=udp to-addresses= to-ports= +add + +# +# IPv4 dynamic source NAT. +# +/ip firewall nat +add action=masquerade chain=srcnat out-interface=WAN + +# +# IPv6 address of the LAN interfaces. +# +# The network part of the IPv6 address (prefix) is taken from the pool +# (POOL6) obtained with prefix delegation. The host part of the IPv6 +# address is configured manually. +# +# In this example, the host part of the IPv6 address of the interfaces +# is ::1. The netmask it will be /64 automatically from the pool. +# +/ipv6 address +add address=::1 from-pool=POOL6 interface=LAN1 +add address=::1 from-pool=POOL6 interface=LAN2 + +# +# IPv6 DHCP client in the WAN interface. +# +# The DHCP client request an IPv6 address for the WAN interface and an IPv6 +# prefix for the pool POOL6. The IPv6 default route is created in the routing +# table and the FW6RULES script is executed when the bind expires and the +# DHCP client obtains another IPv6 prefix for the pool. The FW6RULES script +# update the IPv6 firewall filter rules to the new dst-address. +# +/ipv6 dhcp-client +add add-default-route=yes interface=WAN pool-name=POOL6 request=address,prefix script=FW6RULES + +# +# IPv6 bogon (martians) prefixes. +# +# The bogon or martians prefix are prefix no routeables +# or not used in internet. This list is a brief summary +# of the complete list: https://bit.ly/2uxN3G8 and +# https://bit.ly/2IZy2QN +# +/ipv6 firewall address-list +add address=::/3 list=BOGONv6 +add address=4000::/2 list=BOGONv6 +add address=8000::/2 list=BOGONv6 +add address=c000::/3 list=BOGONv6 +add address=e000::/4 list=BOGONv6 +add address=f000::/5 list=BOGONv6 +add address=f800::/6 list=BOGONv6 +add address=fc00::/7 list=BOGONv6 +add address=fe00::/9 list=BOGONv6 +add address=fec0::/10 list=BOGONv6 +add address=ff00::/8 list=BOGONv6 + +# +# IPv6 firewall rules: input. +# +# Traffic destined to the router. +# +# The ICMP and UDP traffic from and to fe80::/10 and ff02::/16 are used by +# the IPv6 DHCP client to obtain the address and prefix delegation. +# +/ipv6 firewall filter +add action=accept chain=input connection-state=established,related +add action=accept chain=input dst-address=fe80::/10 in-interface=WAN protocol=icmpv6 src-address=fe80::/10 +add action=accept chain=input dst-address=ff02::/16 in-interface=WAN protocol=icmpv6 src-address=fe80::/10 +add action=accept chain=input dst-address=fe80::/10 dst-port=546 in-interface=WAN protocol=udp src-address=fe80::/10 +add action=accept chain=input in-interface=LAN1 +add action=accept chain=input in-interface=LAN2 +add action=drop chain=input in-interface=WAN src-address-list=BOGONv6 +add +add action=drop chain=input + +# +# IPv6 firewall rules: forward. +# +# Traffic wich pass through the router. +# +# In the out-interface of every rule you must configure the correct LAN +# interface. This field is used by the script to identify the rule, the +# out interface, and the new IPv6 prefix of the interface when changes. +# +# The dst-address in the rule is the host part and mask of the IPv6 address +# of the internal servers. Initially you can set the full IPv6 address (actual +# prefix /64 + host part /64) and mask or only the host part (/64) and mask. +# Later, the FW6RULES script changes the dst-address of the rule to the right +# full IPv6 address. +# +# The host part of the IPv6 address in the server must be fixed to the same +# value configured in the firewall rule. This value must be the same across +# the server restarts. In the server, you must disable IPv6 privacy extension +# and it is convenient to configure the host part of the IPv6 address manually. +# +# In GNU/Linux you can disable the IPv6 privacy extension with this: +# +# echo "net.ipv6.conf.all.use_tempaddr=0" > /etc/sysctl.d/95-ipv6-privacy.conf +# echo "net.ipv6.conf.default.use_tempaddr=0" >> /etc/sysctl.d/95-ipv6-privacy.conf +# +# With this, the server set the same host part of the IPv6 address between +# reboots. +# +# Also, you can force the host part of the IPv6 address manually with the +# tokenized interface identifer support. In the /etc/network/interfaces: +# +# iface eth0 inet6 auto +# pre-up /sbin/ifconfig eth0 up +# pre-up /sbin/ip token set ::aaaa:bbbb:cccc:dddd dev eth0 +# +# For example: if the IPv6 prefix obtained is 1111:2222:3333:4444::/64, the +# full IPv6 address of the server will be 1111:2222:3333:4444:aaaa:bbbb:cccc:dddd/64. +# The FW6RULES script detects this change and reconfigure the firewall rule. +# For more info, see here: https://bit.ly/2pQRZR3 +# +# In summary: +# in dst-address: put the host part and mask of the server(s). +# in out-interface: put the name of the LAN interface. +# run the script manually only once: /system script run FW6RULES +# +/ipv6 firewall filter +add action=accept chain=forward connection-state=established,related +add action=accept chain=forward in-interface=LAN1 +add action=accept chain=forward in-interface=LAN2 +add action=drop chain=forward in-interface=WAN src-address-list=BOGONv6 +add action=accept chain=forward dst-address=::aaaa:bbbb:cccc:dddd/128 dst-port= in-interface=WAN out-interface=LAN1 protocol=tcp <...> +add action=accept chain=forward dst-address=::aaaa:bbbb:cccc:dddd/128 dst-port= in-interface=WAN out-interface=LAN1 protocol=udp <...> +add action=accept chain=forward dst-address=::1111:2222:3333:4400/120 dst-port= in-interface=WAN out-interface=LAN2 protocol=tcp <...> +add action=accept chain=forward dst-address=::1111:2222:3333:4400/120 dst-port= in-interface=WAN out-interface=LAN2 protocol=udp <...> +add action=accept chain=forward dst-address=::8888:eeee:5555:0/112 dst-port= in-interface=LAN1 out-interface=LAN2 protocol=tcp <...> +add action=accept chain=forward dst-address=::8888:eeee:5555:0/112 dst-port= in-interface=LAN1 out-interface=LAN2 protocol=udp <...> +add +add action=drop chain=forward + +# +# IPv6 Neighbor Discovery. +# +# Set the interfaces in which the router advertisement is sent and +# the interval. +# +/ipv6 nd +set [ find default=yes ] disabled=yes +add interface=LAN1 mtu=1500 ra-interval=10s-30s +add interface=LAN2 mtu=1500 ra-interval=10s-30s + +# +# IPv6 Neighbor Discovery. +# +# Set the preferred and valid lifetime of the prefixes advertised. +# +/ipv6 nd prefix default +set preferred-lifetime=2m valid-lifetime=2m30s + +# +# Clock. +# +# Set the NTP client, server and the timezone. +# +/system ntp client +set enabled=yes primary-ntp= secondary-ntp= +/system ntp server +set enabled=yes +/system clock +set time-zone-autodetect=no time-zone-name= + +# +# Hostname of the router and no banner at login. +# +/system identity +set name=MIKROTIK +/system note +set show-at-login=no + +# +# End of the configuration. +# + + +### Script +----------- + +# +# Create the script with read and write permissions. +# +/system script +add name=FW6RULES policy=read,write + +# +# Edit the source code of the script. +# +# Note: below is the script in raw mode wich you can copy and paste +# without the comments. +# +/system script +edit FW6RULES source + +# +# Begin of the code. +# + +#-- Wait for the DHCP completion. +:delay 5s; + +#-- +#-- Function: return the uncompressed value of an IPv6 address +#-- or a IPv6 address + mask. +#-- +#-- Parameters: +#-- $1: IPv6 address to expand. +#-- +#-- Examples: +#-- Param $1 Return +#-- ----------- --------- +#-- ::/128 0:0:0:0:0:0:0:0/128 +#-- ::1/128 0:0:0:0:0:0:0:1/128 +#-- 2002:3003::/112 2002:3003:0:0:0:0:0:0/112 +#-- 2112:3113::4114:0/120 2112:3113:0:0:0:0:4114:0/120 +#-- 2332:2:3:4:5:6:7:8/128 2332:2:3:4:5:6:7:8/128 +#-- :: 0:0:0:0:0:0:0:0 +#-- ::1 0:0:0:0:0:0:0:1 +#-- 2002:3003:: 2002:3003:0:0:0:0:0:0 +#-- 2112:3113::4114:0 2112:3113:0:0:0:0:4114:0 +#-- 2332:2:3:4:5:6:7:8 2332:2:3:4:5:6:7:8 +#-- +:local EXPANDIP do={ + #-- Original IPv6 address. + :local ORIGINAL "$1"; + + #-- Uncompressed IPv6 address. + :local EXPANDED "$ORIGINAL"; + + #-- Search for "::". If not found, then the IPv6 address + #-- is already uncompressed. + :local POSTWO [:find $ORIGINAL "::" -1]; + :if ($POSTWO >= 0) do={ + #-- Split the IPv6 address with the separator "::". + :local PREFIX [:pick $ORIGINAL 0 $POSTWO]; + :local SUFFIX [:pick $ORIGINAL ($POSTWO + 2) 99]; + + #-- If any string is empty, set to "0". This happens when + #-- the IPv6 address starts and/or ends with "::". + :if ([:len $PREFIX] = 0) do={ :set PREFIX "0"; } + :if ([:len $SUFFIX] = 0) do={ :set SUFFIX "0"; } + + #-- If the suffix starts with "/", insert a "0" + #-- before de mask. This happens when the IPv6 + #-- address ends with "::/NN". + :if ($SUFFIX ~ "^/") do={ :set SUFFIX ("0" . $SUFFIX); } + + #-- Count the ":" character of the IPv6 address. + :local CNTTWO 0; + :for NDX from=0 to=([:len $ORIGINAL] - 1) do={ + :if ([:pick $ORIGINAL $NDX] = ":") do={ + :set CNTTWO ($CNTTWO + 1); + } + } + + #-- Calculate how much is needed to fill + #-- the IPv6 address with ":0:" in the middle + #-- to uncompress. + :set CNTTWO (8 - $CNTTWO); + + #-- Calculate the mid string with ":0:" to + #-- fill the IPv6 address. + :local MEDFIX ""; + :if ($CNTTWO > 0) do={ + :for NDX from=1 to=$CNTTWO do={ + :set MEDFIX ($MEDFIX . ":0"); + } + } + :set MEDFIX ($MEDFIX . ":"); + + #-- Calculate the expanded IPv6 address. + :set EXPANDED ($PREFIX . $MEDFIX . $SUFFIX); + } + + #-- Finish. + :return $EXPANDED; + } + +#-- +#-- Function: return the prefix or host part of an +#-- expanded IPv6 address. +#-- +#-- The prefix and host boundary always is /64 regardless the +#-- mask of the IPv6 address. +#-- +#-- Parameters: +#-- $1: expanded IPv6 address. +#-- $2: false: return the prefix part (first 64 bits). +#-- true: return the host part (last 64 bits) and mask. +#-- +#-- Examples: +#-- $1 $2=false $2=true +#-- ------------------ ------------ ------------ +#-- 1111:2222:3333:4444:aaaa:bbbb:cccc:dddd/128 1111:2222:3333:4444 aaaa:bbbb:cccc:dddd/128 +#-- 1111:2222:3333:4444:aaaa:bbbb:cccc:dddd 1111:2222:3333:4444 aaaa:bbbb:cccc:dddd +#-- 0:1:2:3:4:5:6:7/120 0:1:2:3 4:5:6:7/120 +#-- 0:1:2:3:4:5:6:7 0:1:2:3 4:5:6:7 +#-- a:b:c:d:1:2:3:4/64 a:b:c:d 1:2:3:4/64 +#-- +:local GETNETHOST do={ + #-- Parameters. + :local DIRIP "$1"; + :local ISHOST "$2"; + + #-- Search for the fourth two points + #-- (the prefix / host boundary). + :local POSDT -2; + :for NUMDT from=1 to=4 do={ + :set POSDT [:find $DIRIP ":" ($POSDT + 1)]; + } + + #-- String with the result. + :local RESULT ""; + + #-- Check for prefix / host part. + :if ($ISHOST = true) do={ + #-- Calculate the host part. + :set RESULT [:pick $DIRIP ($POSDT + 1) 99]; + } else={ + #-- Calculate the prefix part. + :set RESULT [:pick $DIRIP 0 $POSDT]; + } + + #-- Finish. + :return $RESULT; + } + +#-- +#-- Get the IPv6 prefix of every LAN interface. +#-- +#-- Fill the NETLIST array with the name and the expanded +#- IPv6 prefix: +#-- +#-- NETLIST = { "NAME1" -> "PREFIX1"; +#-- "NAME2" -> "PREFIX2"; +#-- .... -> .... } +#-- +#-- Considers only interfaces with an IPv6 pool associated. +#-- If a interface have more than one IPv6 address from a pool, +#-- the algorithm takes into account only the last IPv6 address +#-- obtained for that interface and change the firewall rule +#-- with that prefix. +#-- +#-- Example: +#-- NETLIST = { "LAN1" -> "2002:3440:3efa:3299"; +#-- "LAN2" -> "2003:0:0:0"; } +#-- +:local NETLIST ({}); + +#-- Loop through all interfaces with global IPv6 address. +:foreach INTNDX in=[/ipv6 address find global] do={ + #-- Get the name of the pool of the interface. + :local POOLNAM [/ipv6 address get number=$INTNDX from-pool]; + + #-- Check if is a valid pool name. + #-- If the DHCP proccess fails or the interface not obtain the + #-- IPv6 address from a pool, the pool name is invalid. + :if ([:len $POOLNAM] > 0) do={ + #-- Get the index of the pool. + :local POOLNDX [/ipv6 pool find name=$POOLNAM]; + + #-- Check if is a valid index. + :if ([:len $POOLNDX] > 0) do={ + #--- Check if is a valid IPv6 prefix. + #--- If the DHCP proccess fails, the pool not have a valid prefix. + :if ([:len [/ipv6 pool get number=$POOLNDX prefix]] > 0) do={ + #-- The pool is valid, then the IPv6 address of the interface + #-- is valid. Get the IPv6 address of the interface. + :local INTNETW [/ipv6 address get number=$INTNDX address]; + + #-- Check if the netmask is /64. + :if ($INTNETW ~ "/64\$") do={ + #-- Get the name of the interface. + :local INTNAME [/ipv6 address get number=$INTNDX interface]; + + #-- Fill the array. Expand the IPv6 address and get the prefix part. + :set ($NETLIST->$INTNAME) [$GETNETHOST [$EXPANDIP $INTNETW] false]; + } + } + } + } + } + +#-- +#-- Check every IPv6 firewall filter rule. Change the dst-address of the +#-- rules when is necessary. +#-- +#-- The rules must be configured with the out-interface to match the NETLIST +#-- array. +#-- +#-- Get every firewall filter rule (only forward chain). +:foreach RULENDX in=[/ipv6 firewall filter find chain="forward"] do={ + #-- Get the out-interface of the rule. + :local RULELAN [/ipv6 firewall filter get number=$RULENDX out-interface]; + + #-- Get the new IPv6 prefix of the out-interface of the rule. + :local NEWPRFX ($NETLIST->$RULELAN); + + #-- Check if the out-interface have a valid IPv6 prefix. + :if ([:len $NEWPRFX] > 0) do={ + #-- Get the destination address of the rule. + :local RULEDST [$EXPANDIP [/ipv6 firewall filter get number=$RULENDX dst-address]]; + + #-- Calculate the new IPv6 address of the rule + #-- with the new IPv6 prefix. + :local NEWADDR ($NEWPRFX . ":" . [$GETNETHOST $RULEDST true]); + + #-- Check if the dst address of the rule is different + #-- of the new calculated address. + :if ($RULEDST != $NEWADDR) do={ + #-- Change the dst-address of the rule. + :local RET [/ipv6 firewall filter set numbers=$RULENDX dst-address=$NEWADDR]; + + #-- Log the change. + :log info ("fw6rules: ipv6 fw rule " . $RULENDX . " changed, " . $RULELAN . " new dstaddr " . $NEWADDR); + } + } + } + +#-- Finish. +:log info ("fw6rules: executed"); + + +### Raw script +--------------- + +/system script +add name=FW6RULES policy=read,write source="\ + \n:delay 5s;\ + \n\ + \n:local EXPANDIP do={\ + \n :local ORIGINAL \"\$1\";\ + \n :local EXPANDED \"\$ORIGINAL\";\ + \n :local POSTWO [:find \$ORIGINAL \"::\" -1];\ + \n :if (\$POSTWO >= 0) do={\ + \n :local PREFIX [:pick \$ORIGINAL 0 \$POSTWO];\ + \n :local SUFFIX [:pick \$ORIGINAL (\$POSTWO + 2) 99];\ + \n :if ([:len \$PREFIX] = 0) do={ :set PREFIX \"0\"; }\ + \n :if ([:len \$SUFFIX] = 0) do={ :set SUFFIX \"0\"; }\ + \n :if (\$SUFFIX ~ \"^/\") do={ :set SUFFIX (\"0\" . \$SUFFIX); }\ + \n\ + \n :local CNTTWO 0;\ + \n :for NDX from=0 to=([:len \$ORIGINAL] - 1) do={\ + \n :if ([:pick \$ORIGINAL \$NDX] = \":\") do={\ + \n :set CNTTWO (\$CNTTWO + 1);\ + \n }\ + \n }\ + \n :set CNTTWO (8 - \$CNTTWO);\ + \n\ + \n :local MEDFIX \"\";\ + \n :if (\$CNTTWO > 0) do={\ + \n :for NDX from=1 to=\$CNTTWO do={\ + \n :set MEDFIX (\$MEDFIX . \":0\");\ + \n }\ + \n }\ + \n :set MEDFIX (\$MEDFIX . \":\");\ + \n :set EXPANDED (\$PREFIX . \$MEDFIX . \$SUFFIX);\ + \n }\ + \n :return \$EXPANDED;\ + \n }\ + \n\ + \n:local GETNETHOST do={\ + \n :local DIRIP \"\$1\";\ + \n :local ISHOST \"\$2\";\ + \n :local POSDT -2;\ + \n :for NUMDT from=1 to=4 do={\ + \n :set POSDT [:find \$DIRIP \":\" (\$POSDT + 1)];\ + \n }\ + \n :local RESULT \"\";\ + \n :if (\$ISHOST = true) do={\ + \n :set RESULT [:pick \$DIRIP (\$POSDT + 1) 99];\ + \n } else={\ + \n :set RESULT [:pick \$DIRIP 0 \$POSDT];\ + \n }\ + \n :return \$RESULT;\ + \n }\ + \n\ + \n:local NETLIST ({});\ + \n:foreach INTNDX in=[/ipv6 address find global] do={\ + \n :local POOLNAM [/ipv6 address get number=\$INTNDX from-pool];\ + \n :if ([:len \$POOLNAM] > 0) do={\ + \n :local POOLNDX [/ipv6 pool find name=\$POOLNAM];\ + \n :if ([:len \$POOLNDX] > 0) do={\ + \n :if ([:len [/ipv6 pool get number=\$POOLNDX prefix]] > 0) do={\ + \n :local INTNETW [/ipv6 address get number=\$INTNDX address];\ + \n :if (\$INTNETW ~ \"/64\\\$\") do={\ + \n :local INTNAME [/ipv6 address get number=\$INTNDX interface];\ + \n :set (\$NETLIST->\$INTNAME) [\$GETNETHOST [\$EXPANDIP \$INTNETW] false];\ + \n }\ + \n }\ + \n }\ + \n }\ + \n }\ + \n\ + \n:foreach RULENDX in=[/ipv6 firewall filter find chain=\"forward\"] do={\ + \n :local RULELAN [/ipv6 firewall filter get number=\$RULENDX out-interface];\ + \n :local NEWPRFX (\$NETLIST->\$RULELAN);\ + \n :if ([:len \$NEWPRFX] > 0) do={\ + \n :local RULEDST [\$EXPANDIP [/ipv6 firewall filter get number=\$RULENDX dst-address]];\ + \n :local NEWADDR (\$NEWPRFX . \":\" . [\$GETNETHOST \$RULEDST true]);\ + \n :if (\$RULEDST != \$NEWADDR) do={\ + \n :local RET [/ipv6 firewall filter set numbers=\$RULENDX dst-address=\$NEWADDR];\ + \n :log info (\"fw6rules: ipv6 fw rule \" . \$RULENDX . \" changed, \" . \$RULELAN . \" new dstaddr \" . \$NEWADDR);\ + \n }\ + \n }\ + \n }\ + \n\ + \n:log info (\"fw6rules: executed\");\ + \n" + + +### End +-------- + +If you wants a new feature or found a bug, please open an issue in BitBucket: + + https://bitbucket.org/mangelo/snippets/src + +Thanks.