|
#!/bin/ksh |
|
# http://internethelp.centurylink.com/internethelp/modem-q1000-ipv6rd.html |
|
# http://undeadly.org/cgi?action=article&sid=20130828151241 |
|
# https://forum.openwrt.org/viewtopic.php?id=37516 |
|
# https://www.reddit.com/r/ipv6/comments/15u4hi/6rd_centurylinkqwest/ |
|
# https://gist.github.com/afresh1/791343380b4410687d51fdd94f20bd42 |
|
|
|
# Put this in root's crontab with -s: |
|
# * * * * * -ns /usr/local/sbin/6rd.sh |
|
|
|
PATH=/usr/bin:/usr/sbin:/bin:/sbin |
|
|
|
if=gif0 |
|
publicif=pppoe0 |
|
set -A int_ifs -- vlan40 vlan41 |
|
|
|
search_domain=home.hewus.com |
|
|
|
# CenturyLink |
|
rdprefix=2602 |
|
rdmask=24 |
|
v4dest=205.171.2.64 |
|
|
|
v4ip='' |
|
while [ -z "$v4ip" -o "$v4ip" = "0.0.0.0" ]; do |
|
v4ip=$( ifconfig $publicif | |
|
sed -ne 's/[[:space:]]*inet[[:space:]]\([^[:space:]]*\).*/\1/p' ) |
|
sleep 1 |
|
done |
|
|
|
if [ "$v4ip" = "0.0.0.0" ]; then |
|
echo "No IP on $publicif" >&2 |
|
exit 1 |
|
fi |
|
|
|
v6ip=$( ifconfig $if | |
|
sed -ne "s/[[:space:]]*inet6[[:space:]]\($rdprefix[^[:space:]]*\).*prefixlen[[:space:]]*\([[:digit:]]*\)/\1\/\2/p" ) |
|
|
|
v6format="$rdprefix:%x:%x%02x:%x" |
|
v6prefix=$( printf ${v6format} $( echo $v4ip | tr '.' ' ' ) ) |
|
v6dest=$( printf ${v6format}00::1 $( echo $v4dest | tr '.' ' ' ) ) |
|
|
|
# The prefix I get to use is the rdmask + the 32 bits of the v4 address |
|
# Some OS's only seem to accept a /64 (linux, macos) |
|
v6external=${v6prefix}00::1/$rdmask |
|
|
|
# We're already configured, don't try again |
|
[ "$v6ip" = "$v6external" ] && exit |
|
|
|
# Lose 20 bytes for the 6rd tunnel |
|
mtu="$( ifconfig "$publicif" | sed -ne 's/.* mtu \([0-9]*\)$/\1/p' )" |
|
#mtu=$(( mtu - 20 )) # trying a smaller mtu |
|
# testing shows that to make it internally, we need a _way_ smaller MTU |
|
#mtu=1232 |
|
|
|
# add "include: /var/unbound/etc/6rd.conf" to the end of unbound.conf |
|
exec 5>/var/unbound/etc/6rd.conf |
|
exec 6>/etc/rad.conf |
|
|
|
#exec 5>/tmp/6rd.conf |
|
#exec 6>/tmp/rad.conf |
|
#route() { true; } |
|
#ifconfig() { true; } |
|
#rcctl() { true; } |
|
|
|
ifconfig $if mtu $mtu |
|
ifconfig $if tunnel $v4ip $v4dest |
|
|
|
# reset any old v6 addresses |
|
route -qn delete -inet6 default |
|
ifconfig $if -inet6 |
|
|
|
cat <<-EOL >&5 |
|
server: |
|
# I have this already configured, you might have to uncomment |
|
#local-zone: "$search_domain." static |
|
local-data: "$( hostname ). IN AAAA ${v6external%/*}" |
|
EOL |
|
|
|
cat <<-EOL >&6 |
|
mtu $mtu |
|
dns { search $search_domain } |
|
|
|
EOL |
|
|
|
ifconfig carp 2>/dev/null | grep -q "status: backup" && |
|
echo "router preference low" >&6 |
|
|
|
integer i=0 |
|
for iif in "${int_ifs[@]}"; do |
|
ifconfig $iif -inet6 |
|
i=$(( i + 1 )) |
|
|
|
# wow this is ugly |
|
typeset -Z5 -i16 ih=$i |
|
v6=${v6prefix}${ih%16#*}${ih#*16#}::1/$(( rdmask + 32 + 8 )) |
|
|
|
echo "$iif $v6" >&2 |
|
ifconfig "$iif" inet6 $v6 |
|
|
|
cat <<-EOL >&5 |
|
interface: ${v6%/*} |
|
access-control: $v6 allow |
|
local-data: "ns$i.$search_domain. IN AAAA ${v6%/*}" |
|
|
|
EOL |
|
|
|
cat <<-EOL >&6 |
|
interface $iif { dns { nameserver ${v6%/*} } } |
|
EOL |
|
done |
|
|
|
5>&- |
|
6>&- |
|
|
|
echo "$if $v6external" >&2 |
|
ifconfig $if inet6 $v6external |
|
route -qn add -inet6 default $v6dest |
|
|
|
rcctl reload rad |
|
rcctl start rad |
|
rcctl restart unbound # reload didn't seem to listen on new interfaces |
I've used tpmr(4) to snoop the traffic between the ISP router and their service to figure out what's going on before, like what VLANs are in use, pppoe or not, or pppoe creds.