noraworld / scraps

Just my scraps, like Zenn scraps feature
0 stars 0 forks source link

Raspberry Pi のみ `git push` と `git pull` を禁止する #54

Closed noraworld closed 1 year ago

noraworld commented 1 year ago

実装意図: git pull が Raspberry Pi 上で簡単にできちゃうとブラウザから GitHub のページにアクセスしてファイルを更新することでいつでも簡単に設定ファイルの内容が変更できてしまう。これでは抑止にならない。

かといって Mac とかで日中ずっと GitHub をブロックするわけにはいかない。でも Raspberry Pi なら別に日中ずっとブロックしておいても特に実害はない。Mac ではふつうに GitHub にアクセスできるようにしつつ、Raspberry Pi では日中はずっとブロックしておきたい。そうすれば実用上は影響が出ないし Raspberry Pi 上では気軽に git pull できなくなるのでちょうどいい。

最初は DNS レベルでブロックして名前解決できないようにしようと思ったが、GitHub の IP アドレスを調べて ~/.ssh の設定ファイルに直で IP アドレスを指定することで簡単に回避できてしまうことに気づいた。~/.ssh 内のファイル変更監視をしたところで、コマンドから直接リモートの IP アドレスを指定されたら意味がない。

なので IP アドレスレベルでブロックする必要があった。IP アドレスレベルでブロックするにはもう iptablesufw しか選択肢がない。iptablesOUTPUT (FORWARD ではない) を REJECT すれば、Mac では問題なく GitHub にアクセスできるが、Raspberry Pi ではパケットが届かないようにできる。この方針で進めることに決めた。

noraworld commented 1 year ago

以下から GitHub の IP アドレス一覧を取得できる。

noraworld commented 1 year ago

iptables を使ったブロック方法: https://www.cyberciti.biz/faq/how-to-use-iptables-with-multiple-source-destination-ips-addresses/

一つのコマンドで複数の IP アドレスを同時に指定できることがわかった。サブネットマスクもそのまま指定できるので便利。

最終的には -A ではダメだということに気づき、-I を使った。

noraworld commented 1 year ago

-A だと、ping は通らなくできるんだけど、git pull は実行できてしまった。ブロックしたはずの IP アドレスを直で指定しているのに。

もしかしたらそれに関しては -p all オプションを最初は付け忘れていたのが原因だったかもしれないが、いずれにしても -A ではダメだった。

noraworld commented 1 year ago

https://api.github.com/meta から拾ってきた IP アドレス一覧を iptables に一括で流し込める形式に文字列を整形するのがまあ大変だった。

結局なんか sedgrep だけだと正規表現の指定の仕方がよくわからんかったので perl を使うことに。まあ Ubuntu にデフォで入っているので使ってもいいでしょ。

https://orebibou.com/ja/home/201707/20170720_001/

noraworld commented 1 year ago

JSON データの整形をシェルスクリプトでやるなら jq を使うのが一般的だがこれはデフォルトではインストールされていた。なるべくデフォルト環境で実装したかったので別の方法でやることにして調べたのだが、愚直に grep とか sed とか tr とかを使ってやるしかなかった。

https://stackoverflow.com/questions/57971193/how-to-read-and-parse-json-in-shell-scripting-without-using-json-tool-and-jq-too

noraworld commented 1 year ago

grep でマッチさせた文字列だけを抽出する方法について: https://stackoverflow.com/questions/5080988/how-to-extract-string-following-a-pattern-with-grep-regex-or-perl

noraworld commented 1 year ago

grep -P で最短マッチができる。

https://rokkonet.blogspot.com/2018/07/grep_17.html

noraworld commented 1 year ago

iptables の DROP と REJECT の違いについて: https://serverfault.com/questions/157375/reject-vs-drop-when-using-iptables

REJECT を使ったほうがいい。ちなみに最初は DROP を使っていたんだけどこれだとタイムアウトを迎えるまで git pull が終わらなくなってしまう。無駄に待たされるのは時間の無駄。パケット捨ててるならそれを通知してとっとと失敗してほしい。

noraworld commented 1 year ago

とりあえずまあなんかいい感じにできた。

https://github.com/noraworld/cron-conf/commit/195a73cf8266a2fe1945b87c956e493154b4e28b

あんまり差分はないけどこれだけでもいろいろ調べながら正規表現こねこねしながらで結構時間がかかった。

noraworld commented 1 year ago

このスクリプトは 10 分おきに実行されるんだけど、例によって一時的に無効化して git pull とかされちゃったら意味がない。iptables の設定変更を検知してなんかする的なことをしたかったんだけど、残念ながらそれは現実的ではないことがわかった。ファイルに記述していくタイプならそのファイルを監視すれば良いが、iptables はコマンドで設定が変更できてしまう上にそれがファイルと連動するわけでもないので iptables にそういう機構がない限りは実質的にフックは無理だという結論に至った。

もうそうなると、設定を変更させないようにするっていうのは無理なので、設定を無断で変更したら SSH から締め出すなどのペナルティ形式を採用するしかない。

noraworld commented 1 year ago

git pushgit pull に制限をかけるやつを不正に解除したらペナルティが課されるように実装できた。

https://github.com/noraworld/cron-conf/commit/4978f662a4eea2d948e289392477765e09649a66

ちょっとファイルの移動とかめんどくさかったけどまあわりとすんなりうまくいった。

noraworld commented 1 year ago

0 〜 3 時のあいだだけ git pullgit push ができる。これ以外の時間帯は実行できないので、GitHub のウェブページからファイルをいじってもそれを Raspberry Pi に反映させることはできなくなった。つまりあとファイル監視も再稼働させれば、夜中の 3 時間以外はほぼ設定が変えられない環境になった!!

noraworld commented 1 year ago

今のところの懸念点としては、GitHub の IP アドレス一覧を GitHub API から毎回拾ってきているけど、サーバがダウンしていたりしたときにたぶん失敗しちゃうからどうにかしないといけない。

noraworld commented 1 year ago

各設定ファイルの監視も再稼働させた。これでもう設定はほぼ変えられないぞ!