それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

ssh をiptablesで国内限定にする(日本国外のIPから規制する)

グローバルIPssh を有効にしたらスキャンがいっぱい来る

別に、実害は無いんだけど、ちょっと気持ち悪いよね。 1時間で1000近いログが溜まるんですね。

ポート22のsshはすげぇアクセス来るんだよね。

ISP側である程度のフィルタをされているはずなんだけど。それでもコレくらい来る。

Dec 21 15:02:13 raspi3 sshd[3524]: Received disconnect from 115.238.245.2 port 33445:11:  [preauth]
Dec 21 15:02:13 raspi3 sshd[3524]: Disconnected from 115.238.245.2 port 33445 [preauth]
Dec 21 15:03:49 raspi3 sshd[3532]: Received disconnect from 115.238.245.6 port 34296:11:  [preauth]
Dec 21 15:03:49 raspi3 sshd[3532]: Disconnected from 115.238.245.6 port 34296 [preauth]
Dec 21 15:04:34 raspi3 sshd[3537]: Received disconnect from 221.194.47.245 port 57877:11:  [preauth]
Dec 21 15:04:34 raspi3 sshd[3537]: Disconnected from 221.194.47.245 port 57877 [preauth]
Dec 21 15:05:40 raspi3 sshd[3542]: Received disconnect from 221.194.47.243 port 52506:11:  [preauth]
Dec 21 15:05:40 raspi3 sshd[3542]: Disconnected from 221.194.47.243 port 52506 [preauth]

大学の研究用のガチのグローバルIPだと秒間で10とか来てたから、ソレを考えたら少ない方だわ

公開鍵認証のみなので実害はない。

preauth で止まってるし、password をブルートフォース攻撃されるわけでもないので、別にいいんですが、ログをみてるときにちょっと気持ち悪いよね。 家のドアチャイムを定期的にピンポンダッシュされて空き家か調べられるのはっちょっとだけ良い気がしない。

日本国内のIPアドレスに限定してみよう。

ssh のポートについては日本国内のIPアドレスに限定してみようと思い立った。

日本国内のIPアドレスは何処で取れるのか?

ぐぐったらいくつか在るんだけど、今回は、 https://ipv4.fetus.jp/ を使うことにした。

日本国内のIPアドレスは→ https://ipv4.fetus.jp/jp.txt

iptableにコレ全部登録するの?

流石に約3000件を登録するのはちょっと現実的じゃないよね。

iptables で第三国のIPアドレスを制限して、日本国内に限定したいとか思ったんですが。IPアドレスの範囲を指定するのって思った以上に不便。

iptablesの件数がどこまでも伸びていってしまうよね。

ipsetを使います。

ipsetを使えばかんたんに設定できるようです。

調べてみたら カーネルにnetfilter に ipset という、IPアドレスをグルーピングしてフィルタを記述できるセットが用意されていた。

ipset のインストール

sudo apt search ipset 
ipset/stable 6.30-2 armhf
  administration tool for kernel IP sets
sudo apt install ipset

ipset の使い方

ipset は、名前を付けてリスト(フォルダ的なもの)にIPアドレスか、ネットワーク・アドレスをガンガン放り込んでグルーピングしていくもの

ipset でリストを作る・潰す

リストの作り方と削除

sudo ipset create my_list hash:ip
sudo ipset destory my_list

hash:ip は ip アドレスで、hash:net はネットワークで、それぞれ指定する。件数が多いものはまよわず net を使う。

sudo ipset create my_list hash:net
sudo ipset destory my_list

ipset のリストにIPを登録する・確認する・削除する

ip set のリストにIP・ネットワークを登録し確認し、削除する。

sudo ipset add my_list 1.0.16.0/20
sudo ipset list my_list
sudo ipset del my_list 1.0.23.58

ただし、hash:ip で定義したリストに、サブネット切ったネットワークで、ガッツリIPを放り込むと大量にエントリが発生するので注意が必要

hash:net の方がいいと思う。

実際に入れてみた例

$ sudo ipset create my_list hash:net
$ sudo ipset add my_list 1.0.16.0/20
$ sudo ipset list  my_list
Name: my_list
Type: hash:net
Revision: 6
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 396
References: 0
Members:
1.0.16.0/20

国内限定にするフィルタを作る

ipset の使い方がわかったところで、iptables と連携するための ipset を作ります。

日本国内のIPをざっくり取得する

日本に割当てられたIPv4アドレスを取得する

curl https://ipv4.fetus.jp/jp.txt | \grep -v  '^#'

何度も取得に行くと負荷かけちゃうので、適当にキャッシュした方がいいです。

日本国内IPをざっくり登録する

取得した結果のすべてを ipset で自分の許可リストに放り込んで行きます。

$ curl https://ipv4.fetus.jp/jp.txt | \grep -v  '^#'  |xargs -I@ -P 0  sudo ipset add my_list @

登録したら、確認する

登録ができたら確認してみます。

$ sudo ipset list my_list

登録結果を保存する

登録した結果を保存して

 sudo ipset save my_list > my_list.txt

iptablesでフィルタを作る準備をします。

万が一失敗しても死なないように、別ポートでもsshd を起動しておきます。

/etc/ssh/sshd_config

Port 22
Port 2222

port 2222 でもssh を起動しておきます。

ssh -p 2222 で接続ができることを確認

失敗した時でも安心できるように別ポートが使えることを確認

ssh localhost -p 2222

ローカルIPの追加。

今回は、国内限定にする=ホワイトリスト方式。なので、許可リストにローカルIPを入れておきます。

sudo ipset add my_list 192.168.0.0/16
sudo ipset add my_list 10.0.0.0/8
sudo ipset add my_list 172.16.0.0/12

最後に、ipset の登録値を使ってiptablesを構成する

sudo iptables -I INPUT -m state --state NEW -p tcp --dport 22 -m set --match-set my_list src -j ACCEPT

iptables の設定が出来たことを確認

takuya@raspi3:~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh match-set my_list src

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

設定を保存( permanently/persist)して再起動後も有効な設定 にする

systemd をつかって ipset の取得を定期実行にしたりしておく。

起動時にipset を再度有効にするようにしておく

sudo sh -c 'ipset save > /etc/ipset.conf'

iptablesの設定の保存。これは定番 iptables が再起動後に ipset のリストを使うようにしておく

sudo sh -c 'iptables-save > /etc/iptables.up.rules'

再起動後に実行されるようにする。

再起動に有効にする。

sudo vim /etc/network/if-pre-up.d/iptables-with-ipset
sudo chmod ug+x /etc/network/if-pre-up.d/iptables-with-ipset

/etc/network/if-pre-up.d/iptables

#!/bin/sh
##
## 2017/12/23 記述 
## /etc/network/if-pre-up.d/iptables-with-ipset
## 

# ipset からリストを読み込む
ipset restore < /etc/ipset.conf
# ipset を使ってiptablesを構成する
iptables-restore  < /etc/iptables.up.rules

これで、再起動に有効になる。

メモなど

本当は iptables じゃなくて、openssh側の設定でやりたいんだけどなぁ。

openssh-server の拒否リスト(もしくは MatchAddress )的なところで、ホワイトリストを使えれば良いんだけどなぁ。

iptablesはいろいろな設定をドンドン書いていくので、ゴチャゴチャしすぎて整理できないから辛い。

もしかしてv4の方が使いやすい??

v4 の在庫は枯渇してて、どの国にドレだけ割当てられてるかすでに決まっていて今後大幅に増減はないと考えるなら、v4のフィルタって更新やメンテをあまりしなくても動くんじゃないですかね。

参考資料

https://inaba-serverdesign.jp/blog/20150209/ipset_iptables_country_centos6.html