デバイスのパブリックIPを取得する方法 — IoT・組み込み開発者向けガイド
IoTデバイス、ルーター、組み込みシステムを開発していると、よくシンプルなことが必要になります:デバイスのパブリックIPアドレスです。DDNSの更新、リモートアクセス、ネットワーク接続の変化を確認するために必要です。
このガイドでは、組み込みコードからパブリックIPを取得する簡単な方法を紹介します。APIキー不要、複雑な設定も不要です。
なぜデバイスはパブリックIPが必要なのか
多くのIoTデバイスは家庭用ルーターの背後にあります。ルーターはNAT(ネットワークアドレス変換)を使用します。つまり、デバイスのローカルIP(192.168.1.50のような)は、インターネットから見えるパブリックIPとは異なります。
デバイスが外部からアクセスされる必要がある場合 — リモートカメラアクセス、ホームサーバー、DDNSなど — 現在のパブリックIPを知る必要があります。このアドレスはいつでも変わる可能性があります。特に家庭用インターネット接続では頻繁です。
一般的な使用例:
- DDNSアップデーター:デバイスがパブリックIPを確認し、変わっていればDNSレコードを更新する
- リモートアクセスツール:「接続済み」ステータスを表示する前に、到達可能であることを確認する
- ネットワーク監視:診断のためにIPの変化をログに記録する
- VPNクライアント:見えるIPが変わったかを確認して、トンネルがアクティブであることを確認する
最もシンプルな方法:HTTPリクエスト1回だけ
複雑なAPIは不要です。パブリックIPサービスへのシンプルなHTTP GETリクエストで、プレーンテキストとしてアドレスが返ってきます。
IPPubblico.org はこのために作られた無料サービスです。APIキー不要。ログイン不要。通常の使用(20〜30秒に1回程度の確認)ではレート制限の心配もありません。
GET https://ipv4.ippubblico.org/
レスポンス(プレーンテキスト):
203.0.113.42
これだけです。1行のテキスト。どの言語でも簡単にパースできます。メモリが限られた組み込みデバイスでも問題ありません。
例:ESP32 / Arduino(C++)
ESP32やESP8266を使うホビー向け・商用IoTデバイスで最もよくあるケースです。
#include <WiFi.h>
#include <HTTPClient.h>
String getPublicIP() {
HTTPClient http;
http.begin("https://ipv4.ippubblico.org/");
int httpCode = http.GET();
String ip = "";
if (httpCode == 200) {
ip = http.getString();
ip.trim(); // 改行文字を削除
}
http.end();
return ip;
}
void setup() {
Serial.begin(115200);
WiFi.begin("your-ssid", "your-password");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
String publicIP = getPublicIP();
Serial.println("Public IP: " + publicIP);
}
void loop() {
// 5分ごとに確認 — それ以上頻繁にする必要はない
delay(300000);
String publicIP = getPublicIP();
Serial.println("Public IP: " + publicIP);
}
このコードはM5Stack製品(M5StickC、M5Core2など)でも、ESP32ベースなのでそのまま動作します。
重要:確認は頻繁にしすぎないでください。ほとんどの用途では5分に1回で十分です。数秒ごとに確認すると、バッテリーとネットワーク帯域を無駄に消費し、レート制限に引っかかる可能性があります。
例:Linux組み込みデバイス(シェルスクリプト)
多くのルーターファームウェアや組み込みLinuxボード(OpenWRT、Buildroot、Yocto)はシンプルなシェルスクリプトを実行できます。curlが使える場合、これが最も簡単な方法です。
#!/bin/sh
PUBLIC_IP=$(curl -s https://ipv4.ippubblico.org/)
echo "Public IP: $PUBLIC_IP"
# 例:他のスクリプトが使えるようにファイルに保存
echo "$PUBLIC_IP" > /tmp/public_ip.txt
DDNSアップデータースクリプトの例:
#!/bin/sh
LAST_IP_FILE="/tmp/last_known_ip.txt"
CURRENT_IP=$(curl -s https://ipv4.ippubblico.org/)
LAST_IP=$(cat "$LAST_IP_FILE" 2>/dev/null)
if [ "$CURRENT_IP" != "$LAST_IP" ]; then
echo "IP changed: $LAST_IP -> $CURRENT_IP"
# ここにDDNS更新コマンドを追加
echo "$CURRENT_IP" > "$LAST_IP_FILE"
else
echo "IP unchanged: $CURRENT_IP"
fi
cronで5〜10分ごとに実行:
*/5 * * * * /path/to/ddns_check.sh
例:Python(Raspberry Piなど)
import requests
import time
def get_public_ip():
try:
response = requests.get('https://ipv4.ippubblico.org/', timeout=5)
return response.text.strip()
except requests.RequestException as e:
print(f"Error getting IP: {e}")
return None
def main():
last_ip = None
while True:
current_ip = get_public_ip()
if current_ip and current_ip != last_ip:
print(f"IP changed: {last_ip} -> {current_ip}")
# ここにDDNS更新ロジックを追加
last_ip = current_ip
time.sleep(300) # 5分ごとに確認
if __name__ == '__main__':
main()
IPv4とIPv6の両方を取得
デバイスが両方のプロトコルを確認する必要がある場合:
GET https://ippubblico.org/?text=1
レスポンス:
IPv4: 203.0.113.42
IPv6: 2001:db8::1
プロトコルが利用できない場合、レスポンスはNONEを表示します:
IPv4: 203.0.113.42
IPv6: NONE
重要:レート制限を守る
このサービスには、全員のために安定性を保つためのソフトレート制限があります。デバイスが確認しすぎると、429レスポンスと、何秒待つべきかを示すRetry-Afterヘッダーを受け取ることがあります。
// C++でのシンプルなリトライ処理
int httpCode = http.GET();
if (httpCode == 429) {
String retryAfter = http.header("Retry-After");
int waitSeconds = retryAfter.toInt();
delay(waitSeconds * 1000);
// リクエストを再試行
}
組み込みデバイスのベストプラクティス:
- 通常の用途では5〜10分に1回確認する
- リアルタイムの精度が重要な場合のみ1〜2分に1回確認する
- 20秒に1回より頻繁には確認しない
- ネットワーク障害を常に適切に処理する(インターネット接続がダウンしている可能性がある)
なぜクラウドサービスを使わないのか
多くの商用IoTプラットフォームは、IP検出を含むすべてを自社のクラウド経由でルーティングします。これは機能しますが、サードパーティプラットフォームへの依存が増え、しばしば利用コストやアカウント要件が発生します。
シンプルなケース — DDNS、基本的なリモートアクセス、ネットワーク診断 — では、直接的で無料、キー不要のサービスの方がシンプルで、障害点も少なくなります。
まとめ
| 用途 | エンドポイント | レスポンス |
|---|---|---|
| IPv4のみ | https://ipv4.ippubblico.org/ |
203.0.113.42 |
| IPv6のみ | https://ipv6.ippubblico.org/ |
2001:db8::1 または NONE
|
| 両方 | https://ippubblico.org/?text=1 |
2行、IPv4とIPv6 |
この方法は、ESP32、Linux組み込みボード、Raspberry Pi、基本的なHTTPS GETリクエストを送信できるあらゆるデバイスで同じように動作します。SDKもアカウントもAPIキーも不要です。
完全なドキュメント(43言語対応):ippubblico.org/docs.html
これを使って何か作りましたか?コメントでプロジェクトを共有してください。