Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revisionBoth sides next revision
docs:guide-user:network:ipv6:ipv6.nat6 [2021/02/19 01:12] – [Simplified] include the minimal required steps vgaeteradocs:guide-user:network:ipv6:ipv6.nat6 [2023/09/17 23:39] – [Introduction] vgaetera
Line 1: Line 1:
-====== NAT6 and IPv6 masquerading ====== +====== NAT66 and IPv6 masquerading ====== 
-{{section>meta:infobox:howto_links#cli_skills&noheader&nofooter&noeditbutton}}+{{section>meta:infobox:howto_links#basic_skills&noheader&nofooter&noeditbutton}}
  
 ===== Introduction ===== ===== Introduction =====
-This page describes how to set up NAT6 (also known as NAT66masquerading on your OpenWrt router. +  * This how-to describes the method for setting up NAT66 aka NAT6 with IPv6 masquerading on your OpenWrt router. 
-Most users will not need or want to do this in IPv6but there are some more specific use cases for NAT with IPv6. +  * Assuming a [[docs:guide-user:network:ipv6:configuration#ula_prefix|ULA prefix]][[docs:guide-user:network:ipv6:configuration#slaac_and_dhcpv6|SLAAC and DHCPv6]] and a working IPv6 connection on the router. 
-These might include:+  * Avoid using NAT66 and better [[docs:guide-user:network:ipv6:configuration#ipv6_relay|use relay mode]] if you are provided with a /64 prefix. 
 +  * It is also best to avoid using NAT66 unless you are facing the following problems: 
 +    * IPv6 multihoming without BGP
 +    * Performing stateless 1:1 NAT for migration purposes. 
 +    * Your ISP uses a dynamic prefix and you need stable addressing. 
 +    * Creating a subnet for when the network doesn't support subnetting. 
 +    * Being provided a smaller prefix than a /64 or worse, none at all or a ULA address. 
 +  * See also: [[docs:guide-user:network:ipv6:nat64|NAT64]], [[docs:guide-user:firewall:fw3_configurations:fw3_nat#ipv6_npt|IPv6 NAT and NPT]]
  
-  * IPv6 multihoming without BGP +===== Command-line instructions ===== 
-  * Performing stateless 1:1 NAT for migration purposes +==== 1. Firewall ==== 
-  * Your ISP uses a dynamic prefix and you need stable addressing +Enable IPv6 masquerading on the upstream zone.
-  * Creating a subnet for when the network doesn't support subnetting +
-  * Being provided a smaller prefix than a /64 or worse, none at all or a ULA address +
- +
-Note: If you are provided a /64 prefix, you may not need to use NAT6 and instead [[docs:guide-user:network:ipv6:start#ipv6_relay|should try relay mode]]. +
- +
-This guide relies on OpenWrt default settings and assumes you already have a working IPv6 connection on your OpenWrt router. +
- +
-===== Instructions ===== +
-==== 1. Preparation ==== +
-Install the necessary packages.+
  
 <code bash> <code bash>
-Install packages +Configure firewall 
-opkg update +uci set firewall.@zone[1].masq6="1" 
-opkg install kmod-ipt-nat6+uci commit firewall 
 +/etc/init.d/firewall restart
 </code> </code>
  
 ==== 2. Network ==== ==== 2. Network ====
-If you are handing out only local addresses, i.e. not part of delegated prefix from your upstream, change the first letter of the IPv6 [[docs:guide-user:network:ipv6:ipv6.nat6#ula_prefix|ULA prefix]].+Disable IPv6 source filter on the upstream interface.
  
 <code bash> <code bash>
 # Configure network # Configure network
-uci set network.globals.ula_prefix="$(uci get network.globals.ula_prefix | sed -e "s/^./d/")"+uci set network.wan6.sourcefilter="0"
 uci commit network uci commit network
 /etc/init.d/network restart /etc/init.d/network restart
 </code> </code>
  
-==== 3. DHCPv6 ==== +Prefer [[docs:guide-user:network:ipv6:ipv6_extras#using_ipv6_by_default|IPv6 by default]] or announce [[docs:guide-user:network:ipv6:ipv6_extras#announcing_ipv6_default_route|IPv6 default route]] if necessary.
-Set the DHCPv6 server to always announce default router.+
  
-<code bash> +===== Troubleshooting ===== 
-# Configure odhcpd +Collect and analyze the following information.
-uci set dhcp.lan.ra_default="1" +
-uci commit dhcp +
-/etc/init.d/odhcpd restart +
-</code> +
- +
-==== 4. Firewall ==== +
-Enable the new ''masq6'' option in your firewall on your upstream zone.+
  
 <code bash> <code bash>
-Configure firewall +Log and status
-uci set $(uci show firewall | sed -n -e "/\.name='wan'$/s//.masq6='1'/p" | sed -n -e "1p"+
-uci commit firewall +
-</code> +
- +
-Since masquerading is enabled, disable the redundant firewall rule "Allow-ICMPv6-Forward"+
- +
-<code bash> +
-# Configure firewall +
-uci set $(uci show firewall | sed -n -e "/\.name='Allow-ICMPv6-Forward'$/s//.enabled='0'/p" | sed -n -e "1p"+
-uci commit firewall +
-</code> +
- +
-Save the NAT6 firewall script. +
- +
-<code bash> +
-# Configure firewall +
-cat << "EOF" > /etc/firewall.nat6 +
-# NAT6 + masquerading firewall script +
-# https://github.com/akatrevorjay/openwrt-masq6 +
-# trevorj <github@trevor.joynson.io> +
-+
-# You can configure in /etc/config/firewall per zone: +
-# * IPv4 masquerading +
-#     option masq 1 +
-# * IPv6 masquerading +
-#     option masq6 1 +
-# * IPv6 privacy extensions +
-#     option masq6_privacy 1 +
- +
-set -e -o pipefail +
- +
-. /lib/functions.sh +
-. /lib/functions/network.sh +
-. /usr/share/libubox/jshn.sh +
- +
-log() { +
-    logger -t nat6 -s "${@}" +
-+
- +
-get_ula_prefix() { +
-    uci get network.globals.ula_prefix +
-+
- +
-validate_ula_prefix() { +
-    local ula_prefix="${1}" +
-    if [ $(echo "${ula_prefix}" | grep -c -E -e "^([0-9a-fA-F]{4}):([0-9a-fA-F]{0,4}):") -ne 1 ] ; then +
-        log "Fatal error: IPv6 ULA ula_prefix=\"${ula_prefix}\" seems invalid. Please verify that a ula_prefix is set and valid." +
-        return 1 +
-    fi +
-+
- +
-ip6t() { +
-    ip6tables "${@}" +
-+
- +
-ip6t_add() { +
-    if ! ip6t -C "${@}" &> /dev/null; then +
-        ip6t -I "${@}" +
-    fi +
-+
- +
-nat6_init() { +
-    iptables-save -t nat \ +
-    | sed -e "/\s[DS]NAT\s/d;/\sMASQUERADE$/d;/\s--match-set\s\S*/s//\06/"+
-    | ip6tables-restore -T nat +
-+
- +
-masq6_network() { +
-    # ${config} contains the ID of the current section +
-    local network_name="${1}" +
- +
-    local device +
-    network_get_device device "${network_name}" || return 0 +
- +
-    local done_net_dev +
-    for done_net_dev in ${DONE_NETWORK_DEVICES}; do +
-        if [ "${done_net_dev}" = "${device}" ]; then +
-            log "Already configured device=\"${device}\", so leaving as is." +
-            return 0 +
-        fi +
-    done +
- +
-    log "Found device=\"${device}\" for network_name=\"${network_name}\"." +
- +
-    if [ "${zone_masq6_privacy}" -eq 1 ]; then +
-        log "Enabling IPv6 temporary addresses for device=\"${device}\"." +
- +
-        log "Accepting router advertisements on ${device} even if forwarding is enabled (required for temporary addresses)" +
-        echo 2 > "/proc/sys/net/ipv6/conf/${device}/accept_ra"+
-        || log "Error: Failed to change router advertisements accept policy on ${device} (required for temporary addresses)" +
- +
-        log "Using temporary addresses for outgoing connections on interface ${device}" +
-        echo 2 > "/proc/sys/net/ipv6/conf/${device}/use_tempaddr"+
-        || log "Error: Failed to enable temporary addresses for outgoing connections on interface ${device}" +
-    fi +
- +
-    append DONE_NETWORK_DEVICES "${device}" +
-+
- +
-handle_zone() { +
-    # ${config} contains the ID of the current section +
-    local config="${1}" +
- +
-    local zone_name +
-    config_get zone_name "${config}" name +
- +
-    # Enable masquerading via NAT6 +
-    local zone_masq6 +
-    config_get_bool zone_masq6 "${config}" masq6 0 +
- +
-    log "Firewall config=\"${config}\" zone=\"${zone_name}\" zone_masq6=\"${zone_masq6}\"." +
- +
-    if [ "${zone_masq6}" -eq 0 ]; then +
-        return 0 +
-    fi +
- +
-    # IPv6 privacy extensions: Use temporary addrs for outgoing connections? +
-    local zone_masq6_privacy +
-    config_get_bool zone_masq6_privacy "${config}" masq6_privacy 1 +
- +
-    log "Found firewall zone_name=\"${zone_name}\" with zone_masq6=\"${zone_masq6}\" zone_masq6_privacy=\"${zone_masq6_privacy}\"." +
- +
-    log "Setting up masquerading nat6 for zone_name=\"${zone_name}\" with zone_masq6_privacy=\"${zone_masq6_privacy}\"" +
- +
-    local ula_prefix="$(get_ula_prefix)" +
-    validate_ula_prefix "${ula_prefix}" || return 1 +
- +
-    local postrouting_chain="zone_${zone_name}_postrouting" +
-    log "Ensuring ip6tables chain=\"${postrouting_chain}\" contains our MASQUERADE." +
-    ip6t_add "${postrouting_chain}" -t nat \ +
-        -m comment --comment "!fw3" -j MASQUERADE +
- +
-    local input_chain="zone_${zone_name}_input" +
-    log "Ensuring ip6tables chain=\"${input_chain}\" contains our permissive DNAT rule." +
-    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" +
-    log "Ensuring ip6tables chain=\"${forward_chain}\" contains our permissive DNAT rule." +
-    ip6t_add "${forward_chain}" -t filter -m conntrack --ctstate DNAT \ +
-        -m comment --comment "!fw3: Accept port forwards" -j ACCEPT +
- +
-    local DONE_NETWORK_DEVICES="" +
-    config_list_foreach "${config}" network masq6_network +
- +
-    log "Done setting up nat6 for zone=\"${zone_name}\" on devices: ${DONE_NETWORK_DEVICES}" +
-+
- +
-main() { +
-    nat6_init +
-    config_load firewall +
-    config_foreach handle_zone zone +
-+
- +
-main "${@}" +
-EOF +
-</code> +
- +
-Include the NAT6 firewall script in the configuration. +
- +
-<code bash> +
-# Configure firewall +
-uci -q delete firewall.nat6 +
-uci set firewall.nat6="include" +
-uci set firewall.nat6.path="/etc/firewall.nat6" +
-uci set firewall.nat6.reload="1" +
-uci commit firewall+
 /etc/init.d/firewall restart /etc/init.d/firewall restart
-</code> 
  
-===== Configuration ===== +# Runtime configuration 
-The solution provided here can be considered more robust and portable. +ip -6 address show; ip -6 route show table all 
-Especially the init script comes with benefits such as configurability, sanity checks and error handling, as well as logging (which might help debugging, if something is not working as expected).+ip -6 rule show; nft list ruleset
  
-Configuration is done per firewall zone, just like standard masquerading. +Persistent configuration 
- +uci show network; uci show firewall
-This provides two configurables in UCI's firewall zone section: +
- +
-<code bash> +
-Configure firewall +
-uci set firewall.@zone[1].masq6="1" +
-uci set firewall.@zone[1].masq6_privacy="1" +
-uci commit firewall +
-/etc/init.d/firewall restart +
-</code> +
- +
-If ''masq6_privacy'' is set to ''1'' (default is ''0'' aka off), then outgoing IPv6 connections will use temporary addresses that change dynamically. +
-This supposedly makes it harder to track users and surf behavior. +
- +
-If you prefer to use static addresses (at least as long your ISP assigned prefix doesn't change), leave it at the default of ''0''+
- +
-===== Troubleshooting ===== +
-The script logs informational and error messages to the system log. +
-The messages are tagged with ''nat6''+
-You can view the log messages with the command: +
- +
-<code bash> +
-logread -e nat6 +
-</code> +
- +
-If all was configured successfully, the output should look similar to this: +
- +
-<code> +
-2017-02-04T18:03:44-08:00 notice nat6[]: Found firewall zone_name="wan" with zone_masq6="1" zone_masq6_privacy="1"+
-2017-02-04T18:03:44-08:00 notice nat6[]: Setting up masquerading nat6 for zone_name="wan" with zone_masq6_privacy="1" +
-2017-02-04T18:03:44-08:00 notice nat6[]: Ensuring ip6tables chain="zone_wan_postrouting" contains our MASQUERADE. +
-2017-02-04T18:03:44-08:00 notice nat6[]: Found device="eth1" for network_name="wan"+
-2017-02-04T18:03:44-08:00 notice nat6[]: Enabling IPv6 temporary addresses for device="eth1"+
-2017-02-04T18:03:44-08:00 notice nat6[]: Accepting router advertisements on eth1 even if forwarding is enabled (required for temporary addresses) +
-2017-02-04T18:03:44-08:00 notice nat6[]: Using temporary addresses for outgoing connections on interface eth1 +
-2017-02-04T18:03:44-08:00 notice nat6[]: Already configured device="eth1", so leaving as is. +
-2017-02-04T18:03:44-08:00 notice nat6[]: Done setting up nat6 for zone="wan" on devices: eth1 +
-</code> +
- +
-Failures that occur during initialization (upon each firewall reload), will be logged and marked as such. Pay attention to any noted as error or fatal error. +
- +
-You're also welcome to run the script from a shell to see it progress; it is just a shell script after all. +
- +
-===== Extras ===== +
-==== DHCPv6 ==== +
-Make sure DHCPv6 uses the following settings (on an unmodified OpenWrt installation these should by the default): +
-  * "Router Advertisement-Service" and "DHCPv6-Service" are set to server mode* +
-  * "DHCPv6-Mode" is stateless + stateful +
-  * "NDP-Proxy" is disabled +
- +
-You can check this by running the following command: +
- +
-<code bash> +
-uci show dhcp.lan +
-... +
-dhcp.lan.dhcpv6='server' +
-dhcp.lan.ra='server' +
-dhcp.lan.ra_management='1' +
-</code> +
- +
-If the output is different, you are not using the defaults and you should set these options to the ones shown above. +
-If there is an additional line starting with ''dhcp.lan.ndp'', the NDP-Proxy is enabled and should be disabled. +
-Setups with "DHCPv6-Service" disabled have been reported working as well by some users. +
-However, if "DHCPv6-Service" is disabled, some clients (e.g. Android devices) will prefer IPv4 over IPv6. +
-Therefore, enabling the "DHCPv6-Service" server mode is recommended. +
- +
-==== ULA prefix ==== +
-The default ULA (Unique local address) prefix represents an address that is not globally routed on the internet by design. +
-A lot of clients will prefer IPv4 over a ULA IPv6 address if there is no global IPv6 address assigned, so you may need to change your existing ULA prefix to indicate a global address to ensure traffic goes over IPv6 by default when possible. +
- +
-When changing the ULA prefix, it doesn't necessarily have to start with ''d'', but to avoid conflicts, you should use a prefix that is not being used yet. +
-The letters are unassigned and therefore safe choices. +
- +
-Setting ''ula_prefix'' to ''auto'' will auto-generate a new valid ULA prefix. +
- +
-Using your ISP assigned prefix as ULA should also work. +
-However, unless you have a static IPv6 prefix assigned by your ISP, this is not recommended, since it can cause address conflicts once the prefix changes. +
-If you have a static prefix that you can delegate across your LAN, then you won't need to change your ULA prefix. +
- +
-==== Simplified ==== +
-[[docs:guide-user:network:ipv6:ipv6.nat6#preparation|Install the necessary packages]] and [[docs:guide-user:network:ipv6:ipv6.nat6#dhcpv6|force the default gateway announcement]]. +
-Enable NAT6 with IPv6 masquerading, cloning the IPv4 setup. +
- +
-<code bash> +
-# Configure firewall +
-cat << "EOF" > /etc/firewall.nat6 +
-iptables-save -t nat \ +
-| sed -e "/\s[DS]NAT\s/d;/\s--match-set\s\S*/s//\06/"+
-| ip6tables-restore -T nat +
-EOF +
-uci -q delete firewall.nat6 +
-uci set firewall.nat6="include" +
-uci set firewall.nat6.path="/etc/firewall.nat6" +
-uci set firewall.nat6.reload="1" +
-uci commit firewall +
-/etc/init.d/firewall restart+
 </code> </code>
  
  • Last modified: 2023/10/14 06:10
  • by vgaetera