
シナリオ
サーバー上に、アクセスしたクライアントの IP アドレスをエコーする小さな PHP スクリプトがあります。このスクリプトは、API 経由で cpanel MySQL リモート ホスト テーブルにアドレスを追加できます。スクリプトの URL を渡す IdHTTP1.Get() を使用してこのスクリプトを呼び出します。Delphi コードを実行して現在の IP アドレスを取得する前に、毎回 Bitdefender VPN を使用して新しい IP アドレスを取得することでこれをテストしています。PHP スクリプトのコードと Delphi 呼び出しコードを以下に示します。
問題
VPN を開いて新しい IP アドレスを取得し、コードを実行すると、IPv6 アドレスが返されます。その後、VPN を切断せずに、つまり同じアドレスを保持したままコードを再度実行すると、2 回目の呼び出しで IPv4 アドレスが取得されます。その後コードを実行するたびに、予想どおり同じ IPv4 アドレスが取得されます。
VPNを閉じて再度開いて別のIPアドレスを取得した場合、同じことが起こります。つまり、最初にコードを実行するとIPv6アドレスが取得され、その後はIPv4アドレスが取得されます。
例:初回:2a02:2498:e000:2001:8418:7195:9f43:a0f 2回目以降:88.202.181.53
この郵便受けどちらのアドレス形式も返される可能性があるが、私が取得するパターンは非常に一貫しているようだと説明しています。
質問
コードが常に IPv4 アドレスを返すように強制する方法はありますか? (IPv4 でアドレスを取得するまでコードが繰り返しアドレスを要求することなく)
追加情報
この郵便受け解決策を暗示しているようですが、受け入れられた答えを自分のケースに適用できるほど十分に理解していません。
このページ、https://www.ipify.org/APIの使用法では、IPv4またはIPv6アドレスを取得する方法を示しています。https://api.ipify.orgまたはhttps://api64.ipify.orgだからスクリプトでどちらが欲しいかを伝えることができるはずだ
myip.php コード
<?php
$ip=$_SERVER['REMOTE_ADDR'];
echo $ip;
?>
PHP スクリプトを呼び出す Delphi 関数 (IdHTTP1 はフォーム上の Indy TIdHTTP コンポーネントです)
function TFrmMain.getmyipaddress: string;
var url : string;
begin
url := 'https://Thedomain.com/myip.php';
Result := '';
try
try
theip := IdHTTP1.Get(url);
Result := Trim(theip);
if result = '' then showmessage( 'Failed to get a sensible IP address from myip.php on server:');
finally
end;
except
on E: Exception do
ShowMessage('Failed to get IP address from myip.php on server:' +slinebreak +
e.Message);
end;
end;
答え1
ipify.orgはIPv6とIPv4で異なるドメインを持っているため、IPv4とIPv6の両方のアドレスしか表示できません。https://www.ipify.org/JavaScript を使用して異なるドメインにリクエストを送信します。
http リクエストは IPv4 または IPv6 のいずれかを使用して行うことができ、当然、Web サーバーは TCP ヘッダーから接続 IP アドレスを認識します。結局のところ、Web サーバーはそこに応答を送信します。http リクエストを IPv4 または IPv6 のどちらで送信するかはクライアントが決定しますが、ドメインに A (IPv4) または AAAA (IPv6) レコードのいずれかしかない場合、クライアントには選択の余地がありません。
ドメイン名 api6.ipify.org は IPv6 アドレスにのみ解決され、 api4.ipify.org は IPv4 にのみ解決されるため、クライアントは IPv6 経由で api4.ipify.org に接続することはできません (逆も同様)。
PHP スクリプトが常にクライアントの IPv4 アドレスを返すようにしたい場合は、IPv4 アドレスにのみ解決できるドメインでホストして、IPv6 経由で接続できないようにしてください。
答え2
PHP には、$_SERVER['REMOTE_ADDR']
リクエストを行うために開かれているソケットのリモート アドレスが含まれています。クライアントが選択したアドレスに応じて、IPv4 アドレスまたは IPv6 アドレスのいずれかになります。
ドメインに接続するときにクライアントが IPv4 または IPv6 のいずれかを選択するための基準がいくつかあります。
- クライアントが適切なIPv6アドレスを持っていない場合は、通信にIPv4を使用します。
- ドメインにDNSにAAAAレコードがない場合、クライアントはAレコード、つまりIPv4を使用します。
- クライアントがIPv6に問題があると判断した場合は、IPv4にフォールバックします。
したがって、常に IPv4 アドレスを持つようにしたい場合はREMOTE_ADDR
、A レコードのみを持つドメイン名を使用する必要があります。
クライアントのネットワークを制御できる場合は、クライアントで IPv6 を無効にすることができます。