スキップしてメイン コンテンツに移動

フレッツ光クロス固定IP(V6プラス)にてDHCPCDをつかってプレフィックス変更に備える

フレッツ光クロス固定IP(enひかりクロス+V6プラス固定IP)でDebianを使ったLinuxルータを運用し、本稿執筆時点で一年2か月ほど使っているのですが、二か月ほど前(ちょうど一年たったころ)IPv6プレフィックスが変更され通信できなくなった経験がありました。
当初は何が起こったのか分からなかったのですが、その時はdhclientを使っていてデバッグモードで立ち上げると新しいプレフィックスが降りてきたことが確認できました。半固定というより、突然だったので動的だよなこれ、と思ったのは言うまでもありません。
その後、スクリプトなどを順に追っていって無事IPv6/IPv4ともに通信できましたが、今後もIPv6プレフィックスが変更されうると想定しておく方がよいと思い、サーバにはGUAを割り当てずULAのみにし、また、dhclientでは対応が難しい(dhcpv6サーバからのReconfigure messageに対してlogにメッセージを吐くだけ)ので、Reconfigure messageに対してリアクションができるdhcpcdに切り替えました。
ただ、プレフィックスの変更があった場合、このルータ上ではdhcpcdがルータのIPv6設定を更新しIPv6通信はできるのですが、IPv4通信などはプレフィックスが変更されるのでIP4IP6トンネルが無効になり、IPv4での通信ができなくなります。
他にも、dhcpサーバも配布するGUAが変更されるので、設定ファイルの書き換え・再起動が必要になります。/etc/radvd.confも同じで書き換えてradvdを再起動させる必要があります。また、ULAを使っている場合は、nftablesのルールも書き換える必要があります。さらにサブルータを使っている場合は、サブルータの設定も変更しなければなりません。
このようにIPv6 GUAプレフィックス変更時の対応は思った以上に大変で、手動で変更するには時間的にも手数的にも限界があると思います。

そこでIPv6プレフィックスの変更について、dhcpcdには色々なreasonのeventをhookで処理できるのでどのような対応ができるか調べたところ、RECONFIGURE6はlogにメッセージを吐くだけですが、RECONFIGURE6が発生した直後にreason=RENEW6でアドレスの更新が行われることがわかりました。(RFC3315のReconfigure については、本来ならもう少し異なる状況があり得るのですが、とりあえずRENEW6に着目することにしました。)この場合、新プレフィックスと旧プレフィックスが異なるとこれはRECONFIGURE6に対応したRENEW6だったという事がわかり、プレフィックスの変更処理をすることが出来そうなので本稿を挙げた次第です。
なお、ルータの再起動時はBOUND6というイベントでアドレスを取得できているので、まずは、以下の様な方針で処理することにしました。

1. 起動時、dhcpcd イベント発生時、reason="BOUND6"の場合、hookスクリプトで対応する処理を記述する。
2. 起動後、dhcpcd イベント発生時、reason="RENEW6"の場合でかつ new_dhcp6_ia_pd1_prefix1とold_dhcp6_ia_pd1_prefix1が異なる場合、プレフィックス変更が行われたとみなし、hookスクリプト内で対応する処理を記述する。

また、検討したところ、hookスクリプト自身は最小限に近い処理をし、対応するスクリプトを呼び出す方法をとることにしました。

まず、dhcpcdのインストールと設定です。dhcpcdのインストールは、以下の様にしました。
apt-get install dhcpcd
dpkg -P isc-dhcp-client
参考までに、必要最小限の/etc/apt/sources.listは以下の通りです。この場合、IPv4での通信ができなくてもipv6でパッケージを取得できます。
deb http://deb.debian.org/debian bookworm main non-free-firmware non-free contrib
また/etc/resolv.confも下記の様に最小限にしておけば、IPv6で名前解決できますので、nameserverを取得できなかった場合などの参考にしてください。
nameserver 2606:4700:4700::1111
nameserver 2606:4700:4700::1001
/etc/dhcpcd.confは以下の通りで、enp1s0f0がLAN側でenp1s0f1がWAN側です。
duid ll
noipv6rs
noipv4ll

denyinterfaces enp1s0f0

option dhcp6_reconfigure_msg, dhcp6_reconfigure_accept, dhcp6_name_servers, dhcp6_domain_search
nooption dhcp6_sol_max_rt, dhcp6_inf_max_rt, dhcp6_vivco

interface enp1s0f1
    ipv6rs
    ia_pd 0/::/56 enp1s0f0/0/56
つづいてkea-dhcp6.confやradvd.confといった変更対象ファイルに対しdhcpcdが読み書きできるようにしておきます。
ReadWritePaths=/var/lib/dhcpcd /run/dhcpcd /etc/wpa_supplicant /etc/dhcpcd.conf /etc/resolv.conf /etc/kea/kea-dhcp6.conf /etc/radvd.conf
許可を与えたら、 systemctl daemon-reload としてサービス内容を更新します。
dhcpcdの設定は以上ですが、現在のIPv6プレフィックス情報を記述しておきます。systemctl で dhcpcdを呼び出すとjournalctl -u dhcpcdでプレフィックス情報がわかるのですが、直接以下の様 dhcpcd を単独で呼び出しても、プレフィックス情報がわかります。(どちらでも構いません。)
dhcpcd -k
dhcpcd

dhcpcd-9.4.1 starting
dev: loaded udev
DUID 00:03:00:01:0c:11:22:33:44:25
enp3s0: waiting for carrier
enp1s0f1: IAID aa:bb:cc:dd
enp1s0f1: IA type 25 IAID 00:00:00:00
enp1s0f1: adding address fe80::e22:22ff:fe33:4425
enp1s0f1: soliciting an IPv6 router
enp1s0f1: soliciting a DHCPv6 lease
enp1s0f0: activating for delegation
enp1s0f0: IAID aa:bb:cc:dd
enp1s0f1: Router Advertisement from fe80::16aa:bbff:fecc:dd8a
enp1s0f1: adding default route via fe80::16aa:bbff:fecc:dd8a
enp1s0f1: soliciting a DHCP lease
enp1s0f1: ADV 2xxx:yyyy:zzzz:1600::/56 from fe80::16aa:bbff:fecc:dd8a
(以下略)
ADV 2xxx:yyyy:zzzz:1600::/56が降りてきたPDです。これを今回は以下の様にして/var/lib/dhcpcd/prefix.confに保存してください。
dhcp6_ia_pd1_prefix1=2xxx:yyyy:zzzz:1600::
dhcp6_ia_pd1_prefix1_length=56
つづいて前述の起動時のreason="BOUND6"の場合の処理です。これは、これまで/etc/rc.localで呼び出していた処理をほぼそのまま呼び出すhookで良いので以下の様にしてみました。
######## /lib/dhcpcd/dhcpcd-hooks/10-boot-time

case "$reason" in
    BOUND6)
        /usr/local/sbin/init-v6p-static.sh $new_dhcp6_ia_pd1_prefix1 $new_dhcp6_ia_pd1_prefix1_length
        ;;
esac
呼び出されるスクリプトは init-v6p-static.sh (chmod 700) で以下の通りです。
######## /usr/local/sbin/init-v6p-static.sh

#!/bin/sh

if [ $# -ne 2 ];then
    echo "Usage: $0 NEW_PREFIX NEW_PREFIX_LEN";
    exit 1
fi

NEW_PREFIX=$1
NEW_PREFIX_LEN=$2

ULA=fd98:1:1::/56
ULA_PFX=`echo $ULA | awk -F'::' '{print $1}'`

PREFIX_CONF=/var/lib/dhcpcd/prefix.conf

# get last prefix from $PREFIX_CONF
OLD_PREFIX=`cat $PREFIX_CONF | grep dhcp6_ia_pd1_prefix1= | awk -F'=' '{print $2}'`
OLD_PREFIX_LEN=`cat $PREFIX_CONF | grep dhcp6_ia_pd1_prefix1_length | awk -F'=' '{print $2}'`

# OLD_PREFIXを/$OLD_PREFX_LENで表記した場合、たとえば、2111:2222:3333:4444::/56は2111:2222:3333:4400::/56と訂正し比較する
# また、2111:2222:3333:4444:5555::/80の場合でも2111:2222:3333:4400::/56と訂正し比較する。(サブルータでの対応の為)

OLD_GUA=$OLD_PREFIX

HEXTET_3RD_OLD=`echo $OLD_GUA | awk -F':' '{print $3}'`
HEXTET_4TH_OLD=`echo $OLD_GUA | awk -F':' '{print $4}'`

if [ "" = "$HEXTET_3RD_OLD" ]; then
        OLD=`echo $OLD_GUA | awk -F'::' '{print $1}'`
else
        OLD_GUA_48=`echo $OLD_GUA | awk -F":" '{print $1 ":" $2 ":" $3}'`
        case $HEXTET_4TH_OLD in
                ????)
                        TMP=`echo $HEXTET_4TH_OLD | cut -c 1-2`
                        OLD=$OLD_GUA_48:$TMP
                        OLD_ZZ=00
                        ;;
                ???)
                        TMP=`echo $HEXTET_4TH_OLD | cut -c 1`
                        OLD=$OLD_GUA_48:$TMP
                        OLD_ZZ=00
                        ;;
                "")
                        OLD=$OLD_GUA_48
                        OLD_ZZ=
                        ;;
        esac
fi

OLD_PREFIX=$OLD$OLD_ZZ::

if [ "$OLD_PREFIX" != "$NEW_PREFIX" ]; then
	prefix_has_been_changed=1
else
	prefix_has_been_changed=0
fi

###### 以下、プロバイダからの設定情報を代入
UPDT_URL=http://xxx.enabler.ne.jp/update
USER=username
PASS=password

IFID=0011:2233:4400:0000
IP4=1.1.1.1
BR=2111:2222:3333:4400::55
###### プロバイダからの設定情報は以上

WANDEV=enp1s0f1
LANDEV=enp1s0f0
TUNDEV='tun0'

TUN_MTU=1460

PFX=$1/$2
PREFIX=`echo $PFX | awk 'BEGIN{FS="::"}{print $1}'`
GW_PLEN=$2

GW=23
CE=$PREFIX:$IFID
CE_PLEN=$GW_PLEN

ip -6 addr add $CE/$CE_PLEN dev $LANDEV
ip -6 tunnel add $TUNDEV mode ip4ip6 remote $BR local $CE dev $LANDEV encaplimit none

ip link set dev $TUNDEV mtu $TUN_MTU
ip link set dev $TUNDEV up
ip -4 addr add $IP4/32 dev $TUNDEV

ip route delete default
ip route add default dev $TUNDEV

curl "$UPDT_URL?user=$USER&pass=$PASS"

iptables -t nat -F
iptables -t mangle -F

iptables -t mangle -o $TUNDEV -I FORWARD 1 -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:65495 -j TCPMSS --clamp-mss-to-pmtu

# MASQUERADE
iptables -t nat -A POSTROUTING -o $TUNDEV -j MASQUERADE

# FULLCONENAT
#iptables -t nat -A PREROUTING -i $TUNDEV -j FULLCONENAT
#iptables -t nat -A POSTROUTING -o $TUNDEV -j FULLCONENAT

nft add table ip6 nat66
nft add chain ip6 nat66 PREROUTING { type nat hook prerouting priority dstnat\; policy accept\; }
nft add chain ip6 nat66 INPUT { type nat hook input priority 100\; policy accept\; }
nft add chain ip6 nat66 OUTPUT { type nat hook output priority -100\; policy accept\; }
nft add chain ip6 nat66 POSTROUTING { type nat hook postrouting priority srcnat\; policy accept\; }

nft insert rule ip6 nat66 PREROUTING  iifname "${WANDEV}" oifname "${LANDEV}" dnat ip6 prefix to ip6 daddr map { "${PFX}" : "${ULA}" }
nft insert rule ip6 nat66 POSTROUTING iifname "${LANDEV}" oifname "${WANDEV}" snat ip6 prefix to ip6 saddr map { "${ULA}" : "${PFX}" }

if [ "$prefix_has_been_changed" = "1" ];then
	# 最初に /var/lib/dhcpcd/prefix.confを更新しておく
  /usr/local/sbin/renew-conf-prefix.sh $OLD_PREFIX $NEW_PREFIX /var/lib/dhcpcd/prefix.conf
  
    # /etc/radvd.confを更新し、radvdをリスタート
    /usr/local/sbin/renew-conf-prefix.sh $OLD_PREFIX $NEW_PREFIX /etc/radvd.conf
    systemctl restart radvd

	# /etc/kea/kea-dhcp6.confを更新し、kea-dhcpcd-confをリスタート
    /usr/local/sbin/renew-conf-prefix.sh $OLD_PREFIX $NEW_PREFIX /etc/kea/kea-dhcp6.conf
    systemctl restart kea-dhcp6-server
fi
ルータ起動後のDHCPCDイベントBOUND6時のスクリプトは以上です。
続いてBOUND6とRENEW6で共通使用するスクリプトです。/usr/local/sbin/renew-conf-prefix.sh として保存します。(chmod +x 要)
#!/bin/sh

if [ $# -ne 3 ];then
    echo "Usage: $0 OLD_GUA NEW_GUA TARGET_CONF";
    exit 1
fi

replace_file()
{
    if [ -e "$1" ]; then
        if comp_file "$1" "$2"; then
            echo comp_file "$1" "$2" same > /var/lib/dhcpcd/msgs.txt
            rm -f "$2"
            return 1
        fi
    fi
    cat "$2" > "$1"
    rm -f "$2"
    return 0
}

OLD_GUA=$1
NEW_GUA=$2
TARGET_CONF=$3

# backup TARGET_CONF before processing.
FILENAME=$(basename $TARGET_CONF)
cp -a $TARGET_CONF /var/lib/dhcpcd/$FILENAME.`date '+%Y_%m_%d-%H:%M:%S'`

# copy $TARGET_CONF /var/lib/dhcpcd/$FILENAME
cp -a $TARGET_CONF /var/lib/dhcpcd/$FILENAME

TARGET_WRK=/var/lib/dhcpcd/$FILENAME

HEXTET_1ST_NEW=`echo $NEW_GUA | awk -F':' '{print $1}'`
HEXTET_1ST_OLD=`echo $OLD_GUA | awk -F':' '{print $1}'`

HEXTET_2ND_NEW=`echo $NEW_GUA | awk -F':' '{print $2}'`
HEXTET_2ND_OLD=`echo $OLD_GUA | awk -F':' '{print $2}'`

HEXTET_3RD_NEW=`echo $NEW_GUA | awk -F':' '{print $3}'`
HEXTET_3RD_OLD=`echo $OLD_GUA | awk -F':' '{print $3}'`

HEXTET_4TH_NEW=`echo $NEW_GUA | awk -F':' '{print $4}'`
HEXTET_4TH_OLD=`echo $OLD_GUA | awk -F':' '{print $4}'`

if [ "" = "$HEXTET_3RD_NEW" ];then
    NEW=`echo $NEW_GUA | awk -F'::' '{print $1}'`:0:0:
else
    NEW_GUA_48=`echo $NEW_GUA | awk -F":" '{print $1 ":" $2 ":" $3}'`
    case $HEXTET_4TH_NEW in
        ????)
            TMP=`echo $HEXTET_4TH_NEW | cut -c 1-2`
            NEW=$NEW_GUA_48:$TMP
            NEW_ZZ=00
            ;;
        ???)
            TMP=`echo $HEXTET_4TH_NEW | cut -c 1`
            NEW=$NEW_GUA_48:$TMP
            NEW_ZZ=00
            ;;
        "")
            NEW=$NEW_GUA_48
            NEW_ZZ=
            ;;
    esac
fi

if [ "" = "$HEXTET_3RD_OLD" ]; then
    OLD=`echo $OLD_GUA | awk -F'::' '{print $1}'`
else
    OLD_GUA_48=`echo $OLD_GUA | awk -F":" '{print $1 ":" $2 ":" $3}'`
    case $HEXTET_4TH_OLD in
        ????)
            TMP=`echo $HEXTET_4TH_OLD | cut -c 1-2`
            OLD=$OLD_GUA_48:$TMP
            OLD_ZZ=00
            ;;
        ???)
            TMP=`echo $HEXTET_4TH_OLD | cut -c 1`
            OLD=$OLD_GUA_48:$TMP
            OLD_ZZ=00
            ;;
        "")
            OLD=$OLD_GUA_48
            OLD_ZZ=
            ;;
    esac
fi

TMP2=:0:0:
TMP1=:0:

sed -i "s/$OLD$TMP2/$NEW/g" $TARGET_WRK
sed -i "s/$OLD$TMP1/$NEW/g" $TARGET_WRK

if [ "$HEXTET_1ST_OLD" = "$HEXTET_1ST_NEW" ] && [ "$HEXTET_2ND_OLD" = "$HEXTET_2ND_NEW" ];then
    if [ "$HEXTET_3RD_OLD" != "" ]; then
        if [ "$HEXTET_4TH_OLD" != "" ]; then
            if [ "$HEXTET_3RD_NEW" != "" ];then
                if [ "$HEXTET_4TH_NEW" != "" ];then
                    #echo DL1aa HEXTET_4TH_NEW:$HEXTET_4TH_NEW $OLD $NEW
                    sed -i "s/$OLD/$NEW/g" $TARGET_WRK
                else
                    #echo DL1ab HEXTET_4TH_NEW:$HEXTET_4TH_NEW $OLD $NEW
                    sed -i "s/$OLD/$NEW:/g" $TARGET_WRK
                fi
            else
                #echo DL1b
                sed -i "s/$OLD/$NEW/g" $TARGET_WRK
            fi
        else
            #echo DL2
            # 2111:2222:3333:40:: to 2aaa:bbbb:cccc:dd40::
            sed -i "s/$OLD:/$NEW/g" $TARGET_WRK
            # correct 2aaa:bbbb:cccc:dd: to 2aaa:bbbb:cccc:dd00::
            ZZ=00
            sed -i "s/$NEW:/$NEW$ZZ::/g" $TARGET_WRK
        fi
    else
        #echo DL3
        sed -i "s/$OLD::/$NEW$NEW_ZZ::/g" $TARGET_WRK
    fi
else
    if [ "$HEXTET_3RD_OLD" = "" ];then
        if [ "$HEXTET_4TH_OLD" = "" ];then
            if [ "$HEXTET_3RD_NEW" != "" ];then
                if [ "$HEXTET_4TH_NEW" != "" ];then
                    #echo DL4a
                    sed -i "s/$OLD$OLD_ZZ/$NEW$NEW_ZZ/g" $TARGET_WRK
                    sed -i "s/$OLD/$NEW/g" $TARGET_WRK
                else
                    #echo DL4b $OLD $NEW
                    sed -i "s/$OLD/$NEW:/g" $TARGET_WRK
                    # correct 2111:2222:3333110:: to 2111:2222:3333:110::
                    sed -i "s/$NEW/$NEW:/g" $TARGET_WRK
                fi
            else
                #echo DL4c $OLD $NEW
                sed -i "s/$OLD::/$NEW::/g" $TARGET_WRK
            fi
        else
            :
            #echo DL4d: $OLD_GUA $NEW_GUA
        fi
    else
        if [ "$HEXTET_4TH_OLD" = "" ];then
            if [ "$HEXTET_3RD_NEW" != "" ];then
                if [ "$HEXTET_4TH_NEW" != "" ];then
                    #echo DL5a $OLD $NEW
                    sed -i "s/$OLD/$NEW/g" $TARGET_WRK
                    # correct 2111:2222:3333:16:: to 2111:2222:3333:1600::
                    ZZ=00
                    sed -i "s/$NEW/$NEW$ZZ/g" $TARGET_WRK
                    # ocrrect 2111:2222:3333:1600:10:: 2111:2222:3333:1610::
                    sed -i "/$NEW$ZZ::/!s/$NEW$ZZ:/$NEW/g" $TARGET_WRK
                else
                    #echo DL5b
                    # ex "2111:2222:0":10: to "2aaa:bbbb:cccc:dd"10:
                    sed -i "s/$HEXTET_1ST_OLD:$HEXTET_2ND_OLD:$HEXTET_3RD_OLD:/$NEW/g" $TARGET_WRK
                    # correct 2aaa:bbbb:cccc:dd: to 2aaa:bbbb:cccc:dd00::
                    ZZ=00
                    sed -i "s/$NEW:/$NEW$ZZ::/g" $TARGET_WRK

                fi
            else
               #echo DL5c
               # 2111:2222:3333 2aaa:bbbb
               sed -i "s/$OLD/$NEW/g" $TARGET_WRK
            fi
        else
            #echo DL6
            sed -i "s/$OLD$OLD_ZZ/$NEW$NEW_ZZ/g" $TARGET_WRK
            sed -i "s/$OLD/$NEW/g" $TARGET_WRK
        fi
    fi
fi

sed -i "/duid\|hw-address/!s/:00:/:/g" $TARGET_WRK
sed -i "s/:0:0::/::/g" $TARGET_WRK
sed -i "s/:0::/::/g" $TARGET_WRK
sed -i "s/:::/::/g" $TARGET_WRK

if replace_file $TARGET_CONF "$TARGET_WRK"; then
    chmod 644 $TARGET_CONF
fi

exit 0

次はルーター起動中のDHCPCDイベントRENEW時でprefixの変更があった場合(つまりRECONFIGURE6でプレフィックスの変更があった場合)の処理です。
まずは、dhcpcdでのhookを記述しておきます。
######## /lib/dhcpcd/dhcpcd-hooks/15-reconfigure6

case "$reason" in
	RENEW6)
		if [ "$new_dhcp6_ia_pd1_prefix1" != "$old_dhcp6_ia_pd1_prefix1" ];then
			p1=$new_dhcp6_ia_pd1_prefix1
			p2=$new_dhcp6_ia_pd1_prefix1_length
			p3=$old_dhcp6_ia_pd1_prefix1
			p4=$old_dhcp6_ia_pd1_prefix1_length
			/usr/local/sbin/reconfigure-v6p-static.sh $p1 $p2 $p3 $4
		fi
		;;
esac
続いて呼び出される /usr/local/sbin/reconfigure-v6p-static.sh (chmod 700) です。
######## /usr/local/sbin/reconfigure-v6p-static.sh
#!/bin/sh

if [ $# -ne 4 ];then
    echo "Usage: $0 NEW_PREFIX NEW_PREFIX_LEN OLD_PREFIX OLD_PREFIX_LEN";
    exit 1
fi

NEW_PREFIX=$1
NEW_PREFIX_LEN=$2

ULA=fd98:1:1::/56
ULA_PFX=`echo $ULA | awk -F'::' '{print $1}'`

# ULA address for LANDEV to restore. 
LANDEV_ULA=fd98:1:1::23/56

###### 以下、プロバイダからの設定情報を代入
UPDT_URL=http://xxx.enabler.ne.jp/update
USER=username
PASS=password

IFID=0011:2233:4400:0000
IP4=1.1.1.1
BR=2111:2222:3333:4400::55
###### プロバイダからの設定情報は以上

WANDEV=enp1s0f1
LANDEV=enp1s0f0
TUNDEV='tun0'

TUN_MTU=1460
GW_PLEN=$2
GW=23

PFX=$1/$2
PREFIX=`echo $PFX | awk 'BEGIN{FS="::"}{print $1}'`

CE=$PREFIX:$IFID
CE_PLEN=$GW_PLEN

OLD_PFX=$3/$4
OLD_PREFIX=`echo $OLD_PFX | awk 'BEGIN{FS="::"}{print $1}'`

OLD_CE=$OLD_PREFIX:$IFID
OLD_CE_PLEN=$GW_PLEN

# delete old tunnel
ip -6 tunnel del $TUNDEV
# delete old CE address
ip -6 addr del $OLD_CE/$OLD_CE_PLEN dev $LANDEV 

# add new CE address
ip -6 addr add $CE/$CE_PLEN dev $LANDEV
# add new tunnel
ip -6 tunnel add $TUNDEV mode ip4ip6 remote $BR local $CE dev $LANDEV encaplimit none

ip link set dev $TUNDEV mtu $TUN_MTU
ip link set dev $TUNDEV up
ip -4 addr add $IP4/32 dev $TUNDEV

ip route delete default
ip route add default dev $TUNDEV

curl "$UPDT_URL?user=$USER&pass=$PASS"

iptables -t nat -F
iptables -t mangle -F

iptables -t mangle -o $TUNDEV -I FORWARD 1 -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:65495 -j TCPMSS --clamp-mss-to-pmtu

# MASQUERADE
iptables -t nat -A POSTROUTING -o $TUNDEV -j MASQUERADE

# FULLCONENAT
#iptables -t nat -A PREROUTING -i $TUNDEV -j FULLCONENAT
#iptables -t nat -A POSTROUTING -o $TUNDEV -j FULLCONENAT

nft delete table ip6 nat66

nft add table ip6 nat66
nft add chain ip6 nat66 PREROUTING { type nat hook prerouting priority dstnat\; policy accept\; }
nft add chain ip6 nat66 INPUT { type nat hook input priority 100\; policy accept\; }
nft add chain ip6 nat66 OUTPUT { type nat hook output priority -100\; policy accept\; }
nft add chain ip6 nat66 POSTROUTING { type nat hook postrouting priority srcnat\; policy accept\; }

nft insert rule ip6 nat66 PREROUTING  iifname "${WANDEV}" oifname "${LANDEV}" dnat ip6 prefix to ip6 daddr map { "${PFX}" : "${ULA}" }
nft insert rule ip6 nat66 POSTROUTING iifname "${LANDEV}" oifname "${WANDEV}" snat ip6 prefix to ip6 saddr map { "${ULA}" : "${PFX}" }

# 最初に /var/lib/dhcpcd/prefix.confを更新しておく
/usr/local/sbin/renew-conf-prefix.sh $OLD_PREFIX $NEW_PREFIX /var/lib/dhcpcd/prefix.conf

# /etc/radvd.confを更新し、radvdをリスタート
/usr/local/sbin/renew-conf-prefix.sh $OLD_PREFIX $NEW_PREFIX /etc/radvd.conf
systemctl restart radvd

# /etc/kea/kea-dhcp6.confを更新し、kea-dhcpcd-confをリスタート
/usr/local/sbin/renew-conf-prefix.sh $OLD_PREFIX $NEW_PREFIX /etc/kea/kea-dhcp6.conf
systemctl restart kea-dhcp6-server
/var/lib/dhcpcd/以下に/etc/radvd.confと/etc/kea/kea-dhcp6.confをバックアップする処理を入れたので、これで何かあっても対応できそうです。
IPv6プレフィックス変更に対応する為の記事はほぼみあたらなかったのですが、ご参考になれば幸いです。
今回は以上です。それでは。

コメント

このブログの人気の投稿

wsdd を使ってSamba サーバをネットワークに表示

Windows 10のアップデートで、セキュリティー対応のため、smbv1がデフォルトではインストールされなくなり、Samba serverがエクスプローラーのネットワークに表示されなくなってしまいました。そこで、いくつか方法を調べたのですが、linuxでwsdの実装がないか探したところ、 https://github.com/christgau/wsdd が、見つかりましたので、さっそくインストールしてみました。まだパッケージにはないようですが、インストール自身は簡単です。wsdd自体は以下のように取得し、linkを張っておきます。 cd /usr/local/bin/ sudo wget https://raw.githubusercontent.com/christgau/wsdd/master/src/wsdd.py sudo chmod 755 wsdd.py sudo ln -sf wsdd.py wsdd こちらのsambaサーバはDebianなので、/etc/systemd/system/wsdd.serviceは以下のようにしました。 [Unit] Description=Web Services Dynamic Discovery host daemon Requires=network-online.target After=network.target network-online.target multi-user.target [Service] Type=simple ExecStart=/usr/local/bin/wsdd -d MYDOMAIN [Install] WantedBy=multi-user.target wsdd -d MYDOMAINのところを、環境にあわせて書き換えてください。 次に、systemdに登録・起動テストを行います。 systemctl enable wsdd systemctl start wsdd 起動に成功すると、エクスプローラーのネットワークに表示されます。  なおこのwsddはpython3が必要です。一度試してみてください。SMBv1/CIFSを停止していても、大丈夫です。 cで書かれたほかのwsddの実装もあるようなので、いずれパッケージになるかもしれませ

Hyper-V Server2019にワークグループ環境下でWindows10(1809)から接続

Hyper-V server 2019に、ワークグループ環境にてWindows10(1809)から接続してみました。Windows10にHyper-V管理ツールがインストールされていることと、Hyper-V Serverをインストール済であることが前提です。以下、Hyper-V serverは名前がHyperVSV、アドレスは192.168.1.110としています。 まず、Hyper-V server上で、powershellを起動し、以下のコマンドを入力します。 Enable-WSManCredSSP -Role Server -Force 続いて、クライアントのWindows10のpowershell で以下のコマンドを入力します。 winrm quickconfig -Force Enable-WSManCredSSP -Role Client -DelegateComputer * -Force さらに、クライアントマシンで、gpedit(グループポリシーエディタ)を起動し、以下の要領でポリシーを設定します。 a. [コンピューターの構成]->[管理テンプレート]->[システム]->[資格情報の委任]->[NTLMのみのサーバー認証で新しい資格情報の委任を許可する] を有効にし、サーバを一覧に追加[表示...]ボタンをクリックして、「WSMAN/*」を追加 b. [コンピューターの構成]->[管理テンプレート]->[システム]->[資格情報の委任]->[NTLM のみのサーバー認証で保存された資格情報の委任を許可する] を有効にし、サーバを一覧に追加[表示...]ボタンをクリックして、「*」を追加 また、名前解決できるように、(notepadを管理者権限で実行し)C:\Windows\System32\Drivers\etc\hostsにサーバ名とIPアドレスの対を追加。 192.168.1.110 HyperVSV 最後に、Hyper-Vマネージャーを起動し、Windows10からHyper-V サーバに接続します。手順は以下の通りです。 「サーバーに接続」->コンピュータの選択->別のコンピューターに[HyperVSV]と入力し、[別のユーザーとして接続する

フレッツ光クロス:MAP-E ROUTER by Debian Box (iptables)

フレッツ光クロスがようやく開通したので、Debianにてrouterを構成し接続してみました。なお、プロバイダーを選ぶにあたっては、IPoE方式がそれぞれ異なるため検討したところ、IPoEでは、MAP-Eでもv6plusとocnバーチャルコネクトがあり、前者がポート数240なのに対し、後者は約4倍のポート数が使えるようなネットの情報をみて、OCNバーチャルコネクトを選択しました。(プロバイダーとしてはぷららです。なおDS-LiteはCE側でのNATではないので今回は見送りました。)そこで、OCN バーチャルコネクトをDebian(iptables)で実現するとどうなるかと思い、ネットの情報を頼りにしつつ、設定した次第です。 実際に試した結果、とりあえず通信できていますが、MAP-Eは本来マッピングルールをマップサーバから取得するはずなので、今回のやり方が正解とはいえませんし、仕様変更されると通信できなくなる可能性があります。あくまでも参考程度ですが、本稿をUPしてみました。 2023/03/16追記: こちら にゲームコンソールNAT越え(Nintendo Switch ナットタイプ A判定)対応版を投稿しました。 2023/03/28追記:※1の記述および3行無効化によりNAT越え(Nintendo Switch ナットタイプ B判定)できるようになりました。 構成は以下の通りです。 ルーターがDebianで回線がOCNバーチャルコネクトであること以外はなにも特別なところはない構成です。 さて、いきなり設定ですが、まず、割り当てられたプレフィックスを確認します。 確認は、 dhclient -6 -d -P enp2s0 とします。出力の中に 前略 RCV: | | X-- IAPREFIX 2400:4050:5c71:af00::/56 後略 このようにプレフィックスが表示されるので、その確認したプレフィックスを書き留めておきます。これを こちらで 入力します。すると、 CE: 2400:4050:5c71:af00:99:f171:c600:2f00 IPv4 アドレス: 153.241.113.198 ポート番号:(1776-1791 2800-2815 3824-3839) 4848-4863 5872-5887 6896-