LoginSignup
15
4

More than 1 year has passed since last update.

Discordで動くLinuxターミナルを作る

Last updated at Posted at 2021-12-21

長野高専 Advent Calendar 2021 22日目の記事になります.皆さんすごい記事書いてる...
この記事では,Discord上で動くLinuxターミナル...風のbotを作ってみました.
image.png
こんな感じのターミナルを作りました.

任意コマンド実行を他人に許可することにより,予期せぬ問題が起こる可能性があります.使う際は必ず信頼できるメンバー間でのみにしましょう.

(画像にあるF-langについては以下)

きっかけ

黒板があれば学生が数式を落書きのように書いていく...ああいうノリのTerminal版がほしいなと思ったので作りました.
弊クラスにはDiscord鯖があるので,そこに#Terminalチャンネルを作って遊んでもらうことにしました.

仕組み

せっかくならroot権限を付与して徹底的に破壊してもらいたいものです.ですが,それだけで毎回鯖を復旧させるのは大変なので,Dockerでイメージ,そこからコンテナを作り,必要であればそれを壊してイメージからコンテナを再構築することで,sudo rm /* -rf 1を実行されてもすぐに復活する環境を用意します.

実装

作りましょう.

コンテナづくり

早速コンテナを作りましょう.とりあえず自分が一番慣れているUbuntuで作ります.

SSH導入

Discord Botとのコマンドの受け渡しはSSHで行います.

ユーザー名

コンテナ内のユーザー名は,DiscordのIDに準ずるものにします.ただし,人によってはLinuxのユーザー名に使えない記号を使っていたり,日本語名になっている人もいます.そういう人のためにも,どんな名前が来てもできるような仕組みを作ります.

✝ほねつきにく✝の場合

  1. ローマ字に変換(✝honetsukiniku✝)
  2. [a-z0-9_]以外を消す(honetsukiniku)

LANへのアクセスを無効化

宅鯖などでこいつを運用する場合,家にいる人は当然家のLANにアクセスできることになります.流石にそれは困るので,iptablesで無効化させます.
DockerコンテナのネットワークルールはDOCKER-USERチェインをiptablesにより設定することで反映させられます2.(わりと最低限しか設定していないため,もしかしたら漏れがあるかも)

優先度 対象 理由
1 デフォルトゲートウェイのTCP/80を却下 デフォルトゲートウェイの端末設定を開けなくするため
2 デフォルトゲートウェイを許可(192.168.1.1) ここを許可しないとグローバルに出れないため
3 LAN全体をブロック(192.168.1.0/24) LAN内の別の端末のアクセスを防ぐため
sudo iptables -I DOCKER-USER -s 192.168.1.0/24 -j DROP
sudo iptables -I DOCKER-USER -s 192.168.1.1 -j ACCEPT
sudo iptables -I DOCKER-USER -s 192.168.1.1 -p tcp --dport 80 -j DROP

コンテナに対応する設定ファイル

config.jsonに定義できるようにすることで,とりあえずsshが通るコンテナであれば使えるようにします.

{
 "containers": Array<{
        "name": string,
        "port": number,
        "image": string,
        "dockerConfig": Object<dockerConfig>, //The option to create container. See https://docs.docker.com/engine/api/v1.37/#operation/ContainerCreate
        "discordIcon": string //Example: "<:windows:762682464966803476>"
        "authMethod": {
            "type": string,
            "user": string,
            "password": string
        }
    }>
}

リセットボタン

Discordに便利な機能が追加されました3.これでリアクションで頑張る必要はなさそうですね.
image.png
image.png
クリックされた後はコンテナの停止,削除,イメージからのコンテナ再作成を行います.

ドラッグ&ドロップでアップロード

送信されたファイルをコンテナにSCPで転送します.
送信されたファイルをBufferで格納したら,node-scp2のLow Level APIであるwriteを使って,そのBufferを直接転送します.
image.png
image.png

ファイルのダウンロード

コンテナ内のファイルをDiscord側にSCPで転送します.
アップロードと同じく,SCPでBufferを受け取ってそのままDiscordに転送しようと思ったのですが,どうやらnode-scp2には直接Bufferで受け取るメソッドがない4ようなので,Low Level APIであるreadを追加したnode-scp2パッケージを作成しました5

package.json
 "dependencies": {
-    "scp2": "^0.5.0",
+    "scp2": "github:BonyChops/node-scp2",
  }

Workflow

任意チャンネルで%ワークフロー名 引数...を打つと発動できるWorkflowという機能もつけてみました.これで会話も盛り上がること間違いなし!
image.png
設定はこんな感じにします
image.png

使える引数は以下です

引数 説明
$n 指定された文字列引数(n=1,2,3,...)
$FILEn アップロードされたファイル(のパス)(コードブロックも含む)(n=1,2,3,...)
また,ファイルを/home/workflow/files/に出力すると,出力結果として返ってきます
例: Gnuplot
workflow.sh
PLOTCONFIG=$FILE2
if [ -z $FILE1 ]; then
    echo "プロットデータが必要です"
    exit
fi

if [ -z "$PLOTCONFIG" ]; then
    PLOTCONFIG=config.gnuplot
    echo "set terminal png\nset output \"/home/workflow/files/out.png\"\nplot inputFile with lines notitle" > config.gnuplot
fi
gnuplot -e "inputFile='$FILE1'" "$PLOTCONFIG"

image.png

実際の評判

クラス内で運用してしばらく経ちますが,その際のユースケースを紹介します

  • コマンド確認
    表示結果をさくっと確認
    image.png

  • Gnuplot実行
    学校課題で必要なグラフもWorkflowで実行
    image.png

今後やりたいこと

ちょっと忙しいのでできる見通しがたっていませんが,やりたいことがあります.

  • 表示結果を見やすくする
    textimgを使って出力を画像として出すことにより,より見やすい結果を表示したいなと思っています.画像はとりあえずお試しでやってみたものなのでバグり散らかしてます6
    image.png
    image.png
    image.png7

  • OS(コンテナ)切り替え
    Twitterの方ではできるようになりました!!とか言ってましたが,まだ完璧ではないです...安定してできるようにしたいですね
    image.png

  • Readme.mdの充実化
    面倒臭がって適当なことしか書いてないので,いつかしっかりとした事を書いておきたいです.

  • 汚ソースのリファクタリング
    ソースが汚すぎるのできれいにしたいです(Dockerfile含む)...

  1. --no-preserve-root/ではなく/*のときは必要ないです

  2. https://docs.docker.com/network/iptables/

  3. https://support.discord.com/hc/en-us/articles/1500012250861-Bots-Buttons

  4. もしかしたら見逃しているかもしれません.もしそうでしたらご指摘ください...><

  5. そのままプルリクも投げようかなーとも思いましたが,最後のプルリクCloseが2018でしたのでやめておきました...

  6. ちゃんとフォント入れれば直る...はずです

  7. 雰囲気ちょっとPortal 2の色違いWheatleyっぽい...?そんなことないか

15
4
1

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
15
4