IPv6とIPv4を判別してWebサイトに表示する方法【Connected via画像】
よくKDDIやIIJのサイトで右上に「Connected via IPv4」とか「Connected via IPv6」という表記がされています。
閲覧した人の利用するIPのバージョンを判別して、画像を表示しているこの仕組ですが、本サイトでもやってみました。その方法を紹介します。
IPv6とIPv4を判別してWebサイトに表示する方法
本サイトでは、Cloudflareを利用しているので、Cloudflare Workersを用いて実装しました。
Workerのエンドポイントであるhttps://monolithon.net/cdn-api/v1/ip-badgeをGETすると、接続に使われたIPのバージョンを判別して、適切な画像を返す仕組みです。
コードはこちら。別途Base64エンコードした画像データをご用意ください。
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const remoteIP = request.headers.get(‘CF-Connecting-IP’)
let imgBuf;
if (remoteIP.match(ipv4RegEx)) {
imgBuf = atob(ipv4img)
} else {
imgBuf = atob(ipv6img)
}
const len = imgBuf.length
let bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = imgBuf.charCodeAt(i);
}
headers.append(‘Expires’, new Date(Date.now() + 60000).toUTCString())
return new Response(bytes.buffer, {headers})
}
const ipv4RegEx = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$/
const headers = new Headers()
headers.append(‘Content-Type’, ‘image/jpeg’)
const ipv4img = ‘Your base64-encoded image’
const ipv6img = ‘Your base64-encoded image’
Base64エンコードした画像データをipv4imgとipv6imgという2変数に格納しておき、リクエストごとに、ArrayBufferに変換して送り返すという仕組みです。
サイトには、次のようなHTMLを追加しています。
<img src="/cdn-api/v1/ip-badge" width="140" height="21" loading="lazy">
要は単純に画像を読み込むだけですが、これをページ遷移ごとにやるのは無駄だ。なので、画像は1分間ブラウザにキャッシュするようにしています。
IPv6とIPv4を判別してWebサイトに表示した結果
本サイトをパソコンで見ている方なら気づいたはず。右側のサイドバーの一番上に表示されています。
スマホの方も、下の方にスクロールすると表示されます。ぜひ見てみてください。