RFC Errata
Found 4 records.
Status: Verified (3)
RFC 4890, "Recommendations for Filtering ICMPv6 Messages in Firewalls", May 2007
Source of RFC: v6ops (ops)
Errata ID: 2706
Status: Verified
Type: Technical
Publication Format(s) : TEXT
Reported By: Phil Whineray
Date Reported: 2011-02-06
Verifier Name: ron bonica
Date Verified: 2011-03-03
Section Appendix B. says:
if [ "$STATE_ENABLED" -eq "1" ]
then
# Allow incoming time exceeded code 0 messages
# only for existing sessions
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -m state -p icmpv6 \
-d $inner_prefix \
--state ESTABLISHED,RELATED --icmpv6-type packet-too-big \
-j ACCEPT
done
else
# Allow incoming time exceeded code 0 messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -d $inner_prefix \
--icmpv6-type ttl-zero-during-transit -j ACCEPT
done
fi
It should say:
if [ "$STATE_ENABLED" -eq "1" ]
then
# Allow incoming time exceeded code 0 messages
# only for existing sessions
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -m state -p icmpv6 \
-d $inner_prefix \
--state ESTABLISHED,RELATED --icmpv6-type ttl-zero-during-transmit \
-j ACCEPT
done
else
# Allow incoming time exceeded code 0 messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -d $inner_prefix \
--icmpv6-type ttl-zero-during-transit -j ACCEPT
done
fi
Notes:
Not sure if this is really editorial as it is in the example code, not the main RFC.
In any case, the example incorrectly specifies an icmpv6 type in one code path.
Errata ID: 3985
Status: Verified
Type: Technical
Publication Format(s) : TEXT
Reported By: James Robertson
Date Reported: 2014-05-13
Verifier Name: Joel Jaeggli
Date Verified: 2014-05-19
Section Appendix B says:
if [ "$STATE_ENABLED" -eq "1" ]
then
# Allow incoming time exceeded code 0 messages
# only for existing sessions
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -m state -p icmpv6 \
-d $inner_prefix \
--state ESTABLISHED,RELATED --icmpv6-type packet-too-big \
-j ACCEPT
done
else
# Allow incoming time exceeded code 0 messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -d $inner_prefix \
--icmpv6-type ttl-zero-during-transit -j ACCEPT
done
fi
It should say:
if [ "$STATE_ENABLED" -eq "1" ]
then
# Allow incoming time exceeded code 0 messages
# only for existing sessions
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -m state -p icmpv6 \
-d $inner_prefix \
--state ESTABLISHED,RELATED --icmpv6-type ttl-zero-during-transit \
-j ACCEPT
done
else
# Allow incoming time exceeded code 0 messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -d $inner_prefix \
--icmpv6-type ttl-zero-during-transit -j ACCEPT
done
fi
Notes:
RFC 4890 Errata ID 2706 states that icmpv6-type packet-too-big should
state icmpv6-type ttl-zero-during-transmit. This should read
ttl-zero-during-transit.
Errata ID: 8139
Status: Verified
Type: Technical
Publication Format(s) : TEXT
Reported By: Nikolaos Chatzikonstantinou
Date Reported: 2024-10-13
Verifier Name: Warren Kumari (Ops AD)
Date Verified: 2024-10-14
Section 1 says:
* Ensuring that neighbors remain reachable using the same IP
and link layer addresses after initial discovery (Neighbor
Unreachability Discovery - NUD) and notifying neighbors of
changes to link layer addresses. Uses NS and NA [RFC2461].
It should say:
* Ensuring that neighbors remain reachable using the same IP
and link layer addresses after initial discovery (Neighbor
Unreachability Detection - NUD) and notifying neighbors of
changes to link layer addresses. Uses NS and NA [RFC2461].
Notes:
"Discovery" should be "Detection" as defined in RFC2461 § 7.3.
WK: Doh! Thank you for the clear errata report.
Status: Held for Document Update (1)
RFC 4890, "Recommendations for Filtering ICMPv6 Messages in Firewalls", May 2007
Source of RFC: v6ops (ops)
Errata ID: 7922
Status: Held for Document Update
Type: Technical
Publication Format(s) : TEXT
Reported By: William N.
Date Reported: 2024-05-03
Held for Document Update by: Mohamed Boucadair
Date Held: 2025-06-02
Section Appendix B says:
#!/bin/bash
# Set of prefixes on the trusted ("inner") side of the firewall
export INNER_PREFIXES="2001:DB8:85::/60"
# Set of hosts providing services so that they can be made pingable
export PINGABLE_HOSTS="2001:DB8:85::/64"
# Configuration option: Change this to 1 if errors allowed only for
# existing sessions
export STATE_ENABLED=0
# Configuration option: Change this to 1 if messages to/from link
# local addresses should be filtered.
# Do not use this if the firewall is a bridge.
# Optional for firewalls that are routers.
export FILTER_LINK_LOCAL_ADDRS=0
# Configuration option: Change this to 0 if the site does not support
# Mobile IPv6 Home Agents - see Appendix A.14
export HOME_AGENTS_PRESENT=1
# Configuration option: Change this to 0 if the site does not support
# Mobile IPv6 mobile nodes being present on the site -
# see Appendix A.14
export MOBILE_NODES_PRESENT=1
ip6tables -N icmpv6-filter
ip6tables -A FORWARD -p icmpv6 -j icmpv6-filter
# Match scope of src and dest else deny
# This capability is not provided for in base ip6tables functionality
# An extension (agr) exists which may support it.
#@TODO@
# ECHO REQUESTS AND RESPONSES
# ===========================
# Allow outbound echo requests from prefixes which belong to the site
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -s $inner_prefix \
--icmpv6-type echo-request -j ACCEPT
done
# Allow inbound echo requests towards only predetermined hosts
for pingable_host in $PINGABLE_HOSTS
do
ip6tables -A icmpv6-filter -p icmpv6 -d $pingable_host \
--icmpv6-type echo-request -j ACCEPT
done
if [ "$STATE_ENABLED" -eq "1" ]
then
# Allow incoming and outgoing echo reply messages
# only for existing sessions
ip6tables -A icmpv6-filter -m state -p icmpv6 \
--state ESTABLISHED,RELATED --icmpv6-type \
echo-reply -j ACCEPT
else
# Allow both incoming and outgoing echo replies
for pingable_host in $PINGABLE_HOSTS
do
# Outgoing echo replies from pingable hosts
ip6tables -A icmpv6-filter -p icmpv6 -s $pingable_host \
--icmpv6-type echo-reply -j ACCEPT
done
# Incoming echo replies to prefixes which belong to the site
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -d $inner_prefix \
--icmpv6-type echo-reply -j ACCEPT
done
fi
# Deny icmps to/from link local addresses
# If the firewall is a router:
# These rules should be redundant as routers should not forward
# link local addresses but to be sure...
# DO NOT ENABLE these rules if the firewall is a bridge
if [ "$FILTER_LINK_LOCAL_ADDRS" -eq "1" ]
then
ip6tables -A icmpv6-filter -p icmpv6 -d fe80::/10 -j DROP
ip6tables -A icmpv6-filter -p icmpv6 -s fe80::/10 -j DROP
fi
# Drop echo replies which have a multicast address as a
# destination
ip6tables -A icmpv6-filter -p icmpv6 -d ff00::/8 \
--icmpv6-type echo-reply -j DROP
# DESTINATION UNREACHABLE ERROR MESSAGES
# ======================================
if [ "$STATE_ENABLED" -eq "1" ]
then
# Allow incoming destination unreachable messages
# only for existing sessions
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -m state -p icmpv6 \
-d $inner_prefix \
--state ESTABLISHED,RELATED --icmpv6-type \
destination-unreachable -j ACCEPT
done
else
# Allow incoming destination unreachable messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -d $inner_prefix \
--icmpv6-type destination-unreachable -j ACCEPT
done
fi
# Allow outgoing destination unreachable messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -s $inner_prefix \
--icmpv6-type destination-unreachable -j ACCEPT
done
# PACKET TOO BIG ERROR MESSAGES
# =============================
if [ "$STATE_ENABLED" -eq "1" ]
then
# Allow incoming Packet Too Big messages
# only for existing sessions
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -m state -p icmpv6 \
-d $inner_prefix \
--state ESTABLISHED,RELATED \
--icmpv6-type packet-too-big \
-j ACCEPT
done
else
# Allow incoming Packet Too Big messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -d $inner_prefix \
--icmpv6-type packet-too-big -j ACCEPT
done
fi
# Allow outgoing Packet Too Big messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -s $inner_prefix \
--icmpv6-type packet-too-big -j ACCEPT
done
# TIME EXCEEDED ERROR MESSAGES
# ============================
if [ "$STATE_ENABLED" -eq "1" ]
then
# Allow incoming time exceeded code 0 messages
# only for existing sessions
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -m state -p icmpv6 \
-d $inner_prefix \
--state ESTABLISHED,RELATED --icmpv6-type packet-too-big \
-j ACCEPT
done
else
# Allow incoming time exceeded code 0 messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -d $inner_prefix \
--icmpv6-type ttl-zero-during-transit -j ACCEPT
done
fi
#@POLICY@
# Allow incoming time exceeded code 1 messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -d $inner_prefix \
--icmpv6-type ttl-zero-during-reassembly -j ACCEPT
done
# Allow outgoing time exceeded code 0 messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -s $inner_prefix \
--icmpv6-type ttl-zero-during-transit -j ACCEPT
done
#@POLICY@
# Allow outgoing time exceeded code 1 messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -s $inner_prefix \
--icmpv6-type ttl-zero-during-reassembly -j ACCEPT
done
# PARAMETER PROBLEM ERROR MESSAGES
# ================================
if [ "$STATE_ENABLED" -eq "1" ]
then
# Allow incoming parameter problem code 1 and 2 messages
# for an existing session
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -m state -p icmpv6 \
-d $inner_prefix \
--state ESTABLISHED,RELATED --icmpv6-type \
unknown-header-type \
-j ACCEPT
ip6tables -A icmpv6-filter -m state -p icmpv6 \
-d $inner_prefix \
--state ESTABLISHED,RELATED \
--icmpv6-type unknown-option \
-j ACCEPT
done
fi
# Allow outgoing parameter problem code 1 and code 2 messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 -s $inner_prefix \
--icmpv6-type unknown-header-type -j ACCEPT
ip6tables -A icmpv6-filter -p icmpv6 -s $inner_prefix \
--icmpv6-type unknown-option -j ACCEPT
done
#@POLICY@
# Allow incoming and outgoing parameter
# problem code 0 messages
for inner_prefix in $INNER_PREFIXES
do
ip6tables -A icmpv6-filter -p icmpv6 \
--icmpv6-type bad-header \
-j ACCEPT
done
# NEIGHBOR DISCOVERY MESSAGES
# ===========================
# Drop NS/NA messages both incoming and outgoing
ip6tables -A icmpv6-filter -p icmpv6 \
--icmpv6-type neighbor-solicitation -j DROP
ip6tables -A icmpv6-filter -p icmpv6 \
--icmpv6-type neighbor-advertisement -j DROP
# Drop RS/RA messages both incoming and outgoing
ip6tables -A icmpv6-filter -p icmpv6 \
--icmpv6-type router-solicitation -j DROP
ip6tables -A icmpv6-filter -p icmpv6 \
--icmpv6-type router-advertisement -j DROP
# Drop Redirect messages both incoming and outgoing
ip6tables -A icmpv6-filter -p icmpv6 --icmpv6-type redirect -j DROP
# MLD MESSAGES
# ============
# Drop incoming and outgoing
# Multicast Listener queries (MLDv1 and MLDv2)
ip6tables -A icmpv6-filter -p icmpv6 --icmpv6-type 130 -j DROP
# Drop incoming and outgoing Multicast Listener reports (MLDv1)
ip6tables -A icmpv6-filter -p icmpv6 --icmpv6-type 131 -j DROP
# Drop incoming and outgoing Multicast Listener Done messages (MLDv1)
ip6tables -A icmpv6-filter -p icmpv6 --icmpv6-type 132 -j DROP
# Drop incoming and outgoing Multicast Listener reports (MLDv2)
ip6tables -A icmpv6-filter -p icmpv6 --icmpv6-type 143 -j DROP
# ROUTER RENUMBERING MESSAGES
# ===========================
# Drop router renumbering messages
ip6tables -A icmpv6-filter -p icmpv6 --icmpv6-type 138 -j DROP
# NODE INFORMATION QUERIES
# ========================
# Drop node information queries (139) and replies (140)
ip6tables -A icmpv6-filter -p icmpv6 --icmpv6-type 139 -j DROP
ip6tables -A icmpv6-filter -p icmpv6 --icmpv6-type 140 -j DROP
# MOBILE IPv6 MESSAGES
# ====================
# If there are mobile ipv6 home agents present on the
# trusted side allow
if [ "$HOME_AGENTS_PRESENT" -eq "1" ]
then
for inner_prefix in $INNER_PREFIXES
do
#incoming Home Agent address discovery request
ip6tables -A icmpv6-filter -p icmpv6 -d $inner_prefix \
--icmpv6-type 144 -j ACCEPT
#outgoing Home Agent address discovery reply
ip6tables -A icmpv6-filter -p icmpv6 -s $inner_prefix \
--icmpv6-type 145 -j ACCEPT
#incoming Mobile prefix solicitation
ip6tables -A icmpv6-filter -p icmpv6 -d $inner_prefix \
--icmpv6-type 146 -j ACCEPT
#outgoing Mobile prefix advertisement
ip6tables -A icmpv6-filter -p icmpv6 -s $inner_prefix \
--icmpv6-type 147 -j ACCEPT
done
fi
# If there are roaming mobile nodes present on the
# trusted side allow
if [ "$MOBILE_NODES_PRESENT" -eq "1" ]
then
for inner_prefix in $INNER_PREFIXES
do
#outgoing Home Agent address discovery request
ip6tables -A icmpv6-filter -p icmpv6 -s $inner_prefix \
--icmpv6-type 144 -j ACCEPT
#incoming Home Agent address discovery reply
ip6tables -A icmpv6-filter -p icmpv6 -d $inner_prefix \
--icmpv6-type 145 -j ACCEPT
#outgoing Mobile prefix solicitation
ip6tables -A icmpv6-filter -p icmpv6 -s $inner_prefix \
--icmpv6-type 146 -j ACCEPT
#incoming Mobile prefix advertisement
ip6tables -A icmpv6-filter -p icmpv6 -d $inner_prefix \
--icmpv6-type 147 -j ACCEPT
done
fi
# DROP EVERYTHING ELSE
# ====================
ip6tables -A icmpv6-filter -p icmpv6 -j DROP
It should say:
#!/bin/bash
# Prefixes on the trusted ("inner") side of the firewall
readonly inner_prefixes=( "2001:db8:85::/60" )
# Hosts providing services so that they can be made pingable
readonly pingable_hosts=( "2001:db8:85::/64" )
# 1 - if errors are allowed only for existing sessions
readonly state_enabled=0
# 1 - if messages to/from link local addresses should be filtered
# Do not use this if the firewall is a bridge.
# Optional for firewalls that are routers.
readonly filter_linklocal_addrs=0
# 0 - if the site does not support Mobile IPv6 Home Agents
# 1 - if there are mobile ipv6 home agents present on the trusted side
# see Appendix A.14
readonly home_agents_present=1
# 0 - if the site does not support Mobile IPv6 mobile nodes
# 1 - if there are roaming mobile nodes present on the trusted side
# see Appendix A.14
readonly mobile_nodes_present=1
ip6tables -N icmpv6-filter
ip6tables -A FORWARD -p icmpv6 -j icmpv6-filter
state_args=(
'--match' 'state'
'--state' 'ESTABLISHED,RELATED'
)
(( state_enabled == 0 )) && state_args=()
readonly state_args
# Helper functions
filter() { ip6tables -A icmpv6-filter -p icmpv6 "${@}"; }
accept() { filter "${@}" -j ACCEPT; }
drop() { filter "${@}" -j DROP; }
# Match scope of src and dest else deny
# This capability is not provided for in base ip6tables functionality
# An extension (agr) exists which may support it.
#@TODO@
# ECHO REQUESTS AND RESPONSES
# ===========================
# Outbound echo requests from prefixes belonging to the site
for inner_prefix in "${inner_prefixes[@]}"; do
accept \
-s "${inner_prefix}" \
--icmpv6-type echo-request
done
# Inbound echo requests only towards predetermined hosts
for pingable_host in "${pingable_hosts[@]}"; do
accept \
-d "${pingable_host}" \
--icmpv6-type echo-request
done
if (( state_enabled == 1 )); then
# Incoming and outgoing messages
# only for existing sessions
accept \
"${state_args[@]}" \
--icmpv6-type echo-reply
else
# Both incoming and outgoing echo replies
for pingable_host in "${pingable_hosts[@]}"; do
# Outgoing echo replies from pingable hosts
accept \
-s "${pingable_host}" \
--icmpv6-type echo-reply
done
# Incoming echo replies to prefixes belonging to the site
for inner_prefix in "${inner_prefixes[@]}"; do
accept \
-d "${inner_prefix}" \
--icmpv6-type echo-reply
done
fi
# Deny icmps to/from link local addresses
# If the firewall is a router:
# These rules should be redundant as routers should not forward
# link local addresses but to be sure...
# DO NOT ENABLE these rules if the firewall is a bridge
if (( filter_linklocal_addrs == 1 )); then
drop -d fe80::/10
drop -s fe80::/10
fi
# No echo replies for multicast destination addresses
drop \
-d ff00::/8 \
--icmpv6-type echo-reply
for inner_prefix in "${inner_prefixes[@]}"; do
# DESTINATION UNREACHABLE ERROR MESSAGES
# ======================================
# incoming
accept \
-d "${inner_prefix}" \
"${state_args[@]}" \
--icmpv6-type destination-unreachable
# outgoing
accept \
-s "${inner_prefix}" \
--icmpv6-type destination-unreachable
# PACKET TOO BIG ERROR MESSAGES
# =============================
# incoming
accept \
-d "${inner_prefix}" \
"${state_args[@]}" \
--icmpv6-type packet-too-big
# outgoing
accept \
-s "${inner_prefix}" \
--icmpv6-type packet-too-big
# TIME EXCEEDED ERROR MESSAGES
# ============================
# incoming w/ code 0
accept \
-d "${inner_prefix}" \
"${state_args[@]}" \
--icmpv6-type 3/0
# @POLICY@
# incoming w/ code 1
accept \
-d "${inner_prefix}" \
--icmpv6-type 3/1
# outgoing w/ code 0
accept \
-s "${inner_prefix}" \
--icmpv6-type 3/0
# @POLICY@
# outgoing w/ code 1
accept \
-s "${inner_prefix}" \
--icmpv6-type 3/1
# PARAMETER PROBLEM ERROR MESSAGES
# ================================
if (( state_enabled == 1 )); then
# incoming
accept \
-d "${inner_prefix}" \
"${state_args[@]}" \
--icmpv6-type 4/1
accept \
-d "${inner_prefix}" \
"${state_args[@]}" \
--icmpv6-type 4/2
fi
# outgoing
accept \
-s "${inner_prefix}" \
--icmpv6-type 4/1
accept \
-s "${inner_prefix}" \
--icmpv6-type 4/2
# @POLICY@
# incoming and outgoing
accept --icmpv6-type 4/0
done
# Drop all these, both incoming and outgoing
types=(
# NEIGHBOR DISCOVERY MESSAGES
# ===========================
'135/0' # Neighbor solicitation
'136/0' # Neighbor advertisement
'133/0' # Router solicitation
'134/0' # Router advertisement
'137/0' # Rredirect'
# Multicast Listener Discovery messages
# =====================================
130 # ML queries (MLDv1 and MLDv2)
131 # ML reports (MLDv1)
132 # ML Done messages (MLDv1)
143 # ML reports (MLDv2)
138 # Router renumbering messages
# NODE INFORMATION QUERIES
# ========================
139 # Node information queries
140 # Node information replies
)
for type in "${types[@]}"; do
drop --icmpv6-type "${type}"
done
# MOBILE IPv6 MESSAGES
# ====================
for inner_prefix in "${inner_prefixes[@]}"; do
if (( home_agents_present == 1 )); then
# incoming Home Agent address discovery request
accept \
-d "${inner_prefix}" \
--icmpv6-type 144
# outgoing Home Agent address discovery reply
accept \
-s "${inner_prefix}" \
--icmpv6-type 145
# incoming Mobile prefix solicitation
accept \
-d "${inner_prefix}" \
--icmpv6-type 146
# outgoing Mobile prefix advertisement
accept \
-s "${inner_prefix}" \
--icmpv6-type 147
fi
if (( mobile_nodes_present == 1 )); then
# outgoing Home Agent address discovery request
accept \
-s "${inner_prefix}" \
--icmpv6-type 144
# incoming Home Agent address discovery reply
accept \
-d "${inner_prefix}" \
--icmpv6-type 145
# outgoing Mobile prefix solicitation
accept \
-s "${inner_prefix}" \
--icmpv6-type 146
# incoming Mobile prefix advertisement
accept \
-d "${inner_prefix}" \
--icmpv6-type 147
fi
done
# DROP EVERYTHING ELSE
# ====================
drop
Notes:
- Fix ShellCheck SC2086 warnings
- Code formatting: improve redability
- Remove unnecessary export statements
- Make uppercase variables lowercase constants
- Make pingable_hosts and inner_prefixes arrays, so that for loops make sense
- Use lowercase IPv6 addresses, as commonly accepted
- Remove useless newlines at the beginning of if-checks and for-loops
- Reduce code repetition by using state_args array
- Combine separate loops in sections
-- DESTINATION UNREACHABLE ERROR MESSAGES
-- PACKET TOO BIG ERROR MESSAGES
-- TIME EXCEEDED ERROR MESSAGES
-- PARAMETER PROBLEM ERROR MESSAGES
- Create filter, accept and drop functions to simplify code
- Reduce code repetition by using type array
- Simplify comments. Comments should explain why something is done, not what is done. If code needs explanation about what it does, it is not readable
NOTE: The original does not seem to address type codes as advised and claimed in the comments. Additionally, there is one pointless loop in the example code. In my errata, I use numerical codes and types to address all this.
Please test the code thoroughly.
=== Verifier note
Many of the changes in this erratum are not about errors, but more a refresh, better readability, simplification, etc. See https://mailarchive.ietf.org/arch/msg/v6ops/RnxLhcrAI4JmF8K7BRiW6xwTtkE/
