Moi!
Olen jo jonkin aikaa ollut Unifi-mies, ja oon kyllä kovasti tykännyt. Aina on kuitenkin kaihertanut se, että Telian IPv6RD ei ole ollut natiivisti tuettu. No ei se vielä tänäkään päivänä ole, mutta nyt erään löytämäni tuoreen ohjeen sekä ChatGPT:n avulla sain IPv6:n toimimaan. Laitetaan ohje pohjalle, mitä seurasin, ja laitan sen jälkeen Telian kuidun kanssa toimivan skriptin.
Eli tässä ohje, jota seurasin tarkalleen:
sitten 20-centurylink-6rd.sh:n tilalle tuleva skripti, jonka nimesin 20-telia-6rd.sh:ksi. Kaikki credit ChatGPT:lle
Bash:
#!/bin/bash
set -euo pipefail
# Telia Finland 6RD on UDM/UXG (plain SIT, P2P to relay)
# - 6rd prefix: 2001:2003:f400::/38
# - IPv4 mask length: 14
# - Relay (IPv4): 84.251.255.254
#
# Customer /56 = 38 + (32 - 14) = /56
# Assign:
# tunnel -> ...:xx00::1/64
# br0 -> ...:xx01::1/64
# br300 -> ...:xx02::1/64 (if exists)
# ===== Provider parameters =====
IPV6_6RD_PREFIX_HEX_1=0x2001
IPV6_6RD_PREFIX_HEX_2=0x2003
IPV6_6RD_PREFIX_HEX_3=0xF400 # lower 10 bits get filled from IPv4
IPV6_6RD_PREFIX_LEN=38
IPV4_MASKLEN=14
RELAY_V4="84.251.255.254"
# ===== Device parameters (adjust if needed) =====
WAN_IF="eth4" # oma esimerkki
LAN_IF="br0" # oma esimerkki
VLAN300_IF="br300" # optional
# ===== Helpers =====
get_wan_ip() {
ip -4 addr show "$WAN_IF" | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1 || true
}
get_wan_mtu() {
ip -o link show "$WAN_IF" | awk '{for (i=1;i<=NF;i++) if ($i=="mtu") {print $(i+1); exit}}'
}
# ===== Get WAN IPv4 =====
WAN_IP="$(get_wan_ip || true)"
RETRIES=0
while [[ -z "${WAN_IP}" && $RETRIES -lt 30 ]]; do
sleep 2
WAN_IP="$(get_wan_ip || true)"
RETRIES=$((RETRIES+1))
done
if [[ -z "${WAN_IP}" ]]; then
echo "Error: Could not determine WAN IPv4 address on ${WAN_IF}"
exit 1
fi
echo "WAN IPv4: ${WAN_IP}"
# ===== Compute customer /56 from WAN IPv4 (RFC5969) =====
IFS='.' read -r o1 o2 o3 o4 <<< "${WAN_IP}"
ipv4_int=$(( (o1<<24) + (o2<<16) + (o3<<8) + o4 ))
hostbits=$((32 - IPV4_MASKLEN)) # 18
embed_mask=$(( (1<<hostbits) - 1 )) # 0x3FFFF
embed=$(( ipv4_int & embed_mask )) # low 18 bits to embed
# Split 18 bits: top 10 -> finish 3rd hextet, low 8 -> high byte of 4th hextet
embed_top10=$(( embed >> 8 ))
embed_low8=$(( embed & 0xFF ))
h1=${IPV6_6RD_PREFIX_HEX_1}
h2=${IPV6_6RD_PREFIX_HEX_2}
h3=$(( IPV6_6RD_PREFIX_HEX_3 | (embed_top10 & 0x03FF) ))
h4_base=$(( (embed_low8 << 8) & 0xFF00 )) # low byte will be subnet id (0..255)
printf -v CUSTOMER56 " %x:%x:%x:%x::/56 " "$h1" "$h2" "$h3" "$h4_base"
CUSTOMER56="${CUSTOMER56// /}"
echo "Derived /56: ${CUSTOMER56}"
build_prefix64() {
local subnet_id="$1"
local h4=$(( h4_base | (subnet_id & 0xFF) ))
printf "%x:%x:%x:%x::/64" "$h1" "$h2" "$h3" "$h4"
}
TUN64="$(build_prefix64 0)" # ...:xx00::/64 on the tunnel
LAN64="$(build_prefix64 1)" # ...:xx01::/64 on br0
VLAN300_64="$(build_prefix64 2)" # ...:xx02::/64 on br300 (optional)
addr_from_prefix() {
local pfx="$1"
echo "${pfx%/*}1/64" # ::1 inside the /64
}
TUN_ADDR="$(addr_from_prefix "$TUN64")"
LAN_ADDR="$(addr_from_prefix "$LAN64")"
VLAN300_ADDR="$(addr_from_prefix "$VLAN300_64")"
echo "Tunnel /64 : $TUN64 (addr ${TUN_ADDR})"
echo "LAN /64 : $LAN64 (addr ${LAN_ADDR})"
if ip link show "$VLAN300_IF" >/dev/null 2>&1; then
echo "VLAN300 /64: $VLAN300_64 (addr ${VLAN300_ADDR})"
fi
# ===== Reachability sanity (IPv4 to relay) =====
if ping -c 1 -W 1 "$RELAY_V4" >/dev/null 2>&1; then
echo "Relay $RELAY_V4 reachable over IPv4."
else
echo "Warning: Relay $RELAY_V4 not pingable over IPv4 (might still work)."
fi
# ===== Build/refresh plain SIT tunnel to Telia relay (P2P) =====
ip tunnel del 6rd 2>/dev/null || true
ip tunnel add 6rd mode sit local "$WAN_IP" remote "$RELAY_V4" ttl 255
# Compute a conservative MTU (WAN_MTU - 20 for IPv4 header)
WAN_MTU="$(get_wan_mtu || echo 1500)"
TUN_MTU=$(( WAN_MTU - 20 ))
# Keep within sane bounds
if (( TUN_MTU < 1400 )); then TUN_MTU=1400; fi
if (( TUN_MTU > 1480 )); then TUN_MTU=1480; fi
ip link set 6rd mtu "$TUN_MTU" up
# Address on the tunnel /64
ip -6 addr flush dev 6rd scope global || true
ip -6 addr add "$TUN_ADDR" dev 6rd
# ===== ROUTING (IMPORTANT): P2P tunnel ⇒ default route to the DEVICE (no 'via') =====
ip -6 route replace default dev 6rd metric 1024 2>/dev/null || true
# Enable IPv6 forwarding
sysctl -w net.ipv6.conf.all.forwarding=1 >/dev/null
# ===== Assign LAN addresses =====
if ip link show "$LAN_IF" >/dev/null 2>&1; then
ip -6 addr flush dev "$LAN_IF" scope global || true
ip -6 addr add "$LAN_ADDR" dev "$LAN_IF"
fi
if ip link show "$VLAN300_IF" >/dev/null 2>&1; then
ip -6 addr flush dev "$VLAN300_IF" scope global || true
ip -6 addr add "$VLAN300_ADDR" dev "$VLAN300_IF"
fi
echo
echo "6RD configured (MTU ${TUN_MTU}):"
echo " Tunnel: 6rd (${TUN_ADDR}) -> relay ${RELAY_V4}"
echo " Route : default via dev 6rd"
echo " LAN ${LAN_IF}: ${LAN_ADDR}"
if ip link show "$VLAN300_IF" >/dev/null 2>&1; then
echo " VLAN ${VLAN300_IF}: ${VLAN300_ADDR}"
fi
echo
echo "Quick checks:"
ip -6 addr show dev 6rd | sed 's/^/ /'
ip -6 route show | sed 's/^/ /'
echo
echo "Testing IPv6..."
if ping6 -c 2 -W 3 2001:4860:4860::8888 >/dev/null 2>&1; then
echo "✓ ICMPv6 works to Google DNS"
else
echo "✗ ICMPv6 to 2001:4860:4860::8888 failed"
fi
if curl -6 --connect-timeout 5 -s https://ifconfig.co >/dev/null 2>&1; then
echo "✓ HTTPS over IPv6 works"
curl -6 -s ifconfig.co && echo ""
else
echo "✗ HTTPS over IPv6 failed"
fi
# Hints if still failing:
echo
echo "If still failing, verify on UDM/UXG:"
echo " • WAN IN rule allows IPv4 protocol 41 (IPv6-in-IPv4) from ${RELAY_V4}"
echo " • LAN IN allows ICMPv6 and forwarding to WAN"
echo " • No other rule drops protocol 41 on WAN LOCAL"
Jätin tuon vlan300 esimerkin vuoksi. Minulla ei vlaneja ole, mutta LANiin tuli IPv6-osoite oikein nätisti. Muilta osin homma meni niin kuin ohjeessa. Muista käydä hallinnassa tekemässä tuo IPv6:n määrits staattiseksi LANiin, niin tämä skripti korvaa sitten ne määritykset. Mitään palomuurimäärityksiä ei tarvinnut tehdä. Tarvittavat jutut taitavat olla automaattisesti Unifin muurissa.
HUOM: en anna mitään takeita tämän toimivuudesta. Minulla se toimii, ja ajattelin, että joku muukin tätä IPV6:sta kaipaa. Lisäksi jos sinulla vaihtuu IP-osoite, niin tuo skripti pitää kai käsin ajaa uudelleen. Minulla on käytännössä staattinen, vaikka dynaaminen onkin, niin siksi uskallan ajaa tätä näin. En ole bootannut boksia, vaan ajoin skriptit käsin. Sen näkee sitten seuraavan päivityksen yhteydessä, että tuleeko IP automaattisesti. Jos keksitte jotain hienoja parannuksia tähän, niin jakakaa ihmeessä.