君は心理学者なのか?

大学時代に心理学を専攻しなぜかプログラマになった、サイコ(心理学)プログラマかろてんの雑記。

僕が借りているサーバが、世界各国から「1日900回」不正アクセスされている話〜/var/log/secureからみえる攻撃者の影〜

f:id:karoten512:20180210104805p:plain

私用で使っているサーバの/var/log/secureをみてみた

f:id:karoten512:20180210112501p:plain

見に覚えのないアクセスが大量にある。。。

しかもuserはrootだったりadminだったり。。。

これ、不正アクセスってやつか?

1日どれくらい不正アクセスを試みられているのか

2/4の不正アクセス回数を、すごい雑な方法だけどしらべてみた。

$ cat /var/log/secure | awk '/Feb  4/ && /Failed/' | wc -l
943

わお。943回。どこから不正アクセスされているんだろ。

いったんipだけ抽出して、

どこの国から狙われているか調査してみた。

使用unixコマンド

ここらへんを知っておくとログ調査に便利。

調査手順

ipアドレスのみ抽出

$ grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' /var/log/secure > ips.txt

-Eオプションで正規表現が使えます

40.69.203.57
40.69.203.57
40.69.203.57
172.31.32.142
94.183.180.86
94.183.180.86
94.183.180.86
...

※ 念のためipアドレスは編集しております

ipの重複をなくす

sort ips.txt | uniq > unique_ips.txt

sortしてuniqして、ipをuniqueにします。

101.78.196.27
103.16.142.208
103.20.251.158
103.213.115.45
103.216.205.51
103.22.171.1
...

ipがユニークになった。

ipジオロケーションサービスに投げる

$ curl http://api.hostip.info/get_html.php\?ip=40.69.203.57

これを投げると、

Country: UNITED STATES (US)
City: (Unknown city)
IP: 40.69.203.57

いい感じにデータが返ってきます。

#!/bin/bash
while read ip
do
  curl http://api.hostip.info/get_html.php\?ip=$ip\&position=true
done < unique_ips.txt

run.shという名前で保存して、

$ sh run.sh > countries.txt

こんな感じで走らせ、結果をテキストファイルに保存します。

awkコマンドで国だけ抽出

$ cat countries.txt | awk '/Country/' | sort | uniq

とすると、先ほどの結果の「Country」だけ抽出できます。

結果

Country: (Private Address) (XX)
Country: (Unknown Country?) (XX)
Country: AUSTRALIA (AU)
Country: AUSTRIA (AT)
Country: BRAZIL (BR)
Country: BULGARIA (BG)
Country: CANADA (CA)
Country: CHILE (CL)
Country: CHINA (CN)
Country: COLOMBIA (CO)
Country: CROATIA (HR)
Country: DENMARK (DK)
Country: EUROPEAN UNION (EU)
Country: FRANCE (FR)
Country: GERMANY (DE)
Country: HONG KONG (HK)
Country: HUNGARY (HU)
Country: INDIA (IN)
Country: INDONESIA (ID)
Country: IRELAND (IE)
Country: ISRAEL (IL)
Country: ITALY (IT)
Country: JAPAN (JP)
Country: KOREA, REPUBLIC OF (KR)
Country: MALAYSIA (MY)
Country: MEXICO (MX)
Country: NETHERLANDS (NL)
Country: NORWAY (NO)
Country: PAKISTAN (PK)
Country: PERU (PE)
Country: PHILIPPINES (PH)
Country: POLAND (PL)
Country: RUSSIAN FEDERATION (RU)
Country: SENEGAL (SN)
Country: SLOVENIA (SI)
Country: SPAIN (ES)
Country: SWITZERLAND (CH)
Country: TAIWAN (TW)
Country: THAILAND (TH)
Country: UKRAINE (UA)
Country: UNITED KINGDOM (GB)
Country: UNITED STATES (US)
Country: VIET NAM (VN)

おおー。

世界各国から狙われている笑

攻撃元を特定するのは難しい

ただ、これだけだと発信元を特定するのは難しい。

攻撃者はいくつもの踏み台サーバを使って攻撃することにより、

自分の発信元を特定しにくくしているから。

なので、世界各国からアクセスされているからと言って、

本当に世界各国の人が狙っているかどうかはわからない。

攻撃を回避するには

色んな方法があるが、

今回はポート番号を変えてみた(次回)

puttyからsshでログインしようとした時に、Disconnected: No supported authentication methods availableと言われてしまった

f:id:karoten512:20180210003701p:plain

puttyを使ってsshでパスワード認証を使ってログインしようとした

こんなエラーが表示されました。

Disconnected: No supported authentication methods available

とりあえずサーバに入り、/etc/ssh/sshd_configをみてみる

いろいろな原因が考えられるが、とりあえずサーバの設定ファイルをみてみた。

PasswordAuthentication no

パスワード認証が使えないように設定されている。

だいぶ前にいじったから忘れてた。

セキュアじゃなくなるけど

一旦

PasswordAuthentication yes

とした。そうしたらログインできるようになった。

その後、すぐにnoに戻した。

duコマンドを使って、現在いるディレクトリにあるファイルの合計サイズを出したい

f:id:karoten512:20180209233955p:plain

現在いるディレクトリにあるファイルの合計サイズを出したい

$ du -sh .

解説

sオプションについて

sオプションをつけないとどうなるか

$ du -h .
1.2G    ./directoryA
1.2G    ./directoryB
 24K    ./pra

すべてのディレクトリのサイズがでてくる。

つけるとどうなるか

$ du -hs .
3.6G    .

普通に合計値が出る。

hオプションについて

つけないとどうなるか

$ du -s .
7614736 .

512バイト単位で出る。 なぜだ。

つけるとどうなるか

$ du -sh .
3.6G    .

いい感じの単位で出してくれる。

Angularを使って、カートで商品を選択する画面を作ってみた〜親子コンポーネント・サービス間連携をしてみる〜

Angularの復習をしようと思った

今回の開発で、Angularを使った。

基本フロント側は一人で開発をしていたが、

1画面で扱っているコンポーネントの数が600個をこえたり、

画面間で引き継ぐ項目がどんどん増えてきたりで、

だんだん大変なことになってきた。

なぜ大変な事になってきたか

サービス増えすぎ問題

それぞれのコンポーネントで値(以下、モデル)を共有させようとした時に、

サービスをDIして共有させていた。

モデルごとにサービスを作ってしまっていたので、

モデルが増えるたびにサービスが増え、大変なことになってしまった。

サービスの役割2つあるよ問題

ページ間をまたがないデータはコンポーネントに持たせればよいのに、

なぜかサービスにデータを持たせてしまっていた。

よって、

サービスが「データの保持」「データ処理」の2つの役割を持ってしまっていた。

サービスの役割が曖昧になり、追加でいじる時にどこをいじればよいのかわかりにくくなってしまっていた。

作ったのがこれ

f:id:karoten512:20180128205736g:plain

github.com

説明

構成

f:id:karoten512:20180128211839p:plain

最上位にAppComponentをおく。

このコンポーネントが、この画面で扱うすべてのプロパティを保持している。

子供はAppComponentのプロパティを共有している。

子供で起こったイベントは、AppServiceを通じてAppComponentに伝えられる。

商品をクリックした時、どのように画面が変更されるか

クリックしたことをAppServiceに伝える

f:id:karoten512:20180128211859p:plain

AppServiceは、AppComponentが持っているプロパティを操作する

f:id:karoten512:20180128212001p:plain

コンポーネントに、AppComponentのプロパティ変更が伝わる

f:id:karoten512:20180128212033p:plain

コンポーネントは親のプロパティを共有しているので、

そのまま親のプロパティの変更が伝わります。

画面に結果があらわれる

f:id:karoten512:20180128212121p:plain

まとめ

今回、AppComponentに画面上で扱うすべてのプロパティをもたせたので、

シンプルになった。

また、AppServiceを用いたことにより、

子供から親へのイベントバブリングと言った複雑なことをしなくても良くなった。

今後はこういう設計にしていきたいなぁ。

module.exportsとは何か、どうもわからなかったので実験してみた〜Node.jsにて外部moduleをrequireする〜

f:id:karoten512:20180128191834p:plain

いきさつ

今まで何も考えずに

npm install

して、

var module = require('module-name');

して使ってきたが、

Node.jsについて知らなさすぎて、

node_moduleディレクトリ配下に格納されているmoduleをみても、

ぜんぜん読めないことに気づいた。

exports.moduleが分かればだいぶ読めるようになるかな、と思い、

まずはexports.moduleについて理解することにした。

ディレクトリ構造

├── main.js
└── node_modules
    └── weather-module.js

やってること

main.jsからweather-module.jsを読み込む。

// main.js
var weather = require('weather-module');
weather.today();
weather.yesterday();
// weather-module.js
/** weatherオブジェクトの生成 */
var weather = {}; 

weather.today = function() {
  console.log('晴れだよ');
}

weather.yesterday = function() {
  console.log('雨だったよ');
}

module.exports = weather;

わからないこと

module.exports = weather;

の部分で何をやっているのかわからない。

結論

// main.js
require('weather-module');

requireが、

weather-module.jsでmodule.exportsに渡されているオブジェクトを

返してくれるので、それを使用することができる。

実験手順

何を読み込んでいるのか調べる

これを外部ファイル(main.js)から読み込んで使いたい。

// main.js
var weatherModule = require('weather-module');
console.log(weatherModule);

main.jsを実行

$ node main.js
{ today: [Function], yesterday: [Function] }

weatherオブジェクトそのものが渡っているようである。

weatherオブジェクトはmodule.exportsに渡されているのものなので、

require('weather-module');

module.exportsに渡されているオブジェクトを返す、と考えられる。

module.exportsに複数のオブジェクトを渡してみる

/** weatherオブジェクトの生成 */
var weather = {}; 

weather.today = function() {
  console.log('晴れだよ');
}

/** 関数の追加2 */
weather.yesterday = function() {
  console.log('雨だったよ');
}

/** temperatureオブジェクトの生成 */
var temperature = {}; 

temperature.today = function() {
  console.log('25');
}

temperature.yesterday = function() {
  console.log('15');

}

module.exports = { 
  weather: weather,
  temperature: temperature // もう一個渡す
};

main.jsを実行

$ node main.js
{ weather: { today: [Function], yesterday: [Function] },
  temperature: { today: [Function], yesterday: [Function] } }

やはり、

require('weather-module');

module.exportsに渡されているオブジェクトを返すようだ。

まとめ

require('hoge-module');

hoge-module.jsにて、

module.exportsに渡されているオブジェクトを返す。

逆に言えば、

module.exportsに渡していないオブジェクトは使えない。

外部から使用したいオブジェクトは、必ずmodule.exportsに渡すこと。

参考

numb86-tech.hatenablog.com

本番環境にテストデータを入れてしまったときは、deleteではなくtruncateでテーブルからレコードを一掃しよう〜deleteとtruncateの違い〜

いきさつ

社内で使用するシステムの開発が一旦落ち着いたので、

本番環境構築することになった。

といってもすでにテスト環境を構築しているので、

慣れたものである。

種々のインスタンスを立ち上げ、ansible用のユーザを作成し、

playbookの諸々の設定位置を少し書き換ええ、流すだけで良い。

(playbook、つくるのは大変だった)

で、いつものように本番環境にデプロイし終わり

きちんと登録できるか一通りの操作をした。

そこで先輩が一言

「本番環境上に作ってしまったデータは残してはいけないから、

きちんとtruncateしといてね」

僕はハッとした

当たり前だが、その一言に僕はハッとさせられた。

基本的に本番環境はまっさらな状態で、お客さんに使ってもらう。

使ってもらう時、

私たち開発者がテスト用に打ったゴミデータが入っていると、

アカウント管理をしているとはいえ、

万が一そのゴミデータのせいでバグが起こりうる場合もある。

(そもそも本番環境なので、

 テストデータが紛れ込んでいると言うのはおかしい、というのもある)

なので

テストデータは消しておく必要がある。

そのときに注意しておくのがdeleteとtruncateの違いだ。

deleteとtruncateの違い

idがauto_incrementになっていた場合、

deleteは連番情報を保持したまま。

truncateは1から裁判し直す。

という違いがある。

まっさらな状態にする、という意味ではtruncateが適している。

まとめ

本番環境の扱いには気をつけよう。

シェルで文字列を比較したときに、[: =: unary operator expected :というエラーがでる

f:id:karoten512:20180119002642j:plain

いきさつ

空行を検出するスクリプトを書いていた

古池や

蛙飛び込む
水の音

をシェルに読み込ませ、空行があったときに

「空行があるよ」というスクリプトを書いた。

※ 実際の処理を簡略化してます

#!/bin/bash
while read line
do
  if [ $line = '' ]; then
    echo '空行があるよ'
  fi  
done < line.txt

しかしうごかないんだなこれが

test.sh: line 4: [: =: unary operator expected

というエラーがでる。

どこでエラーが置きているかわからないので、

#!/bin/bash
while read line
do
  echo $line # ここで出力する
  if [ $line = '' ]; then
    echo '空行があるよ'
  fi  
done < line.txt

echo で毎行出力してみる。

古池や

test.sh: line 5: [: =: unary operator expected
蛙飛び込む
水の音

どうやら空行を読み込んだ時に起きているエラーのようだ。

調べてみた

fluidx.exblog.jp

変数に格納されている文字列比較において、 文字列の比較は文字列と行う必要があるところを、 文字列と何かわからない型の変数を比較してしまっているので、 このようなエラーが発生するらしい。

空行は「文字列かわからない型」なのか…?

ちょっとそこは釈然としない。

対処

#!/bin/bash
while read line
do
  if [ "$line" = '' ]; then
    echo '空行があるよ'
  fi  
done < line.txt

$lineを""でかこむ。文字列にキャストしている感じなのかな。

結果

空行があるよ

動いた。

シェルは独特。でもサッとかけるから便利。

環境を選ばないしねぇ。

最強のポータビリティ言語である。