見出し画像

TWSNMP開発日誌:モバイル版に自分のIPアドレスを調べる機能を追加したい

今朝も5時から開発開始です。
夜中に、ふとモバイル版で自分のIPアドレスを表示する機能を追加したくなりました。スマホについているデバイスのIPだけでなくインターネットで通信している時の自分IPアドレスも知りたいのです。今週、本業で悩まされている問題が影響しているのかもしれません。寝ながら考えていたらSTUNサーバーを利用するアイデアを思いつきました。起きた時も覚えていたいので早速調べました。

が参考になりました。ありがたいことです。

ソースコードもありましたがRustでした。でもパケットキャプチャーのファイルもあったのでこちらのほうが参考になりました。
テストプログラムを作ってみました。
STUNのパケットを作る部分は、

  List<int> _makeSTUNPkt(bool change) {
    final now = DateTime.now();
    List<int> r = [];
    r.add(0x00); // Bind Request
    r.add(0x01);
    r.add(0x00); // Length
    r.add(0x08);
    // TID
    for (var i = 0; i < 16; i++) {
      r.add(i * now.microsecond);
    }

    r.add(0x00); // Attr Type = Change
    r.add(0x03);
    r.add(0x00); // Attr Len =4
    r.add(0x04);
    r.add(0x00); // Attr
    r.add(0x00);
    r.add(0x00); // Attr
    if (change) {
      r.add(0x04);
    } else {
      r.add(0x00);
    }

    return r;
  }

これをUDP送信します。こんなソースコードです。

  void _testSTUN() async {
    var strun = await UDP.bind(Endpoint.any());

    // receiving\listening
    strun.asStream(timeout: const Duration(seconds: 120)).listen((datagram) {
      print(datagram!.data);
      strun.close();
    });
    // stun1.l.google.com:19302
    var dataLength = await strun.send(_makeSTUNPkt(false), Endpoint.unicast(InternetAddress("74.125.197.127"), port: const Port(19302)));
    print('$dataLength bytes sent.');

送信したパケットを WireSharkで見ると

STUNリクエスト

応答も帰ってきました。デコードすれば自分のインターネット上のIPアドレスがわかります。

STUNのレスポンス

デバイスのIPアドレスは、

    for (var interface in await NetworkInterface.list()) {
      print('== Interface: ${interface.name} ==');
      for (var addr in interface.addresses) {
        print('${addr.address} ${addr.host} ${addr.isLoopback} ${addr.rawAddress} ${addr.type.name}');
      }
    }

のようなソースコードでよさそうですが Androidではだめとか書いてあるサイトがあるので、もう少し調べる必要がありそうです。
でも、今朝は時間切れです。

明日に続く

開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。 ソフトウェアのマニュアルをnoteの記事で提供しています。 サポートによりnoteの運営にも貢献できるのでよろしくお願います。