Skip to content

Instantly share code, notes, and snippets.

@hrz6976
Last active June 9, 2023 07:06
Show Gist options
  • Save hrz6976/75cbde6c4ff40ea6143b3e1f3a3c869f to your computer and use it in GitHub Desktop.
Save hrz6976/75cbde6c4ff40ea6143b3e1f3a3c869f to your computer and use it in GitHub Desktop.
Champion IPv6 Fix for OpenWRT Routers
WAN_IFACE="eth1.5"
LAN_IFACE="br-lan"
GATEWAY_V6="240c:c001:a:128::1"
GATEWAY_V6_T="fe80::200:ff:fe00:1"
LOCAL_V6_PREFIX="240c:c001:"
LOCAL_V6_TEMPFILE="/tmp/local_v6s"
#!/bin/sh
set -e
# load $CWD/.env
CWD=$(dirname $0)
if [ -f $CWD/.env ]; then
source $CWD/.env
fi
### --- IPv6 --- ###
### -- Reference: https://stackoverflow.com/questions/14697403/expand-ipv6-address-in-shell-script
# helper to convert hex to dec (portable version)
hex2dec(){
[ "$1" != "" ] && printf "%d" "$(( 0x$1 ))"
}
# expand an ipv6 address
expand_ipv6() {
ip=$1
# prepend 0 if we start with :
echo $ip | grep -qs "^:" && ip="0${ip}"
# expand ::
if echo $ip | grep -qs "::"; then
colons=$(echo $ip | sed 's/[^:]//g')
missing=$(echo ":::::::::" | sed "s/$colons//")
expanded=$(echo $missing | sed 's/:/:0/g')
ip=$(echo $ip | sed "s/::/$expanded/")
fi
blocks=$(echo $ip | grep -o "[0-9a-f]\+")
set $blocks
printf "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n" \
$(hex2dec $1) \
$(hex2dec $2) \
$(hex2dec $3) \
$(hex2dec $4) \
$(hex2dec $5) \
$(hex2dec $6) \
$(hex2dec $7) \
$(hex2dec $8)
}
### END IPv6 ###
# echo $(expand_ipv6 "2001:db8::ff00:0042:8329")
LOCAL_V6S=$(ip -6 neigh | awk $(printf '/ dev %s / && !/ FAILED/ && !/ INCOMPLETE/{print $1}' ${LAN_IFACE}) | grep "^${LOCAL_V6_PREFIX}")
echo "Local IPv6 Clients: ${LOCAL_V6S}"
# read from tempfile; if has not changed, exit
if [ -f "$LOCAL_V6_TEMPFILE" ]; then
if [ "$(cat "$LOCAL_V6_TEMPFILE")" = "$LOCAL_V6S" ]; then
echo "No change in local IPv6 clients, exiting"
exit 0
fi
fi
# write to tempfile
echo "$LOCAL_V6S" > "$LOCAL_V6_TEMPFILE"
echo "Updating IPv6 firewall rules"
ip6tables -F OUTBOUND_NA_LAN
ip6tables -I OUTBOUND_NA_LAN 1 -j DROP
for addr in "$LOCAL_V6S"; do
ipt_addr=$(expand_ipv6 "$addr" | sed 's/://g' | sed -E 's/(..)/\1 /g')
echo "Adding rule for $addr ($ipt_addr)"
ip6tables -I OUTBOUND_NA_LAN 1 -m string --hex-string "|$ipt_addr|" --algo bm -j ACCEPT
done
#!/bin/sh
#!/bin/sh
set -e
# load $CWD/.env
CWD=$(dirname $0)
if [ -f $CWD/.env ]; then
source $CWD/.env
fi
### --- IPv6 --- ###
### -- Reference: https://stackoverflow.com/questions/14697403/expand-ipv6-address-in-shell-script
# helper to convert hex to dec (portable version)
hex2dec(){
[ "$1" != "" ] && printf "%d" "$(( 0x$1 ))"
}
# expand an ipv6 address
expand_ipv6() {
ip=$1
# prepend 0 if we start with :
echo $ip | grep -qs "^:" && ip="0${ip}"
# expand ::
if echo $ip | grep -qs "::"; then
colons=$(echo $ip | sed 's/[^:]//g')
missing=$(echo ":::::::::" | sed "s/$colons//")
expanded=$(echo $missing | sed 's/:/:0/g')
ip=$(echo $ip | sed "s/::/$expanded/")
fi
blocks=$(echo $ip | grep -o "[0-9a-f]\+")
set $blocks
printf "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n" \
$(hex2dec $1) \
$(hex2dec $2) \
$(hex2dec $3) \
$(hex2dec $4) \
$(hex2dec $5) \
$(hex2dec $6) \
$(hex2dec $7) \
$(hex2dec $8)
}
### END IPv6 ###
sleep 1;
ip6tables -I INPUT 1 -i $WAN_IFACE -p ipv6-icmp --icmpv6-type 136 -j DROP;
for addr in $GATEWAY_V6 $GATEWAY_V6_T; do
ipt_addr=$(expand_ipv6 "$addr" | sed 's/://g' | sed -E 's/(..)/\1 /g')
echo "Adding rule for $addr ($ipt_addr)"
ip6tables -I INPUT 1 -i $WAN_IFACE -p ipv6-icmp --icmpv6-type 136 -m string --hex-string "|$ipt_addr|" --algo bm -j ACCEPT
done
ip6tables -N OUTBOUND_NA_LAN
ip6tables -I OUTPUT 1 -o $WAN_IFACE -p ipv6-icmp --icmpv6-type 136 -j DROP;
ip6tables -I OUTPUT 2 -o $WAN_IFACE -p ipv6-icmp --icmpv6-type 136 -j OUTBOUND_NA_LAN;
ip -6 neigh flush dev $WAN_IFACE
#!/bin/sh
add_firewall_script(){
if [ ! -f ${2} ]; then
echo "file ${2} not exists"
return
fi
# if the service exists
if [ ! -z $(uci -q get firewall.${1}) ]; then
echo "firewall.${1} already exists"
# exit
return
fi
echo "add firewall.${1} ${2}"
# add the service
uci set firewall.${1}=include
uci set firewall.${1}.type=script
uci set firewall.${1}.path="${2}"
uci set firewall.${1}.enabled=1
# commit the changes
uci commit firewall
}
CWD=$(dirname $0)
FULL_PATH=$(readlink -f "${CWD}/init-ipv6.sh")
echo "Installing to /etc/config/firewall"
add_firewall_script "ipv6_fix" "${FULL_PATH}"
echo "Installing to crontab"
cp /etc/crontabs/root /etc/crontabs/root.bak
FULL_PATH=$(readlink -f "${CWD}/fix-ipv6.sh")
echo "* * * * * test -x ${FULL_PATH} && ${FULL_PATH} > /dev/null 2>&1" >> /etc/crontabs/root
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment