前置き
サーバへの余計なトラフィックを遮断します。
/var/log/secure に sshd へ BruteForce/DoS の痕跡が記録されていて、今年に入ってその数がかなり多くなってきました。サーバへの攻撃が予測・検出される場合、「sshd のポートを非標準の番号へ変更して防御する」
手法が分散型の上に間隔が短いため、結果的に DDoS になることもあります。
「ssh サーバが IP 192.168.232.226 からの接続のためにポート 22 を開いたが、認証する前に切断された」という意味を持つ複数の記録。
Mar 10 07:26:57 MyHost sshd[710923]: Received disconnect from 192.168.232.226 port 43292:11: Bye Bye [preauth]
Mar 10 07:26:58 MyHost sshd[712577]: Received disconnect from 192.168.232.226 port 42130:11: Bye Bye [preauth]
…
普通にブルートフォースを受けています。
という記述がよそ様のサイトに散見されますが、敵も然る者引っ掻くもの。
ポートを変更した程度では一時しのぎにしかなりません。
SSHGuard という優れたプログラムが公開されているので、これを利用します。
SSHGuard の動作は以下で、しつこく不正接続されるほど強固に (1 → 4) 接続元をブロックします。
なお、下記 4-1 にある通り永久ブロックするのは sshd ポートだけでなく、攻撃元 IP アドレスからの接続がすべて遮断されます。
- sshd に対して認証失敗があると、接続元を一定期間の監視対象にするとともに攻撃スコアを蓄積する。
→ 監視期間中にアクセスが無ければ、接続元を監視対象から外す。
- 監視期間が終了する前に加えて認証失敗があれば、監視期間を延長して攻撃スコアを蓄積する。
→ 攻撃スコアがしきい値に達したら接続元を一時ブロックする。
(一時ブロック: 監視時間が経過したり SSHGuard が再起動されるとブロックが解除される)
- それでも接続試行が止まらなければ、接続元を一時ブロックしたまま監視期間をさらに延長して攻撃スコアを蓄積する。
- それでも接続試行・認証失敗が止まらなければ、接続元を永久ブロックする。(BLACKLIST_FILE が有効の場合)
(永久ブロック: SSHGuard が再起動されてもブロックを継続する)
(冗談でも攻撃しないこと。メールや http/https 等も遮断されるので絶縁状態となります)
0. インストール要件
OS AlmaLinux 9.3 (Shamrock Pampas Cat) 本稿記述時の最新版 防御ソフト SSHGuard 2.4.2 firewalld 1.2.5 AlmaLinux に付属のもの ipset 7.11
1. firewalld の確認
$ LANG=C dnf info firewalld | egrep 'Name|Version|Release'
$ LANG=C dnf info ipset | egrep 'Name|Version|Release'
Name : firewalld Version : 1.2.5 Release : 2.el9_3
Name : ipset Version : 7.11 Release : 8.el9
2. EPEL のインストール
$ su
# dnf install epel-release #*1
*1が使用不能の場合はこちらを実行↓
# dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
# LANG=C dnf info epel-release | egrep 'Name|Version|Release'
# exit
Name : epel-release Version : 9 Release : 7.el9
$
3. SSHGuard のインストールと起動
3-1. SSHGuard をインストールする。
$ su3-2. 設定ファイルを用意する。
# dnf install sshguard
# LANG=C dnf info sshguard | egrep 'Name|Version|Release'
Name : sshguard Version : 2.4.2 Release : 7.el9
# cat /etc/sshguard.conf | grep -v '^#' | grep -v '^$'3-3. SSHGuard を起動する。
# vim /etc/sshguard.confjournalctl のオプションスイッチ
BACKEND="/usr/libexec/sshguard/sshg-fw-firewalld" LOGREADER="LANG=C /usr/bin/journalctl -afb -p info -n1 -o cat -t sshd"
- -a : すべてのフィールドを出力する。
- -f : 最新のログを追跡して出力する。
- -b : 指定ブートからのログを出力する。(指定を省略しているので現在のブートが対象)
- -p info : SYSLOG と同じ指定レベルのログを出力する。(info を指定している)
- -n 1 : 指定行数を出力する。(1 行を指定している)
- -o cat : ログの内容だけを出力する。(タイムスタンプ等を出力しない)
- -t sshd : 絞り込む SYSLOG の ID を指定する。(sshd を指定している。-t sshd -t unix_chkpwd のように複数指定可能)
BLACKLIST_FILE=, WHITELIST_FILE= を明記する。# cat /etc/sshguard.conf | grep -v '^#' | grep -v '^$'
90: 攻撃スコアの累積が 90 に達するとブラックリストに追加する (永久ブロック) という意味。
# Colon-separated blacklist threshold and full path to blacklist file. # Uncomment to add attackers hitting the threshold to the permanent blacklist # (default: disabled) BLACKLIST_FILE=90:/var/lib/sshguard/blacklist
# Full path to whitelist file. # Uncomment to consider IP addresses, address blocks or hostnames listed in this # file as friendlies that will never be blocked. # (default: disabled) WHITELIST_FILE=/etc/sshguard.whitelist
30 分間の連続した接続失敗を攻撃スコアとして累積する (DETECTION_TIME=1800)。累積はリセットされない。
攻撃スコアは、受けた攻撃の重要度によって決まっている。
blacklist は sshguard の再起動時に読まれるが、読み込みが速くない。
すべての永久ブロックが読み込まれるまで時間を必要とする。
(約 4 アドレス/秒。10,000 アドレスだと約 40 分程度)
# touch /var/lib/sshguard/blacklist # このファイルに永久ブロックする IP アドレスが追記される。
BACKEND="/usr/libexec/sshguard/sshg-fw-firewalld" LOGREADER="LANG=C /usr/bin/journalctl -afb -p info -n1 -o cat -t sshd" BLACKLIST_FILE=90:/var/lib/sshguard/blacklist WHITELIST_FILE=/etc/sshguard.whitelist
# cat /etc/sshguard.whitelist | grep -v '^#' | grep -v '^$' | wc -l
# vim /etc/sshguard.whitelist
0
自分の環境に合わせて、ブロックしない IP アドレスやホスト名を記述する。
(ホスト名は SSHGuard の起動時に一回だけ解決されるので、起動後に IP アドレスを変更すると認識されない)
127.0.0.0/8 192.168.0.0/24 192.168.56.0/24 192.168.122.0/24 client.example.jp
# systemctl enable sshguard
# systemctl status sshguard | grep 'Loaded:'
# systemctl start sshguardenabled になっていること。(自動起動になっていないと disabled になる)
Loaded: loaded (/usr/lib/systemd/system/sshguard.service; enabled; preset: disabled)
# systemctl status sshguard | grep 'Active:'
# exitactive になっていること。(起動していないと inactive になる)
Active: active (running) since Mon 2024-03-04 15:44:51 JST; 3s ago
$
4. 動作確認
4-1. firewalld の設定状況を確認する。
$ su4-2. 永久ブロック対象の増加を確認する。
# firewall-cmd --list-all
ipset の登録タイミングは /usr/libexec/sshguard/sshg-fw-firewalld を参照。
public (active) target: default icmp-block-inversion: no interfaces: enp4s0f0 sources: services: cockpit ssh ports: protocols: forward: yes masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: rule family="ipv6" source ipset="sshguard6" drop rule family="ipv4" source ipset="sshguard4" drop
# firewall-cmd --ipset=sshguard4 --get-entries | tail
(IPv6 の場合は --ipset=sshguard6 とする)
# exit起動して少し放っておくとブロックリストに IP アドレスが追加されていく。
192.168.16.117/32 192.168.1.36/32 10.2.0.39/32 192.168.224.167/32 192.168.223.124/32 10.2.1.11/32 192.168.149.150/32
(これはサンプル。実際はグローバルアドレスになる)
$
5. 間違えて永久ブロック登録された IP アドレスの解除
5-1. firewalld の「実行時」から IP アドレスを解除。
$ su5-2. sshguard のブラックリストから IP アドレスを解除。(firewalld の「永続」に相当)
# firewall-cmd --ipset=sshguard4 --remove-entry=10.2.1.99/32
(10.2.1.99/32 は間違えて登録された IP アドレスの例)
(IPv6 の場合は --ipset=sshguard6 とする)
# systemctl stop sshguard
# vim /var/lib/sshguard/blacklist
(間違えて登録された IP アドレスを削除する)# systemctl start sshguard
# exit
$
6. 実証
疑似攻撃してみる。
攻/防 ホスト名 IP アドレス 攻撃側 Villain 10.2.1.99 防御側 MyHost 10.2.1.10
6-1. 攻撃の様子
6-1-1. MyHost の sshd ポートに接続可能か確認する。
Villain$ telnet 10.2.1.10 226-1-2. MyHost の sshd にブルートフォースをかけてみる。
Trying 10.2.1.10... Connected to 10.2.1.10. Escape character is '^]'. SSH-2.0-OpenSSH_8.7 ^C
← 接続できている。
存在しないユーザ・パスワード違いの攻撃スコアは 10 + 10 + 2 = 22 となっている。
しきい値 30 に達するように攻撃を 2 回繰り返す。
Villain$ for i in {1..2} ; do sshpass -p password ssh -l admin 10.2.1.10 ; done
接続不許可の応答。これは当然。
Permission denied, please try again. Permission denied, please try again.
6-1-3. MyHost の sshd ポートに接続可能か確認する。
Villain$ telnet 10.2.1.10 22
Trying 10.2.1.10... telnet: connect to address 10.2.1.10: Connection timed out
← 接続できなくなった。
6-2. 防御の様子
MyHost$ cat /var/log/messages | grep sshguard | tail
2 回目の攻撃の最初で攻撃スコアの累積が 30 に達して 10.2.1.99 が 120 秒間のブロック対象になった。
Mar 4 20:20:56 MyHost sshguard[6157]: Attack from "10.2.1.99" on service SSH with danger 10.
Mar 4 20:20:58 MyHost sshguard[6157]: Attack from "10.2.1.99" on service SSH with danger 10.
Mar 4 20:21:00 MyHost sshguard[6157]: Attack from "10.2.1.99" on service SSH with danger 2.
Mar 4 20:21:00 MyHost sshguard[6157]: Attack from "10.2.1.99" on service SSH with danger 10.
Mar 4 20:21:00 MyHost sshguard[6157]: Blocking "10.2.1.99/32" for 120 secs (4 attacks in 4 secs, after 1 abuses over 4 secs.)
ここでは可読性を上げるため行間に線を表示している。実際は存在しない。
7. おまけ
7-1. sshguard の動作ログを確認。
MyHost$ tail -f /var/log/messages | grep sshguard7-2. GNOME では firewall-config から永久ブロック対象を確認可能。
*210.2.1.99 を 120 秒間のブロック対象とする。(攻撃スコアがしきい値 THRESHOLD=30 に達した)
Mar 4 22:49:34 MyHost sshguard[1109]: Attack from "10.2.1.99" on service SSH with danger 10.
Mar 4 22:49:36 MyHost sshguard[1109]: Attack from "10.2.1.99" on service SSH with danger 10.
Mar 4 22:49:36 MyHost sshguard[1109]: Attack from "10.2.1.99" on service SSH with danger 2.
Mar 4 22:50:18 MyHost sshguard[1109]: Attack from "10.2.1.99" on service SSH with danger 10.
Mar 4 22:50:18 MyHost sshguard[1109]: Blocking "10.2.1.99/32" for 120 secs*2 (4 attacks in 44 secs, after 1 abuses over 44 secs.)
Mar 4 22:53:05 MyHost sshguard[1109]: 10.2.1.99: unblocking after 167 secs*3
Mar 4 22:53:10 MyHost sshguard[1109]: Attack from "10.2.1.99" on service SSH with danger 10.
Mar 4 22:53:13 MyHost sshguard[1109]: Attack from "10.2.1.99" on service SSH with danger 10.
Mar 4 22:53:15 MyHost sshguard[1109]: Attack from "10.2.1.99" on service SSH with danger 2.
Mar 4 22:53:56 MyHost sshguard[1109]: Attack from "10.2.1.99" on service SSH with danger 10.
Mar 4 22:53:56 MyHost sshguard[1109]: Blocking "10.2.1.99/32" for 240 secs*4 (4 attacks in 46 secs, after 2 abuses over 262 secs.*5)
Mar 4 22:57:58 MyHost sshguard[1109]: 10.2.1.99: unblocking after 242 secs
Mar 4 22:58:12 MyHost sshguard[1109]: Attack from "10.2.1.99" on service SSH with danger 10.
Mar 4 22:58:14 MyHost sshguard[1109]: Attack from "10.2.1.99" on service SSH with danger 10.
Mar 4 22:58:14 MyHost sshguard[1109]: Attack from "10.2.1.99" on service SSH with danger 2.
Mar 4 22:58:25 MyHost sshguard[1109]: Attack from "10.2.1.99" on service SSH with danger 10.
Mar 4 22:58:25 MyHost sshguard[1109]: Blocking "10.2.1.99/32" forever*6 (4 attacks in 13 secs, after 3 abuses over 531 secs.)
*310.2.1.99 をブロック対象から除外した。(除外までの時間はちょうど 120 秒ではなく、ランダムに秒数が加算される)
*410.2.1.99 を 240 秒間のブロック対象とする。(← 監視期間を延長した) *5(46 秒間に 4 回の攻撃動作、最初の認証失敗から 262 秒間に 2 回の不正接続)
*610.2.1.99 の攻撃スコアがしきい値 90 に達して、永久ブロック対象となった。
firewall-config をインストールする。
⇓
firewall-config を起動する。
⇓
firewall-config 画面
*7永久ブロックする IP アドレス (上図の「エントリー」) は SSHGuard が起動するたび firewalld の に登録されるため に登録されなくて良い。
⇔