LoginSignup
1
0

More than 3 years have passed since last update.

SNMPでWIFIルーターの電波OFFをする

Posted at

やりたいこと

WIFIルーターの電波on/offをリモートで行う。

前提となる知識

SNMP(Simple Network Management Protocol)

  • ネットワーク機器を管理するために用いられるプロトコル。今回でいうと、ルーターの設定値を読み出したり、電波をon/offしたり。
  • ルーターの設定をSNMPプロトコルを通じて変更が可能 (変更が許可されているもののみ)。
  • ルーターの設定値を読み出すことも可能。

MIBファイル形式

  • MIBファイルにはルーターの各設定について、OID(Object ID)が何で、データ型が何なのか、設定許可されているかどうかなどが記載されている。
  • ルーターの各設定項目について、それぞれObject ID(OID)が設定されている(メーカー独自)ため、ルーターのメーカーからMIBファイルを入手する必要がある。もしくはルーターの管理画面からダウンロードできるのかもしれない。
  • MIBファイル形式について
  • Q:SNMPv2形式の拡張MIBファイルの基本的な文法

OID(Object ID)について

設定値がツリー構造になっており、数字を順番に辿っていくと、ある設定値にたどり着く。たとえば、以下の例だとxxはベンダー名が割り当てられている。それ以降はモデル名だったり、設定値だったりと続いていく。これはベンダー毎に定義がされている。

1.3.6.1.4.1.xx

実際のMIBファイルはテキストになっているが、解読するのは結構大変だった。以下は実際の例。

使用したツール

TWSNMP

MIBファイルを読み込ませる必要がある。GUIで、設定値が一覧で見えてくるので直感的でわかりやすい。現在設定値の確認、ObjectIDの確認などを行うときに使用した。

snmpwalk (windowns)

コマンドラインで設定の読み出しや変更を行う。実際にプログラム内でコマンドを投げるときに、正しくObjectIDや型などを送信しないといけないのだが、そのコマンドの確認のために使用。TWSNMPだと、実際にどういうコマンドが投げられているのかはわからない。Object IDはわかるのだが、型をどう指定するのかとか、Object IDの末尾の数字をどうするとか、そのあたりが確認できた。

例えば、1.3.6.1.4.1.xx.xx.xx.xxというObject IDの値を読み出したいというとき、SNMPv2-SMI::なんとかと返ってくる。ちなみに-vはSNMPのバージョン(今回はv2)。 -cはコミュニティ名。ここでは"public"という名前(ルーターの設定でsnmp communityという項目があるはず)。1.3.6.1.4.1.xx.xx.xx.xxのあとに、1とか0などがでてきて、データ型がなんなのかを教えてくれる。で、実際にコマンドを投げるときは、1.3.6.1.4.1.xx.xx.xx.xx.1をObjectIDとする必要があった。ここがわからず結構はまった。

設定値の読み出し
c:\usr\bin>snmpwalk -v 2c -c public 192.168.1.10 1.3.6.1.4.1.xx.xx.xx.xx
SNMPv2-SMI::enterprises.xx.xx.xx.xx.1 = INTEGER:0
  • 設定の書き込みをする場合はルーターのsnmpの設定で、READ-WRITEの設定をしておく(書き込み可能にしておく)。
  • enterprises.xx.xx.xx.xx.1の最後に1なのか0なのかはMIBファイルを見ただけではわからなかった。(何か規則性がある?)
  • ここで得られたenterprises.xx.xx.xx.xx.1をOIDとして設定している。

SharpSnmp (.NET SNMP Library)

SNMPを行うためのライブラリ。いくつか似たようなのがある。

SNMP Library Documentation
インストール方法はここに書いてある。

using Lextm.SharpSnmpLib;
using Lextm.SharpSnmpLib.Messaging;
  • SNMPv2を使用した。v2はわりとシンプル。v3は認証などもありで複雑、たぶん。今回はローカルの環境でしか使用しないので、v2を使用。

SetRequest 設定を送信する

設定値の送信

private void SetRequest(string oid, int val)
        {
            // Snmp v2
            VersionCode version = VersionCode.V2;

            var receiver = new IPEndPoint(IPAddress.Parse(ip), snmpProt);
            Discovery discovery = Messenger.GetNextDiscovery(SnmpType.GetRequestPdu);
            ReportMessage report = discovery.GetResponse(timeout, receiver);

            // int型のデータを送信する場合
            ISnmpData data = new Integer32(val);

            // string型のデータを送信する場合
//            ISnmpData data = new OctetString(val);

            var test = new Variable(new ObjectIdentifier(oid), data);
            var vList = new List<Variable>();
            vList.Add(test);

            var request = new SetRequestMessage(Messenger.NextRequestId, version, new OctetString(community), vList);

            ISnmpMessage reply = request.GetResponse(timeout, receiver);

            if (reply.Pdu().ErrorStatus.ToInt32() != 0)
            {
                throw ErrorException.Create(
                    "error in response",
                    receiver.Address,
                    reply);
            }

            // 結果を出力
            foreach (Variable v in reply.Pdu().Variables)
            {
                Console.WriteLine(v);
            }
        }

設定を取得する

ここではint型の設定を返している。

設定値の取得

        private int GetRequest(string oid)
        {

            VersionCode version = VersionCode.V2;

            var receiver = new IPEndPoint(IPAddress.Parse(ip), snmpProt);
            Discovery discovery = Messenger.GetNextDiscovery(SnmpType.GetRequestPdu);
            ReportMessage report = discovery.GetResponse(timeout, receiver);

            // 取得したいOID
            var test = new Variable(new ObjectIdentifier(oid));
            var vList = new List<Variable>();
            vList.Add(test);

            var request = new GetRequestMessage(Messenger.NextRequestId, version, new OctetString(community), vList);

            ISnmpMessage reply = request.GetResponse(timeout, receiver);

            if (reply.Pdu().ErrorStatus.ToInt32() != 0)
            {
                throw ErrorException.Create(
                    "error in response",
                    receiver.Address,
                    reply);
            }

            // 結果を出力
            foreach (Variable v in reply.Pdu().Variables)
            {
                Console.WriteLine(v);                
            }

            return int.Parse(reply.Pdu().Variables[0].Data.ToString());
        }
    }

その他はまったポイント

ルーターの設定画面にラウザでアクセスしている状態(ログインしている)で、プログラムからコマンドを投げてもうまく反映がされなかった。コマンドを投げるときは、一旦ログアウトしてから、コマンドを投げる。その後、もう一度ルーターにログインして、値が変更されているかを確認する、といったことをやらなければならなかった。これも気づくまでに時間がかかった。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0