|
#!/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 |
hostname.vlan201 should read:
EDIT (Andrew): I fixed it, was using the olde timey
vlandev cnmac0