RFC 4193 - 3.2.2 を使って Ethernet などの MAC アドレスから Unique Local IPv6 Unicast Addresses プリフィクスを生成します。
genulaprefix.py
#!/usr/bin/env python3
import argparse
import hashlib
import time
from struct import pack, unpack
parser = argparse.ArgumentParser()
parser.add_argument('ether', metavar='MAC')
args = parser.parse_args()
mac = bytes([int(b, 16) for b in args.ether.replace('-', ':').split(':')])
if len(mac) != 6:
print(f'未知の MAC アドレス: "{args.ether}"')
else:
# 現在時刻を 64bit NTP 形式で得る
# [date(1970,1,1) - date(1900,1,1) = 25567 days] * 86400 = 2208988800
ntp64 = pack('>Q', ((time.time_ns() + 2208988800 * 10**9) << 32) // (10**9))
# EUI-64 を MAC アドレスから作る
eui64 = bytes([mac[0] ^ 2, *mac[1:3], 0xff, 0xfe, *mac[3:]])
# SHA1 を使って Global ID を得る
fh = hashlib.sha1()
fh.update(ntp64 + eui64)
gid = fh.digest()[-5:]
# IPv6 アドレス プリフィクスを作る
ulap = ':'.join(f'{h:x}' for h in unpack('>3H', b'\xfd' + gid))
print(f'ULA Prefix = {ulap}::/48')
実行結果
$ python3 genulaprefix.py 12:34:56:78:9a:bc
ULA Prefix = fdd2:f08b:fba8::/48
$ python3 genulaprefix.py 12:34:56:78:9a:bc
ULA Prefix = fd95:b84:924f::/48
現在時刻を time.time_ns() で取得しているので毎回変わります。