コンテンツへスキップ

シェルスクリプトでIPを引数にしたいとき、nslookupやdigを使用する時がある。
その結果からIPだけの文字列に整形をするのだが、IP以外にも切り取られてしまうことがある。

例えば、以下のコマンドの場合、digコマンドからIPを表示されない場合がある。

dig -4 $i | grep "IN" | grep -v ';' | awk '{print $5}'

どうにかならないか考えたところ、以下サイトが参考になった。


個人的にありがたかったのが、grepのオプション -o で、grepが一致した箇所だけを表示する。
それを踏まえて、dig のオプション -4でIPV4にしぼり、正規表現で3ケタの0-9までの文字列にしぼる。

dig -4 $i | grep "IN" | grep -Eo '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'


上記のコマンドで現在は安定してIPを取得できている

Zabbixでホストを大量に抱えていると一気にアラート発生したときに確認に苦労する。
例えば、「aaa.comでアラートが発生しました」とアラートが発生したら、
まず、踏み台サーバーのコンソールにログインし、aaa.comのIPをnslookupで取得する。
次に取得したIPでssh接続。原因を調べて解決。のような流れ。

今回は、nslookupでドメインからIPを取得する流れが面倒だったため、/etc/hostsファイルに追記することで、
ドメインでssh接続できるシェルスクリプトを考えてみた。

mkhosts.sh

#!/bin/bash
header='Content-Type:application/json-rpc'
apiurl='http://000.000.000/zabbix/api_jsonrpc.php'
json='{"jsonrpc": "2.0","method": "user.login","params": {"user": "zabbixのユーザー名","password": "Zabbixのパスワード"},"id": 1,"auth": null}'

zbxauth=$(curl -sS -X POST -H "${header}" -d "${json}" ${apiurl} | jq -r ".result")
echo $zbxauth

json='{"jsonrpc": "2.0","method": "host.get","params": {"output": ["hostid","host"]},"id": 2,"auth": "'$zbxauth'"}'
echo $json | jq

hostlist=`curl -sS -X POST -H "${header}" -d "${json}" ${apiurl} | jq | grep "host"| grep -v "hostid" | awk -F: '{print $2}' | sed "s/\"/""/g" `

for i in $hostlist 
do

#任意でnslookupの結果をIPのみに整形する
iplist=`nslookup $i | grep "Address" | grep -v "\#53" |  awk -F: '{print $2}'` 
echo "$iplist $i"| sed 's/^[ \t]*//' >> /etc/hosts 
done

全体の流れとして、ZabbixのAPIからホスト名を取得し整形する。
次に取得したホスト名を引数にしてfor文でnslookupをかけてIPを取得する変数をつくる
最後に、echoで「IP ホスト名」の形にしたものを、/etc/hosts ファイルの最終行に追記する。
mkhosts.sh 実行後、/etc/hostsファイルを確認すると、
IP ホスト名
となっているはず。
その後、

ssh ホスト名

で対象のホストに接続できると思うので確認してみてほしい。

参考
https://www.zabbix.com/documentation/4.4/en/manual/api
https://tech-mmmm.blogspot.com/2019/02/zabbix-api.html
https://orebibou.com/ja/home/201607/20160712_003/
https://ex1.m-yabe.com/archives/3306

SPFレコードについて書くのが苦手だったけど、
今回で仕事で必要な知識だったので知ったことをまとめてみる。

まず前提として、SPFレコードは、本人確認に利用されている。
具体的には、受信サーバーが、送信サーバー元のDNSに問い合わせて、
送信者のIPとDNSに記載されているSPFレコードのIPが一致していたら認証成功。

そして本題の書き方の例

v=spf1  +ip4:192.168.10.1  –all

v=spf1 はspfを書く際のおまじないのようなもの。
+ip4:192.168.10.1 の +(プラス)については認証許可を意味する。
なので、 192.168.10.1 のメール送信を許可する
–all の-(マイナス)については、拒否を意味する。
なので、全てのIPを拒否するということ。

つまり今回は、 192.168.10.1 以外からのIPを拒否すると考える。

余談。
+include:_spf.google.com とincludeとあった場合、
google.comのSPFレコードを参照するという意味が加わる。

参考
https://baremail.jp/blog/2020/02/28/579/

恥ずかしい話、gitlabを今まで利用していたものの、よくわからなかったので、
ファイルをコピーして、CUI上でペーストしてそのスクリプトを使うって方法で運用していました。

最近はチームでgitlabを通して開発することでgitコマンドを用いて
gitlabを利用しているので忘れないうちにメモをします。

※前提として、既にgitlabにリポジトリがあるものを利用する場合です。

gitlabに公開鍵を登録する

gitlabにログイン後、プロフィールにアクセス。
メニューの項目からSSH鍵を選択。

上記にページにたどり着いたら、キーの箇所に自分が利用する端末の公開鍵を貼り付けます。
タイトルは自動で表示されます。Expiration dateは有効期限なので空白で構いません。

git cloneでリポジトリを入手する

自分が利用したいリポジトリを選択し、ページ右上の「クローン」を選択します。

先ほど公開鍵を登録したので、SSHでクローン以下のアドレスをコピーします。

そのあと、自分のCUI上で以下を入力するとリポジトリを入手できます。

git clone ”コピーしたアドレス”

git pushでリポジトリを更新

git pushはgitlab上のリポジトリを更新できるコマンドですが、
pushをするまでにいくつか段階を踏みます。

git addでCUI上のファイルを追加

git add "対象のコマンド"

git commitでリポジトリに反映

git commit -m"コメントを残せる"

git pushでgit labに反映

git push

この後、gitlabへアクセスすると、リポジトリが更新されたかと思います。

リポジトリを更新したい場合は下記コマンドを使います

git pull

ブログを初めてからはや1年以上たちます。
本来の予想通り、メモ帳として活躍しています。
この記事みたいに振り返りやすいのもいいですね。

IT関連

今年の上半期は、ディスクとかlxcの仮想サーバー用のメモ、postfixでのメール設定に取り組んでいました。
ネットワーク関連からルーティングとかも勉強していました。
下半期からは、ほぼbashのシェルスクリプトばかりの記事でしたね。
はじめはスクリプトの構文に慣れるところから苦労しましたが、書き慣れてきて楽しくなり
できることが増えるとあれやこれやと業務の自動化で使えるネタを作りました。

スクリプト書いててわかったけど、時間が経つと自分が何書いたコードが忘れるから
コメントアウトは本当に大事だと身に沁みました。

イラスト関連

Wacomの液タブで絵を描くモチベが低かったのもあって、8月頃に思い切ってipadpro 12.9インチを購入しました。
寝っ転がりながら描けるのがすばらしくモチベ維持に繋がっています。
ただ、ipadの表面にフィルターを何もつけていないのもあるけど、
ペンタブで描くと滑るのでイラストの質や製作時間には影響がでているかもしれない。

最近描いたイラスト

Heartiumのシキ

Heartiumは数年前のフリゲなんですけど、ストーリーが面白くてハマりました。
キャラも可愛く特にシキがお気に入りだったので描きましたとさ。
(前から描こう描こう思ってなかなか描けなかった。)
Heartium って題名のつけ方もゲームの内容とオシャレにマッチしていて好き。

その他、友人の小説の表紙を書いたりして本になりました。
自分の作品が物理的に形としてのこるのはいいものですね。
その他個人依頼でちょくちょくイラストをかいたり。

来年は、
awsとPHPとデータベースあたり頑張りたいなと思います。

Heartium
https://www.freem.ne.jp/win/game/9818

bashでスクリプトを作るとき、スクリプト内のリダイレクト先を下記のように指定すると
そのスクリプトがあるディレクトリにファイルが作成される。

echo "test" > test

しかし、cronでそのスクリプトを実行するとtestファイルは、
rootディレクトリに作成されてしまう。
これに気が付くまで

そのため、cronを実施する場合、リダイレクトしたいディレクトリのパスを毎回記載する必要があった。

echo "test" > 対象ディレクトリ/test

パスが長ければ長いほど手間がかかるため、楽が出来ないかと探したところdirnameコマンドを知った。
dirnameコマンドはファイルが設置されている、パスを取得を取得できるコマンド。

dirname /etc/fail2ban
/etc

また、$0 は実行スクリプトを取得できる。それとpwdとサブシェルを合わせると絶対パスを取得できる。

BASE_DIR=$(cd $(dirname $0); pwd) 
echo "test" > ${BASE_DIR}/test

上記を用いるとcronからスクリプトを実行しても、
実行スクリプトと同じ階層からリダイレクトしたファイルを取得できた。

参考
[bash] 実行スクリプトの絶対パスの取得
https://qiita.com/koara-local/items/2d67c0964188bba39e29

今更ゼルダの伝説ブレスオブザワイルドをやっていました。

はじめは、すぐにゲームオーバーなるわ、どこにいけばいいのやらで退屈していましたが、
祠を見つけ出すと見事にはまってしまいました。

ひとまず祠を一通り集めた上でクリアしましたとさ。クリア時のプレイ45時間だったのに、クリア後の祠集めで
95時間になってるのはさすがのボリュームでございます。

当時、必死に逃げていたライネルも今となればなつかしいものです。

久しぶりにUnityで2dゲームを作るにあたってゲームのアニメーションを書いてました。
いつかできたら見せてあげたいなあと思います。

かわりにふと書いた落書き

はやくかえろ?的な

個人的にブレザーのしわに挑戦をしています。

ブログのスパム攻撃とか変なアクセスが気になるので、日本とgoogle以外のIPをブロックするスクリプトを作りました。
テスト環境でうまくいっているみたいなので、アップ
ipblker

#!/bin/bash
#ssコマンドで15個までのIPを取得します。
ip=`/usr/sbin/ss -t | awk -F : '{print$2}' | awk '{print$2}' | grep -v Peer | sort | uniq | head -n 15`
echo "$ip"
echo "$ip" > /root/ipblk/ip_listold

#whitelistに記録されているIPを除外しip_listoldとして吐き出します。
for i in `cat /root/ipblk/whitelist`
do
cat /root/ipblk/ip_listold | grep -v "$i" > /root/ipblk/ip_listold1
cat /root/ipblk/ip_listold1 > /root/ipblk/ip_listold
cat /root/ipblk/ip_listold
cat /root/ipblk/ip_listold | wc -l
echo ""
echo "$i"
echo ""
done

#ip_listoldから日本とgoogleのIPをwhitelistに追加します
#それ以外をブロックし、blacklistに追加します
ipl=`cat /root/ipblk/ip_listold`
for i in `echo "$ipl"`
do

curl -kfsS https://ipinfo.io/"$i"/country >> /root/ipblk/ip_country
if [[ "$?" -eq 0 ]]; then
  echo "終了コードは0です 1"
   if [[ `tail -n 1 /root/ipblk/ip_country` = JP ]]; then
      echo "nonblock_JP"
      echo "$i"
      echo "$i" >> /root/ipblk/whitelist
      continue
   else
     echo 日本ではない
    fi
elif [[ "$?" -ne 0 ]]; then
  echo "終了コードは0以外です 1"
  continue
fi

curl -kfsS https://ipinfo.io/"$i"/ | grep org | awk '{print$3}' >> /root/ipblk/ip_org
if [[ "$?" -eq 0 ]]; then
  echo "終了コードは0です 2"
   if [[ `tail -n 1 /root/ipblk/ip_org` = "Google" ]] && [[ `host "$i" | awk -F . '{print$7}'` = "googlebot" ]]; then
      echo "nonblock_Google"
      echo "$ip"
      echo "$ip" >> /root/ipblk/whitelist
       continue
   else
      echo googleではない
   fi

  elif [[ "$?" -ne 0 ]]; then
      echo "終了コードは0以外です 2"
  continue
fi

curl -kfsS https://ipinfo.io/"$i"/ip >> /root/ipblk/ip_ip
if [[ "$?" -eq 0 ]]; then
  echo "終了コードは0です 3"
   if [[ `tail -n 1 /root/ipblk/ip_ip` = "127.0.0.1" ]]; then
      echo "nonblock_loopback"
      continue
   else
      echo `tail -n 1 /root/ipblk/ip_country`
      echo /sbin/iptables -I INPUT -s $i -j DROP
      echo iptables -I INPUT -s $i -j DROP >> /root/ipblk/blacklist
   fi
  elif [[ "$?" -ne 0 ]]; then
      echo "終了コードは0以外です 3"
      echo 127.0.0.1ではない
  continue
fi

done

と、 ipinfo.io 様からIPの情報を取得しています。
後半の行でIPをブロックしますが、
テストを兼ねてechoを付けていますので、
実際に実行される場合は、echoを外してください。

echo iptables -I INPUT -s $i -j DROP
iptables -I INPUT -s $i -j DROP

次に上記のスクリプトをcronに設置します。

cd /var/spool/cron/crontabs/
vim root
*/1 * * * * /root/ipblk/ipblker

エラー通知のみ受信したい場合
*/1 * * * * /root/ipblk/ipblker 1> /dev/null

全ての通知を受信しない場合
*/1 * * * * /root/ipblk/ipblker >/dev/null 2>$1

cronのログ自体を確認したい場合

vim /etc/rsyslog.d/50-default.conf

#cron.*                          /var/log/cron.log
コメントされている場合外してあげます。
cron.*                          /var/log/cron.log


テスト用としてcronを1分に一回と設定していますが、
ipinfo.ioの1日に取得できるIPは無料だと1000回までなので、
それを超えない設定にします。
今回の場合、1回につき最大IPを15個まで取得できるように設定しているので、
30分に一回、ipblkerを実行します。

*/30 * * * * /root/ipblk/ipblker 1> /dev/null

何かエラー通知あれば、確認して調整していく予定です。

友人が文芸作品のフリーマーケット(文フリ)に小説を
出店するとのことで小説のカバーを担当しました。

当日、私が文フリに遊びに行ったところ友人から
製本されたものを頂いたのでアップします。

高校生の百合系もの

横からみると結構分厚い

おまけの裏表紙

本についてはそこそこ売れたそうです。コロナの時期にも関わらずよかった。
友人とは5年前くらいに知り合っていつかお互いの協力した何かしら作品ができたらいいねと
話してたのでついに実現できてよかったなあと思います。

お礼として寿司とクレープをご馳走になりました。ありがとうございました。
来年も機会があれば、小説の挿絵も描かないとなと他の文フリの作品を見て思いました。

サーバー監視において、高負荷が上がった場合、
サーバーにssh接続できないことがあるからcronで対応することがあります。
その条件として何かしらのプロセス数を用いることが多いからテンプレートを作成しました。
#!/bin/bash
ps=`ps -ef | grep <監視したいプロセス> | wc -l`
date=`date '+%Y/%m/%d - %H:%M:%S'`

if [[ $ps -gt <プロセス数> ]]; then
echo $date ; <実行内容>

else
  echo $date  "プロセス数:$ps"

fi

cronとあわせる場合
1 * * * * /usr/local/bin/test >> /var/log/test_log

elseの結果を /var/log/test_log から確認した場合、
2021/10/02 - 13:22:01 プロセス数:1