自宅サーバーを公開したら、早速多くのアクセスがきました。
SSHサーバーへの大量のアタックが・・・・・(;´д`)
公開した深夜に、サーバーマシンがうるさくて目が冷めました。
どうも、パスワードを総当りに試してくるブルートフォースアタックとかいうたぐいのものらしく、
ご丁寧に我がサーバーは、ダメです。ダメです。と延々と返事していた模様。
いやぁ、すごいですね。
一応、SSHの設定でrootでのログインはできないし、大丈夫だとおもったのですが、
root以外もpostgresとか手当たり次第ですね。
まぁ、特定のユーザー以外は基本/sbin/nologinシェルなので、パスワードの総当りアタックじゃ突破される可能性は低いだろうけど。
(鍵認証でも使えばさらにパスワードアタック意味なくなるけど、固定のパソコンからのアクセスだけじゃないので今回はパス。)
まぁ、なにはともあれ、とにかくマシンがうるさい。
アタック攻撃のために電気代を払って、睡眠の邪魔をされるのが非常に忌々しいので、
LinuxのFirewall機能、iptablesについて少し調べた。
まぁ、ざっくりいうとiptablesとは、パケットの流れのルールを決めたり、パケットの中身を書き換えたりする。
このIPアドレスからアクセスさせないだとか、このポートからはアクセスさせるだとか。このポートからのアクセスはポート番号を変更するだとか。
もう少し具体的に言うと、Webサーバー(apache)を立てたら外から見れるようにするために、http通信が使う80番ポートを通す。
でも、FTPは使ってないから20番ポートは塞いでおこう。
といった具合。
今回は、この「パケットの流れのルール」を操作することで、不正アクセス行為を少し黙らせることにした。
さて、もう少し突っ込んだ話をする。
iptablesは、filterテーブル、natテーブルと呼ばれるテーブルにルールを書く。
今回は、パケットの流れのルールを操作するので、filterテーブルを使う。
filterテーブルには、チェインと呼ばれるものがある。
また、デフォルトで3つのチェインが揃っている。
- パケットが入る際に利用するINPUTチェイン
- パケットが出ていく際に利用するOUTPUTチェイン
- インターフェース間をまたぐ際に利用するFORWARDチェイン
なんで、チェインなのか知らないが、まぁ、上から下にルールを鎖みたいに繋いで行くからチェインなのかなと、ざっくり理解。
今回はやかましいSSHのアクセスをどうにかするべきなので、INPUTチェインにルールを書く。
さてiptablesにルールを書く方法は二つある。
- コマンドを叩きながら一行ずつ反映させる方法
- テキストファイルにルールを書いて読み込ませる方法
自分は前者で実行していたのだが、正直後者のほうが楽かも。
ということで後者のやりかたを記述する。
まず、rootになった後、ホームディレクトリに移動する。
#cd ~/
別にホームディレクトリでもどこでもいいのだが、編集したファイルをどこに置いたか忘れそうなのでホームにする。
次に、iptables.txtという名前で現在のファイアウォールの設定をファイルに書き出す。
#/sbin/iptables-save > iptables.txt
rootユーザー以外から一切の変更や読み込みを許可したくないので、
#chmod 600 iptables.txt
そして、中身を見てみよう。
まぁ、色々書いてあると思うが、自分は下記のように書いた。
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [42525:19874252]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 --tcp-flags FIN,SYN,RST,ACK SYN -m hashlimit --hashlimit-burst 5 --hashlimit-upto 1/min --hashlimit-mode srcip --hashlimit-name ssh_limit --hashlimit-htable-expire 300000 -j ACCEPT
-A INPUT -j LOG --log-prefix "IPTABLES_REJECT "
-A INPUT -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
上部の方のフィルター定義はとりあえず触れずに、ルールの部分を説明する。
-Aは末尾に記述
INPUTはINPUTチェインを指す
-j は動詞になる。(を~する) ACCEPT(許可) DROP(捨て) REJECT(不要だと送り返す) LOG(ログる)
ルール1は、パケットの状態がRELATED,ESTABLISHEDのものを許可。
つまり、既に一度OKが出たものは再度見る必要がないので許可するということ。コレをチェイン頭に持ってくることで、余計なパケットをチェックする手間が減る。
ルール2は、プロトコルがicmpなら許可。pingだったり、エラーメッセージだったり色々あるので、とりあえず許可。
ルール3は、ループバック、つまり自分から自分へのデータ転送は全部許可ってこと。
ルール4は、プロトコルがtcpで、ポート番号が80番のものを許可。つまりHTTPでアクセスしたものは許可ってことだ。
そして、これが重要。
ルール5は、えらく長いのだが、要は、プロトコルがtcpでポート番号22番、つまりSSHについてのルールについて書いている。
ざっくり、説明すると、新規接続で5回きたら(つまり5回失敗している)、それ以降は一分に一回しか接続できなくする。ただ、そのままだと永遠に一分に一回になっちゃうので、300秒(5分)したら制限は外すよ。ってことだ。
これで、馬鹿みたいにアタックしてきた数も制限される。
ルール6は今までのルールで許可されなかったものを捨てる前にロギングするよ~ってこと。ちなみにログの識別子に”IPTABLES_REJECT “ってつけてるのは、このログはrsyslogで後で見つけやすいように目印つけてるだけ。
ルール7はポート番号に届かんかったわ~って送信パケットにエラーメッセージを返してパケットを破棄する。
ルール8はFowardに関するルール。
これは、複数のサーバーを使ったり、サーバーをプロキシサーバーに使ったりとか色々するときに使うっぽい?とにかく、このマシンじゃFowardはしないよ!ってエラーを返して終了する。
さて、ここまで書いたら
#/sbin/iptalbes-restore iptables.txt
を実行して反映させる。
その後、
#iptables -L
で確認。
きちんと反映されてるかをチェック。
これで問題なければ大丈夫だろう。
しかし、このままでは実はサーバーがリスタートしたら設定が消える・・・。
そこで、セーブをする。
#service iptables save
これでセーブされたら、
#service iptables restart
でiptablesをリスタートしてみよう。
その後、もう一度、
#iptables -L
で確認して問題なかったら反映されていることになる。
まぁ、実のところ、ルーターで80番と22番以外はサーバーに通さない設定になっているので、その他のicmpとかは設定したけど届いてないんだけどね、一応念の為色々と設定してみた。
まだまだ、奥が深いiptablesだが、ざっくりな私は今回はこれまで。
また、機会があれば調べてみよう。
ちなみに、その後のサーバーへの過度なアクセスは減ったんだけど、バーストした後も、1分に1回のアクセスが結構くるもんだからログがうざったくて仕方がない・・・。
他に、不正アクセスと思われるIPアドレスを自動的にアクセス拒否リストに追加する方法とかあるのだけど、どうせ自前のサーバーだし、手っ取り早くsshのポート番号ごと変えることを検討しようと思う。