Help us understand the problem. What is going on with this article?

RaspberryPiがネットワーク接続したときに、接続環境を通知させたい

Raspberry Pi 4を買いました。で、SDカードにはArchLinuxを入れました。

今回LEDとかも別に買っているわけではなく、素の状態での運用となるのですが、困ることが一つあって、

どこに接続しているのかの確認が面倒くさい

基本的にはDHCP利用な上にモニターもない状態なので、有線接続だろうと無線接続だろうとIPアドレスを確認しに行くのも面倒です。
そこで今回は、タイトルの通り「ネットワーク接続が確立できた時点で接続情報を自分から伝えてもらう」ことにしました。

まとめ

環境情報

  • 筐体: Raspberry Pi 4
  • OS: ArchLinux (ARM版)
  • ネットワーク管理: NetworkManager
  • Python 3.8.0

書いたコード

/etc/NetworkManager/dispatcher.d/notify-connection-information.py
#!/usr/bin/env python
import json
import os
import sys
from urllib.request import urlopen


WEBHOOK_URL = 'https://hooks.slack.com/services/THISIS/SLACK/WEBHOOK'


def main(conn_id, ip_addr):
    payload = {
        'username': 'info',
        'icon_emoji': ':strawberry:',
        'text': f'*attakei-pi* has connected to {conn_id}\n IP address is `{ip_addr}`',
        'channel': '@attakei',
    }
    urlopen(WEBHOOK_URL, json.dumps(payload).encode())


if __name__ == '__main__':
    argv = sys.argv[1:]
    # if argv[0] != 'wlan0' or argv[1] != 'up':
    if argv[1] != 'up':
        sys.exit(0)
    ip_addr = os.environ['DHCP4_IP_ADDRESS']
    conn_id = os.environ['CONNECTION_ID']
    main(conn_id, ip_addr)

出来上がった通知

スクリーンショット 2019-12-02 18.58.02.png

NetworkManagerの話

NetworkManagerとは

ネットワーク接続に関するあれこれを管理するためのデーモン(+ツール)です。
SSIDの管理をしてくれたり、すでに登録済みのSSIDには自動接続を行ったりしてくれます。

systemd-networkd などもありますが、とりあえず自分は現在これを利用しています。

NetworkManagerのdispatch機能

さて、NetworkManagerには「ネットワークの切り割りをイベントとしてコマンド実行する」ことを可能にする、dispatcher機能があります。
ArchLinuxのWikiに掲載されているサンプルなどでは、「有線接続をしたときは無線を無効化(+その逆)」「特定ネットワークに接続した場合は、続けてVPN接続する」みたいな例が書かれています。
今回はこれらのスクリプトを参考にして、上記のような「ネットワーク接続時に、指定されたSlackチャンネルに 利用したSSIDIPアドレスを申告する」スクリプトを作ってみました。

dispatcherが受け取るもの

実際に使用してわかっている範囲だと、Disptcherはコマンド実行時に以下の情報を渡すようになってます。

  • コマンドの引数として
    • イベントのあったネットワークデバイス名
    • どんなイベントが発生したか(例: up=接続した)
  • 環境変数として
    • 上記イベントに付随する情報各種
      • 接続設定名
      • IPアドレス
      • などなど

情報を揃えてdispatchする

トリガーにしたい条件をもとに、どこから情報を取るかや振る舞いを整理します。

  • 「ネットワーク接続時に」
    • => コマンドの第2引数を参照する。up以外は無視
  • 「指定されたSlackチャンネルに」
    • => NetworkManager-dispacherの管理領域ではないので、とりあえずスクリプト直接記載
  • 利用したSSID
    • => 環境変数のCONNECTION_IDを参照
  • IPアドレス
    • => とりあえずIPv4がほとんどなので、環境変数のDHCP4_IP_ADDRESSを参照

これで、必要な情報は揃ったので、コードが書けますね。コードは最初に記載したのでそちらを参照して下さい。

補足

スクリプトは直接呼び出されるので、shebangと実行権限付与を忘れずに。
※自分はこれで「あれっ」ってなり、頑張る系のIPアドレス探索をするはめになりかけました。

URLs

attakei
東京湾岸にて勤務中。 【公私】主にインフラ・サーバサイドWeb担当。Pythonista 【他】徒歩バカ
nijibox
ニジボックスの開発は、社内のUI/UXデザインチームと連携をとりながらワンストップで行う開発支援サービスです。Reactを始めPHP(Laravel)・Ruby on Rails、Swift・Kotlinを使った開発実績も多く、バックエンドからアプリまで幅広く対応しています。現在、リクルートの大規模サービスでのモダン開発に興味のあるフロントエンドエンジニアを積極採用中です!
https://www.wantedly.com/companies/nijibox
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away