Next.jsで簡易的なアクセス制限機能を実装するときに、アクセス接続元情報を参照する必要があった。

簡易的なアクセス制限機能であるため、クライアントを識別するには次の情報さえあれば良い。
(厳密にやるならばネットワーク上にサーバ等構築する必要はある。)

  • IPアドレス
  • User Agent
  • ホスト名

これらの接続元情報をNext.jsで構築したアプリケーションで取得する方法について書く。

環境

  • Next.js 12.0.4

実装

SSR(サーバーサイド)で実行されるgetServerSidePropsメソッドには、contextというオブジェクトが渡ってくる。

contextオブジェクトには、reqというリクエストオブジェクトが内包されており、リクエストヘッダーの情報も含んでいるため、前述した接続元情報はreqオブジェクトから参照する。

getServerSidePropsからreqを参照するには次のように記載する。

export const getServerSideProps: GetServerSideProps = async(context) => {
    const { req } = context;

    return {
        props: {}
    }
}

IPアドレスの取得

x-forwarded-forヘッダーからIPアドレスを参照する。
X-Forwarded-For - HTTP | MDN

x-forwarded-forヘッダーは、次のようにカンマ区切りの構造となっている。

X-Forwarded-For: <client>, <proxy1>, <proxy2>

proxyには、複数のプロキシを経由された場合に経由されたプロキシのIPアドレスが出力される。

接続元(client)のIPアドレスを取得するには、カンマ区切りしたリストの先頭を参照すれば良い。

const ipAddress = req.headers["x-forwarded-for"]
    ? String(req.headers["x-forwarded-for"]).split(',')[0]
    : req.connection.remoteAddress
        ? req.connection.remoteAddress
        : "";

User Agentの取得

User-AgentヘッダーからUser Agentを参照する。
User-Agent - HTTP | MDN

const userAgent = req.headers["user-agent"];

ホスト名の取得

ホスト名はHTTPヘッダーには含まれないため、IPアドレスから逆引きして取得する。

Node.jsのdns.lookupServiceメソッドを使用してDNSサーバに問い合わせを行う。

import {lookupService} from "dns";

const getHostName = (ipAddress: string): Promise<string> => {
    return new Promise(function(resolve, reject) {
        lookupService(ipAddress, 22, function (error, hostname, service) {
            if (error) {
                return reject(error);
            }
            resolve(hostname);
        });
    });
};
const hostName = await getHostName(ipAddress);

dns.lookupServiceメソッドは、問い合わせ成功時にコールバック関数を介してホスト名を返却する。
任意の変数などに初期化するには、Promiseオブジェクトでラップして返却させる。