GCPにて国単位でIPアドレスを弾く方法

GCPの無料枠を使う場合、特定国のIPアドレスを弾く必要があるようです。
元ネタはこちらになります→Google Cloud Platformで中国からの通信をブロック
フィルタ登録時の手打ちが面倒だったので、半自動にしてみました。

前提条件

  • 今回はwsl上での作業です
  • Google Cloud Functionsの環境が出来ていること
  • 次のファイルがカレントフォルダに置かれていること
    https://ipv4.fetus.jp/cn.txt
  • 時々リストを更新する必要があると思いますが、今回はそこまで考慮していません

手順

  1. 次のやっつけスクリプトをカレントフォルダに置きます
    #!/bin/bash
    #
    # CONST_PROJECT に、ご自分のプロジェクト名を入れて下さい。
    # カレントディレクトリに https://ipv4.fetus.jp/cn.txt を置いて下さい。
    # 出来上がった china_block_xx.txt を、cloud shell に投げ込んで下さい。
    #
    # wslからcloud shellを起動する自分メモ
    #   gcloud alpha cloud-shell ssh
    # vimで流し込む場合は(貼り付け前に次のコマンドで)
    # インデントを無効にしておいた方が良いと思います
    #   :set paste
    #
    CONST_PROJECT="MyProject"
    CONST_INPUTFILE="cn.txt"
    counterNo=1
    lineNo=0
    ruleNo=1
    ruleStr="000"
    FileNo=0
    fileStr="00"
    outputFile="foobar.txt"
    itemsCounter=0
    readData=""
    workFile="puyopuyo.txt"
    # curl https://ipv4.fetus.jp/cn.txt
    
    if [ ! -f $CONST_INPUTFILE ]; then
      echo "Input file not found..."
      exit 1
    fi
    
    workFile=$(mktemp "china-block.tmp.XXXXXX")
    sed '1,6d' $CONST_INPUTFILE > $workFile
    itemsCounter=`wc -l $workFile | cut -d " " -f 1`
    
    cat $workFile | while read readData
    do
      if [ $(($counterNo % 2500)) -eq 1 ]; then
        fileNo=`expr $fileNo + 1`;
        fileStr=`seq -f %02g $fileNo $fileNo`
        outputFile="china_block_$fileStr.txt"
        echo "File $outputFile"
      fi
      if [ $lineNo -eq 0 ]; then
        ruleStr=`seq -f %03g $ruleNo $ruleNo`
        echo "gcloud compute --project=$CONST_PROJECT firewall-rules create china-block-$ruleStr --description=\\中\\華\\圏\\のIP\\を\\弾\\く --direction=INGRESS --priority=10 --network=default --action=DENY --rules=all --source-ranges=\\" >> $outputFile
        lineNo=`expr $lineNo + 1`
        echo -n "Rule $ruleStr:"
      fi
      echo -n "$readData" >> $outputFile
      if [ $counterNo -eq $itemsCounter ]; then
        echo "" >> $outputFile
        echo ""
      else
        if [ $(($counterNo % 250)) -ne 0 ]; then
          if [ $(($counterNo % 5)) -eq 0 ]; then
            echo ",\\" >> $outputFile
            lineNo=`expr $lineNo + 1`
          else
            echo -n "," >> $outputFile
          fi
          echo -n "."
        else
          echo "" >> $outputFile
          echo ""
          lineNo=0
          ruleNo=`expr $ruleNo + 1`
        fi
      fi
      counterNo=`expr $counterNo + 1`
    done
    rm -f $workFile
    exit 0
  2. スクリプトのCONST_PROJECTの内容を、自分のプロジェクト名に差し替えます
  3. wsl上でスクリプトをキックすると、china_block_xx.txtなるファイルが出来上がります
  4. cloud shellを起動します
    gcloud alpha cloud-shell ssh
  5. 出来上がったchina_block_xx.txtを、cloud shellに投げ込みます
    ※一度に全部流し込んだらGCP側でリソース不足になったので、出力を分割しました
    vimで流し込む場合は、貼り付け前に

    :set paste

    にてインデントを無効にしておいた方が良いと思います。
  6. GCPの 『VPCネットワーク』→『ファイアウォールルール』にて、結果を確認します

Office365サービスのIPアドレス確認(変更監視)について

はじめに

セキュリティ機器等にO365サービスのIPアドレスを登録する時の確認方法が Microsoft公式ページ にて公開されています。
今回、Win10なPCとIFTTTとWebhookとGmailを使い、当該IPアドレスの変更を検知して通知メールを飛ばすようにしてみました。
※IFTTTとWebhookとGmailの登録及び連携は済んでいるものとします
※以下、常時ログインしているユーザ名を『foo』とします

IFTTTの設定

  1. 公式ページ内のサンプルスクリプトを取り込み、適当に保存します。
    例:C:\Users\foo\Documents\Office365IPCheck.ps1

  2. PowerShell から上記スクリプトを実行します。

  3. 上記スクリプトの実行結果
    C:\Users\foo\AppData\Local\Temp\endpoints_clientid_latestversion.txt
    を開いて、一行目の文字列をメモっておきます。
    これが後程必要となる ClientRequestId となります。

  4. IFTTTで新規アプレットを作成します。
    this には『Webhooks』を選択
    Event Name には『トリガー名(半角ANKで)』を入力
    that には『Gmail(Send an email)』を選択
    To address には『通知先メアド』を入力
    Body には次の内容を
    What: {{EventName}}<br>
    When: {{OccurredAt}}<br>
    Old Version: {{Value1}}<br>
    New Version: {{Value2}}<br>
    <a href="https://endpoints.office.com/endpoints/Worldwide?ClientRequestId=上でメモったClientRequsestId">https://endpoints.office.com/endpoints/Worldwide?ClientRequestId=上でメモったClientRequsestId</a>
    Attachment URL には次の内容を
    https://endpoints.office.com/endpoints/Worldwide?ClientRequestId=上でメモったClientRequsestId
    記入します。
  5. アプレットを保存します。

PowerShellスクリプトの変更

  1. IFTTT 上の Webhooks のページにある『Documentation』をクリックし、『Your key is:』の値をメモします。

  2. PowerShellスクリプトの最後の方の、『# TODO』行と『}』行の間に、次の行を追加します。
    Invoke-RestMethod -Uri "https://maker.ifttt.com/trigger/上で決めたトリガー名/with/key/先程メモったキーの値" -Method Post -Body ( @{"value1"="$lastVersion";"value2"=$version.latest} | ConvertTo-Json) -ContentType 'application/json'
  3. PowerShellスクリプトを保存します。

監視タスクの追加

  1. 監視タスク実行時に窓が表示されるのを防ぐために、キック用スクリプトを次のような内容で作成します。
    例:C:\Users\foo\Documents\task-scheduler.js
    wsShell = WScript.createObject("WScript.Shell");
    retCode = wsShell.Run("\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -File \"" + WScript.Arguments.Item(0)+"\"",0,true);
    WScript.Quit(retCode);
  2. タスクスケジューラで監視タスクを作成します。
    • トリガータイミングは適当に(毎時とか毎日とか毎週とか)
    • 操作→プログラムの開始
    • プログラム名には、『task-scheduler.js』を入力
    • 引数には、PowerShellスクリプト名をダブルクォートで囲って設定
      例:”C:\Users\foo\Documents\Office365IPCheck.ps1″
    • 開始オプションに、PowerShellスクリプトの保管場所を指定
      例:C:\Users\foo\Documents\
  3. 監視タスクを保存します。

動作テスト

  1. PowerShellスクリプトの実行結果ファイル
    C:\Users\foo\AppData\Local\Temp\endpoints_clientid_latestversion.txt
    を削除します。
    本ファイルを削除することにより、PowerShellスクリプトの実行時に『IPアドレスが更新された』と判断されます。

  2. タスクスケジューラで設定したタイミングでメール通知が届けば成功です。

2019.03.22追記:本日、GmailとIFTTTの連携を停止する通知がGoogleから届きました。
いまのところどうしようもないみたいなので、回避策を記します。

Zapierでの実装について

  1. Zapierのアカウントを作成し、ログインを済ませておきます
  2. 次のURLに移動します
    https://zapier.com/apps/gmail/integrations/webhook
  3. “Send an email from Gmail when a webhook is received” の『Try It』をクリックします
  4. “Catch Hook”画面で『Continue』をクリックします
  5. URLが表示されるのでコピーしておき、『Ok, I did this』をクリックします
  6. ps1スクリプトを変更します
    1. Invoke-RestMethod -Uri での飛び先をIFTTTからZapierの先程コピーしたURLに変更
    2. スクリプトをキック
    3. Zapier画面で待機
      問題無ければ、数分後には5.の画面に『Continue』ボタンが現れるので、クリックします
  7. Gmail / Send Email 画面で『Continue』をクリックします
  8. Select Gmail Account画面で(連携未設定の場合は『Connect an Account』を押して連携設定後)アカウントを選択し、『Continue』をクリックします
  9. Set up Gmail Email画面で、To:やFrom:、Subject:等を設定します
  10. Bodyは次のように書きます
    Old Version:
    New Version:
    https://endpoints.office.com/endpoints/Worldwide?ClientRequestId=上でメモったClientRequsestId
  11. 『Old Version:』の右をクリックして、画面右側の『+』をクリック、『Value1』を選択します
    Old Version: の右に『Step1:値』が挿入されます
  12. 『New Version:』の右をクリックして、画面右側の『+』をクリック、『Value2』を選択します
    Old Version: の右に『Step2:値』が挿入されます
  13. Attachmentには次の値を投入します
    https://endpoints.office.com/endpoints/Worldwide?ClientRequestId=上でメモったClientRequsestId
  14. 入れ終わったら、『Continue』をクリックします
  15. テストボタンが出るので、クリックします
  16. 無事にメールが届いたら、『Finish』をクリックします

2019.04.15追記
バージョンチェックファイルが存在するのに、Test-Pathにて『存在しない』扱いになるケースがあるようです。waitを挟んでも、複数回チェックしても、駄目な時は駄目な感じ。実害は無いとは思うのですが、回避策等について現在確認中です。


2019.05.07追記
IPアドレスは基本的に月末に更新されるようです。
このときにバージョンチェックファイルendpoints_clientid_latestversion.txtの更新がうまく行かない場合は、次の図の①の部分を見直してみて下さい。
スケジュールのプロパティログインアカウントのパスワードを変更したりすると、ここの部分で引っかかったりもするようです。
テスト時の実行アカウントと、スケジュール実行アカウントの権限の差が原因の場合もあります。

ファイル所有者名の確認
dir /q バージョンチェックファイル名

ここで駄目な場合は、②の部分を触るとうまく行くようになる場合があります。
それでも駄目な場合は、スケジュール自体を作り直してみて下さい。