快速介绍

ipv6地址共 128 位(二进制),转化成16进制共32位, 每4位分成1组, 用分号隔开, 共8组
如果有多个零, 可以省略成 ::, ipv6地址中只能有一个 ::

# 同一组地址
fddd:f00d:cafe:0000:0000:0000:0000:0001  
fddd:f00d:cafe:0:0:0:0:1  
fddd:f00d:cafe::1

前三组是路由前缀
第48-64位(第四个小组)能切割作为不同子网, 和前三组加起来就是子网前缀
后四组64位是给子网内设备分配地址的

2开头的是公网地址, f开头的是内网地址

3大运营商IPv6地址前缀:

  • 中国移动:2409:8000::/20
  • 中国电信:240e::/20
  • 中国联通:2408:8000::/20

ifconfigtemporary是临时地址, 为了安全,

检测v6的网站

获取ipv4 url
http://checkip.dyndns.com
http://4.ipw.cn

获取ipv6 url
http://checkipv6.dyndns.com/
http://6.ipw.cn/

检测优先级
https://ipw.cn/

生成ipv6前缀
https://cd34.com/rfc4193/

获取ipv6-pd

之前能够获取到pd地址, 换了路由后获取不到, 只下发了 /64 的地址, 无法再分配

方案1: 实测有效

添加防火墙规则,允许 ipv6 udp 456 端口和 ipv6 的 igmp 协议进入本设备

方案2:

vim /etc/hotplug.d/iface/99-ipv6
#!/bin/sh
[ "$ACTION" = ifup ] || exit 0
[ "$INTERFACE" = wan ] || exit 0
#sleep 18s 从我的粗略测试来看,有没有这一行都能正常获得我们想要的效果
uci set network.globals.ula_prefix="$(ip -6 route show | grep default | sed -e 's/^.*from //g' | sed 's/ via.*$//g')"
uci commit network
/sbin/ifup lan

chmod a+x /etc/hotplug.d/iface/99-ipv6

重启
# 如果无法升级版本,可以利用策略路由,把来自 WAN 的 IPv6 无脑(删掉 路由到 LAN:
mkdir -p /etc/ppp/ip-up.d
vi /etc/ppp/ip-up.d/00-pppoe-ipv6.sh

# 脚本内容
#!/bin/sh
[ "$1" = "pppoe-wan" ] || exit 0
ip -6 route add default dev br-lan table 6
ip -6 rule add iif $1 lookup 6

# 记得加可执行权限 chmod +x /etc/ppp/ip-up.d/00-pppoe-ipv6.sh

方案3:


vi /etc/hotplug.d/iface/99-ipv6
===
#!/bin/sh
[ "$ACTION" = ifup ] || exit 0
[ "$INTERFACE" = wan ] || exit 0
uci set network.globals.ula_prefix="$(ip -6 route show | grep default | sed -e 's/^.*from //g' | sed 's/ via.*$//g')"
uci commit network
/sbin/ifup lan
===

chmod a+x /etc/hotplug.d/iface/99-ipv6
reboot

设置ipv6

教程: https://post.smzdm.com/p/awzodmpp/?sort_tab=hot%2525252F

添加wan接口

  1. 添加新的接口, 名称填 wwan6 (原来ipv4的接口是wwan), 协议选 dhcpv6, 设备选 接口别名@wwan
  2. 请求ipv6地址选 try, 长度选自动

  1. 高级设置, 委托前缀打勾, 分配长度禁用

  1. 防火墙选 wan
  2. dhcp服务器不开启
  3. 最终获取接口能够获取到v6地址, 如图, 关键是ipv6-pd, :/62(反正小于等于64) 这个地址段, 可以供我们分配

修改lan接口

高级设置

  1. 委托前缀不需要, 因为设备都在路由下, 不需要再切割地址
  2. 分配长度选64
  3. 分配提示不需要(自定义子网的最后一位地址)
  4. 后缀填 ::1


3. 最终如图所示

dhcp服务器

  1. ipv6设置, ra模式选服务器, dhcpv6选服务器(也有的说开了slaac,就不要用dhcpv6, 让设备自己注册), ndp禁用

  1. ipv6ra 设置, 启用slaac, ra标记受管配置, 其他配置

如果没有下发pd

  1. 修改wwan6接口, 配置DHCP服务器
  2. 勾选忽略此接口,并且在IPv6设置里勾选 指定的主接口,RA服务、DHCPv6服务、NDP代理都选择中继模式, 学习路由
  3. 修改lan, DHCP服务器->IPv6设置里同样全部选择中继模式, 学习路由. 不勾选指定主接口

ddns

使用 ddns 插件

教程: https://blog.upx8.com/3110

缺点: 似乎不能批量更新域名, 改为 ddns-go

需要安装的插件 luci-i18n-ddns-zh-cn curl ddns-scripts-cloudflare

使用ddns-go

  1. 用上面的url, 测试自己是否有ipv6
  2. 到cloudflare添加 AAAA 记录

  1. 安装插件 luci-i18n-ddns-go-zh-cn
  2. 先改下端口, 不要用默认的 [::]:1

  1. dns选择 cloudflare, 需要到 cloudflare 设置 token

创建令牌->编辑区域 DNS (使用模板)-->区域资源选择所有区域

ipv4访问ipv6

利用 cloudflare的cdn, 要开启小云朵

ipv4 --> cloudflare CDN --> ipv6

https://mymuwu.net/?p=489

# http 能走cdn的端口
80 8080 8880 2052 2082 2086 2095
# https 能走cdn的端口
443  2053  2083  2087  2096  8443

路由器设置

  1. 防火墙放行对应的ipv6端口

网络 -- 防火墙 -- 通信规则

  1. 端口转发

安装 luci-i18n-socat-zh-cn

添加端口转发, 把ipv6转发到ipv4地址的端口
安装完第一次添加状态是x, 重启下 socat 和 firewall 服务
也可以转发到局域网设备的端口, 这样局域网设备虽然也有ipv6, 但不用ddns, 只需要路由转发就够了

  1. 这样访问时还需要在域名后添加 2052 端口, 利用 cloudflare 的规则可以自动添加

规则 --> Origin Rules --> 创建规则 --> 自定义筛选表达式 --> 主机名等于 --> 重写端口到2052

cloudflare ddns 脚本

https://appscross.com/2023/08/url-redirect-record/

curl --request GET \
  --url https://api.cloudflare.com/client/v4/zones/{ZoneID}/dns_records \
  --header 'Content-Type: application/json' \
  --header 'X-Auth-Email: {Email}' \
  --header 'Authorization: Bearer {Token}' \
  | python3 -m json.tool
#!/bin/sh

cat << EOF > /bin/cf-ddns6.sh
#!/bin/sh
sleep 10
IP6=\$(ip -6 addr show dev {interface} | awk '/global/ {print \$2}' | awk -F "/" '{print \$1}')
if [ -z "\$IP6" ]; then
  exit
fi
response=\$(curl -s -o /dev/null -w %{http_code} --request PUT \
  --url "https://api.cloudflare.com/client/v4/zones/{ZoneID}/dns_records/{RecordID}" \
  --header "Content-Type: application/json" \
  --header "X-Auth-Email: {Email}" \
  --header "Authorization: Bearer {Token}" \
  --data '{
  "type": "AAAA",
  "name": "{Fullname}",
  "content": "'"\$IP6"'",
  "proxied": false
  }')
if [ "\$response" = "200" ]; then
  echo "DNS记录更新成功"
else
  echo "DNS记录更新失败,HTTP状态码: \$response"
fi
EOF
chmod +x /bin/cf-ddns6.sh
  • {interface}: 替换为监测的网络接口,例如 eth0。
  • {ZoneID}: 替换为 Cloudflare 域名所在的区域 ID。
  • {RecordID}: 替换为要更新的 DNS 记录的 ID。
  • {Email}: 替换为你的 Cloudflare 帐户的注册电子邮件地址。
  • {Token}: 替换为你获取的 Cloudflare API  Token。
  • {Fullname}: 替换为要更新的完整主机域名,如ai.xxxx.eu.org
curl -sSL -o ddns6.sh https://raw.githubusercontent.com/evanawn65/appscross/main/generate-cf-ddns6.sh && chmod +x ./ddns6.sh && ./ddns6.sh &&vim /bin/cf-ddns6.sh
sudo nano /etc/NetworkManager/dispatcher.d/99-ip6-address-change

#!/bin/bash
IFACE="$1"
REASON="$2"
if [ "$IFACE" = "eth0" ] && [ "$REASON" = "dhcp6-change" ]; then
    # 调用 DNS 记录更新脚本
    /bin/cf-ddns6.sh
fi

# 赋权、属组、属主设为root
curl -sSL -o /etc/NetworkManager/dispatcher.d/99-ip6-address-change https://github.com/evanawn65/appscross/raw/main/99-ip6-address-change
#!/bin/bash

# 需要jq

#LEDE/Openwrt may need install ca-bundle curl(opkg install ca-bundle curl)

#Add you custom record to the CloudFlare first.

#Your sub domain
SUB_DOMAIN="webdav.shiyitopo.tech"
#dash --> example.com --> Overview --> Zone ID:
#https://dash.cloudflare.com/_your_account_id_/example.com
ZONE_ID=""
#API Tokens
#https://dash.cloudflare.com/profile/api-tokens
#Manage access and permissions for your accounts, sites, and products
#example.com- Zone:Read, DNS:Edit
TOKEN_ID=""
#The path of jq binaries . Download from https://stedolan.github.io/jq/download/
#If the system has installed jq. Just typed jq.
#If you custom a special binary. Just type the path of jq
JQ_PATH="/root/jq-linux64"

if [ -n "$DNS_ZONE_ID" ]; then
    echo "The user has not configure the the ZONE ID "
    exit 1
fi

echo "Your dns zone id is: $ZONE_ID"
jsonResult=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
    -H "Authorization: Bearer ${TOKEN_ID}" \
    -H "Content-Type: application/json")

curlResult=$(echo $jsonResult | $JQ_PATH -r .success)

if [ "$curlResult" = true ]; then
    echo "Get dns record success."
else
    echo "Get dns record fail.$jsonResult"
    exit 1
fi

recordSize=$(echo $jsonResult | $JQ_PATH .result | $JQ_PATH length)
echo "Total found $recordSize record"

index=0
while [ $index -lt $recordSize ]; do
    tResult=$(echo $jsonResult | $JQ_PATH -r .result[$index])
    tmpDomain=$(echo $tResult | $JQ_PATH -r .name)
    type=$(echo $tResult | $JQ_PATH -r .type)

    if [ "$tmpDomain"x = "$SUB_DOMAIN"x ]; then
        if [ "AAAA"x = "$type"x ]; then
            echo "Found AAAA domain:$tmpDomain"
            identifier_v6=$(echo $tResult | $JQ_PATH -r .id)
        elif [ "A"x = "$type"x ]; then
            echo "Found A domain:$tmpDomain"
            identifier_v4=$(echo $tResult | $JQ_PATH -r .id)
        else
            echo "Please add the A or AAAA record manually first."
        fi
    fi
    index=$(expr $index + 1)
done

if [ -z "$identifier_v4" ] && [ -z "$identifier_v6" ]; then
    echo "Get '$SUB_DOMAIN' identifier failed. Please add the A or AAAA record manually first."
    exit 1
else
    echo "Get '$SUB_DOMAIN' identifier success. [A] identifier:$identifier_v4 [AAAA] identifier:$identifier_v6"
fi

if [ -z "$identifier_v4" ]; then
    echo "IPv4 address are not required."
else
    #IP=$(curl -s http://members.3322.org/dyndns/getip)
    IP=$(curl -s http://ip.3322.net/)
    regex='\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}\b'
    matchIP=$(echo $IP | grep -E $regex)
    if [ -n "$matchIP" ]; then
        echo "[$IP] IPv4 matches..."
        jsonResult=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${identifier_v4}" \
            -H "Authorization: Bearer ${TOKEN_ID}" \
            -H "Content-Type: application/json" \
            --data '{"type":"A","name":"'${SUB_DOMAIN}'","content":"'${IP}'","ttl":1,"proxied":false}')
        curlResult=$(echo $jsonResult | $JQ_PATH -r .success)

        if [ "$curlResult" = true ]; then
            echo "Update IPv4 dns record success."
        else
            echo "Update IPv4 dns record fail."
        fi
    else
        echo "[$IP]IPv4 doesn't match!"
    fi
fi

if [ -z "$identifier_v6" ]; then
    echo "IPv6 addresses are not required."
else
    #IP=$(curl -6 ip.sb)
    IP=$(ip addr show dev  ens18|sed -e's/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d'|grep 2409|head -1)
    regex='^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$'
    matchIP=$(echo $IP | grep -E $regex)
    if [ -n "$matchIP" ]; then
        echo "[$IP] IPv6 matches..."
        echo "Update IPv6 ..."
        jsonResult=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${identifier_v6}" \
            -H "Authorization: Bearer ${TOKEN_ID}" \
            -H "Content-Type: application/json" \
            --data '{"type":"AAAA","name":"'${SUB_DOMAIN}'","content":"'${IP}'","ttl":1,"proxied":true}')
        curlResult=$(echo $jsonResult | $JQ_PATH -r .success)

        if [ "$curlResult" = true ]; then
            echo "Update IPv6 dns record success."
        else
            echo "Update IPv6 dns record fail."
        fi
    else
        echo "[$IP] IPv6 doesn't match!"
    fi
fi

ipv4优先

vim /etc/gai.conf

precedence ::ffff:0:0/96  200

配置Openwrt无线中继随身WIFI,IPv6NAT

https://post.smzdm.com/p/ad9qkz9k/

https://zhuanlan.zhihu.com/p/492774540?utm_id=0

https://gitlab.com/XDOSC/WIFI/-/wikis/tips/ipv-6-router

要下载的那个脚本

#!/bin/sh /etc/rc.common
# NAT6 init script for OpenWrt // Depends on package: kmod-ipt-nat6

# edited by Sad Pencil at 2020-02-09
# replace route command with ip command to solve issues on new OpenWRT


# edited by Sad Pencil at 2021-11-29
# update line WAN6_INTERFACE=$(uci get "network.$WAN6_NAME.device" || uci get "network.$WAN6_NAME.ifname")


START=55

# Options
# -------

# Use temporary addresses (IPv6 privacy extensions) for outgoing connections? Yes: 1 / No: 0
PRIVACY=1

# Maximum number of attempts before this script will stop in case no IPv6 route is available
# This limits the execution time of the IPv6 route lookup to (MAX_TRIES+1)*(MAX_TRIES/2) seconds. The default (15) equals 120 seconds.
MAX_TRIES=15

# An initial delay (in seconds) helps to avoid looking for the IPv6 network too early. Ideally, the first probe is successful.
# This would be the case if the time passed between the system log messages "Probing IPv6 route" and "Setting up NAT6" is 1 second.
DELAY=5

# Logical interface name of outbound IPv6 connection
# There should be no need to modify this, unless you changed the default network interface names
# Edit by Vincent: I never changed my default network interface names, but still I have to change the WAN6_NAME to "wan" instead of "wan6"
WAN6_NAME="wan6"

# ---------------------------------------------------
# Options end here - no need to change anything below

boot() {
        [ $DELAY -gt 0 ] && sleep $DELAY
        WAN6_INTERFACE=eth1
        logger -t NAT6 "Probing IPv6 route"
        PROBE=0
        COUNT=1
        while [ $PROBE -eq 0 ]
        do
                if [ $COUNT -gt $MAX_TRIES ]
                then
                        logger -t NAT6 "Fatal error: No IPv6 route found (reached retry limit)" && exit 1
                fi
                sleep $COUNT
                COUNT=$((COUNT+1))
                PROBE=$(ip -6 route | grep -i '^default.*via' | grep -i -F "dev $WAN6_INTERFACE" | grep -i -o 'via.*' | wc -l)
        done

        logger -t NAT6 "Setting up NAT6"

        if [ -z "$WAN6_INTERFACE" ] || [ ! -e "/sys/class/net/$WAN6_INTERFACE/" ] ; then
                logger -t NAT6 "Fatal error: Lookup of $WAN6_NAME interface failed. Were the default interface names changed?" && exit 1
        fi
        WAN6_GATEWAY="2001:da8:xxxx:xxxx::1"
        if [ -z "$WAN6_GATEWAY" ] ; then
                logger -t NAT6 "Fatal error: No IPv6 gateway for $WAN6_INTERFACE found" && exit 1
        fi
        LAN_ULA_PREFIX=$(uci get network.globals.ula_prefix)
        if [ $(echo "$LAN_ULA_PREFIX" | grep -c -E "^([0-9a-fA-F]{4}):([0-9a-fA-F]{0,4}):") -ne 1 ] ; then
                logger -t NAT6 "Fatal error: IPv6 ULA prefix $LAN_ULA_PREFIX seems invalid. Please verify that a prefix is set and valid." && exit 1
        fi

        ip6tables -t nat -I POSTROUTING -s "$LAN_ULA_PREFIX" -o "$WAN6_INTERFACE" -j MASQUERADE
        if [ $? -eq 0 ] ; then
                logger -t NAT6 "Added IPv6 masquerading rule to the firewall (Src: $LAN_ULA_PREFIX - Dst: $WAN6_INTERFACE)"
        else
                logger -t NAT6 "Fatal error: Failed to add IPv6 masquerading rule to the firewall (Src: $LAN_ULA_PREFIX - Dst: $WAN6_INTERFACE)" && exit 1
        fi

        ip -6 route add 2000::/3 via "$WAN6_GATEWAY" dev "$WAN6_INTERFACE"
        if [ $? -eq 0 ] ; then
                logger -t NAT6 "Added $WAN6_GATEWAY to routing table as gateway on $WAN6_INTERFACE for outgoing connections"
        else
                logger -t NAT6 "Error: Failed to add $WAN6_GATEWAY to routing table as gateway on $WAN6_INTERFACE for outgoing connections"
        fi

        if [ $PRIVACY -eq 1 ] ; then
                echo 2 > "/proc/sys/net/ipv6/conf/$WAN6_INTERFACE/accept_ra"
                if [ $? -eq 0 ] ; then
                        logger -t NAT6 "Accepting router advertisements on $WAN6_INTERFACE even if forwarding is enabled (required for temporary addresses)"
                else
                        logger -t NAT6 "Error: Failed to change router advertisements accept policy on $WAN6_INTERFACE (required for temporary addresses)"
                fi
                echo 2 > "/proc/sys/net/ipv6/conf/$WAN6_INTERFACE/use_tempaddr"
                if [ $? -eq 0 ] ; then
                        logger -t NAT6 "Using temporary addresses for outgoing connections on interface $WAN6_INTERFACE"
                else
                        logger -t NAT6 "Error: Failed to enable temporary addresses for outgoing connections on interface $WAN6_INTERFACE"
                fi
        fi

        exit 0
}


image-20240204134135263