Golangでランダムなパスワードで設定するhostapdを建てる方法

2021-10-18

はじめに

Raspberry piなどで使い切りの簡易の無線LANルータを立てたいニーズがありました。 そういった制御を行うプログラムを書いてみましょう。 やってることはLinuxコマンドを順番に並べているのでShell Scriptの方が適切な気もするのですが、Goで書いていきます。

起動時にランダムなパスワードでWi-Fiスポットを建てる

ランダムな文字列を取得する関数

よくある方法ですが、引数に入った桁数分だけ静的な文字列を並べています。

func MakeRandomStr(l uint32) (string, error) {
    const let = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    b := make([]byte, l)
    if _, err := rand.Read(b); err != nil {
        return "", errors.New("unexpected error...")
    }

    var result string
    for _, v := range b {
        result += string(let[int(v)%len(let)])
    }
    return result, nil
}

コマンドプロンプトを実行できる関数

引数に入れられたコマンドをsudoで実行しています。 Run()というのをOutput()に変えて戻り値を2つ並べると、出力結果を得ることができます。 argsには、引数に入ってくるコマンドを分割して良い感じに並べるようにしています。

func commonExecution(exe string) {
    args := strings.Fields(exe)
    err := exec.Command("sudo", args...).Run()
    if err != nil {
        log.Fatal(err)
    }
}

hostapdの設定をする関数

sedコマンドでhostapdの設定ファイル内のwpa_passphraseを取得した文字列で書き換えています。 その後 systemctlで動かしているhostapdを落として、再起動しています。 これで起動ごとにランダムなパスワードでWi-Fiスポットを立ち上げることができますね。

func hostapdSetting() string {
    pass, err := MakeRandomStr(15)

    if err != nil {
        fmt.Println(err)
    }

    commonExecution("sed -i -e s/wpa_passphrase=.*/wpa_passphrase=" + pass + "/g /etc/hostapd/hostapd.conf")
    commonExecution("systemctl unmask hostapd")
    commonExecution("systemctl enable hostapd")
    commonExecution("systemctl start hostapd")
    commonExecution("service hostapd restart")

    return pass
}

main

コード全文を載せておきます。 動作確認してないですが、hostapd動く環境なら使えるでしょう。

import (
    "crypto/rand"
    "errors"
    "fmt"
    "os"
    "os/exec"
    "strings"
)

func hostapdSetting() string {
    pass, err := MakeRandomStr(15)

    if err != nil {
        fmt.Println(err)
    }

    commonExecution("sed -i -e s/wpa_passphrase=.*/wpa_passphrase=" + pass + "/g /etc/hostapd/hostapd.conf")
    commonExecution("systemctl unmask hostapd")
    commonExecution("systemctl enable hostapd")
    commonExecution("systemctl start hostapd")
    commonExecution("service hostapd restart")

    return pass
}

func commonExecution(exe string) {
    args := strings.Fields(exe)
    err := exec.Command("sudo", args...).Run()
    if err != nil {
        log.Fatal(err)
    }
}

func MakeRandomStr(l uint32) (string, error) {
    const let = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    b := make([]byte, l)
    if _, err := rand.Read(b); err != nil {
        return "", errors.New("unexpected error...")
    }

    var result string
    for _, v := range b {
        result += string(let[int(v)%len(let)])
    }
    return result, nil
}

func main() {
  hostapdSetting()
}

まとめ

今回はソフト先行で手元にあってその内容を薄めて書いたような記事です。 実際はこのWi-Fiスポットに接続できるQRコードを生成して表示するようなものも付いてます。

プログラムを勉強し始めた頃は、知ってしまうと簡単に書けるようなプログラムでもどうやって実現してんだろうかって思ってたんですが、Linuxコマンドが使えると大体組み合わせれば実現できるんですよね。偉大だなぁ。