OpenWrt 上安裝 fail2ban

OpenWrt 版本為 23.05.4,本來(lái)以為直接 opkg install fail2ban 安裝上再把之前的 sshd.conf 配置文件拷到 /etc/fail2ban/jail.d/ 下就行了,誰(shuí)知道并沒(méi)有那么簡(jiǎn)單,遇到不少問(wèn)題。

一切都是日志問(wèn)題

fail2ban 是通過(guò)分析 ssh 的登錄日志來(lái)封禁IP的,然而OP為節(jié)省空間通常并不把日志文件寫出來(lái),并沒(méi)有通常的 /var/log/auth.log 等類似的文件。由于日志文件無(wú)法讀取,fail2ban無(wú)法正常工作,其實(shí)是無(wú)法正常啟動(dòng)。fail2ban-client status 會(huì)提示錯(cuò)誤。雖然 /etc/init.d/fail2ban status 查看是在 running,但是 ps | grep fail2ban 根本沒(méi)有相應(yīng)進(jìn)程!

1. dropbear => sshd

雖然我裝了 openssh-server,但是OP默認(rèn)的 ssh 服務(wù)器并不是 sshd 而是 dropbear,可以通過(guò) netstat -nap |grep :22 查看。dropbear 是輕量級(jí)的 ssh 服務(wù)器,占用內(nèi)存小功能也相對(duì)少,行為上和 sshd 也并不完全一樣。一開(kāi)始我以為不寫日志是 /etc/ssh/sshd_config 中沒(méi)有打開(kāi)如下相應(yīng)設(shè)置

SyslogFacility AUTH
LogLevel INFO

但事實(shí)上該文件對(duì) dropbear 根本無(wú)效。于是關(guān)掉 dropbear 啟用 sshd:

/etc/init.d/dropbear stop
/etc/init.d/dropbear disable
/etc/init.d/sshd start
/etc/init.d/sshd enbale

不過(guò),剛進(jìn)行完上述設(shè)置后 LUCI 登錄總是密碼錯(cuò)誤,重新 ssh 登錄OP也進(jìn)不去,倒是之前沒(méi)退出得 ssh 會(huì)話依然可用。原來(lái)是因?yàn)?sshd_config中沒(méi)有啟用 root 登錄,加上如下設(shè)置并重啟 sshd 后解決

PermitRootLogin yes

然而,啟用 sshd 后登錄OP仍然沒(méi)有在 /var/log/ 中生成日志文件?。?/p>

2. logread

OP 默認(rèn)的日志都是在內(nèi)存中,要通過(guò) logread 命令讀取出來(lái),于是想到通過(guò) logread | grep sshd > /var/log/myauth.log 將日志保存在文件中,這樣再重啟 fail2ban 就能正常顯示 fail2ban-client status sshd 的結(jié)果了

root@OpenWrt:~# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     0
|  `- File list:        /var/log/myauth.log
`- Actions
   |- Currently banned: 0
   |- Total banned:     0
   `- Banned IP list:

其實(shí),也可以通過(guò) luci 圖形界面設(shè)置將日志寫到文件中,在 “系統(tǒng) / 系統(tǒng) / 系統(tǒng)屬性 / 日志 / 將系統(tǒng)日志寫入文件” 處設(shè)置并保存即可。不過(guò)這樣的日志是所有系統(tǒng)日志,不只是 sshd 的。

3. 日志解析無(wú)果

有了日志后 fail2ban 可以正常運(yùn)行了,為了測(cè)試,我有意錯(cuò)誤登錄多次,按規(guī)則應(yīng)該被禁掉,然而 fail2ban-client status sshd 的結(jié)果和上面的一樣都是 0,沒(méi)有分析出登錄失敗也沒(méi)有禁掉的 IP。fail2ban 是通過(guò)正則表達(dá)式匹配規(guī)則來(lái)分析日志的,sshd 的默認(rèn)定義在 /etc/fail2ban/filter.d/sshd.conf 中,不過(guò)內(nèi)容太多看不太明白。其實(shí)是可以通過(guò) fail2ban-regex 命令分析日志查看匹配情況的,格式如下。

fail2ban-regex  日志文件  '...正則表達(dá)式匹配規(guī)則...'

顯然,問(wèn)題就在于配置文件中的默認(rèn)規(guī)則并不能匹配出日志的條目,應(yīng)該是格式不符。日志格式如下

Thu Aug 22 22:37:21 2024 auth.info sshd-session[4772]: Failed password for root from 183.81.169.238 port 56310 ssh2
Thu Aug 22 22:47:27 2024 auth.info sshd-session[5176]: Invalid user testuser from 221.181.127.106 port 25516
Thu Aug 22 22:47:27 2024 auth.info sshd-session[5176]: Failed password for invalid user testuser from 221.181.127.106 port 25516 ssh2
Thu Aug 22 22:47:27 2024 auth.info sshd-session[5176]: Connection closed by invalid user testuser 221.181.127.106 port 25516 [preauth]
Thu Aug 22 22:47:29 2024 auth.info sshd[4639]: drop connection #0 from [221.181.127.106]:26456 on [192.168.0.10]:22 penalty: failed authentication
Thu Aug 22 22:47:29 2024 auth.err sshd-session[5180]: error: Could not get shadow information for NOUSER

通過(guò)猜測(cè)和嘗試,發(fā)現(xiàn)把 sshd 前面的 auth.info 或 auth.err 去掉后就行了!

其實(shí),logread 可以通過(guò) -e 參數(shù)添加過(guò)濾內(nèi)容,不需要用 grep 篩選,而且可以用 -f 參數(shù)保持一直運(yùn)行監(jiān)測(cè)最新日志,只要有一條就會(huì)輸出一條。于是,最終比較好的生成日志的方式是在 /etc/rc.local (該文件默認(rèn)沒(méi)有可執(zhí)行權(quán)限,我加了,不知道不加是否行)中添加如下命令用于開(kāi)機(jī)啟動(dòng)

logread -e sshd -f | sed 's/auth\.[^ ]* //' >> /var/log/myauth.log &

這樣只要有新的 sshd 相關(guān)日志就會(huì)及時(shí)的追加到日志文件中,且已經(jīng)把 auth.info 等內(nèi)容去除。

4. 防火墻

日志正常分析了,fail2band status sshd 也能列出失敗次數(shù)以及禁用的 IP 列表了。但是,如果沒(méi)有把這些 IP 成功添加進(jìn)防火墻的話依然是沒(méi)有真正禁用。比如我有意多次登錄失敗的那個(gè) IP 就在列表中,然而我仍然能登錄。通過(guò)如下搜索防火墻規(guī)則

nft list ruleset | grep 相應(yīng)IP

結(jié)果是什么都沒(méi)有。這說(shuō)明分析出要禁用的 IP 后并沒(méi)有成功添加進(jìn)防火墻!jail.d/sshd.conf 配置文件中我原來(lái)的 action 設(shè)置是

action = %(action_mwl)s

它應(yīng)該對(duì)應(yīng) action.d 下 mail-whois-lines.conf 文件所定義的動(dòng)作。由于我不清楚這個(gè)動(dòng)作是使用 nftables 還是 iptables 作為防火墻,以為它用了 iptables 而實(shí)際系統(tǒng)用的卻是 nftables。為此,問(wèn) chatgpt,說(shuō)可以如下明確指定防火墻動(dòng)作

action = nftables[name=SSH, port=ssh, protocol=tcp]

最終的 /etc/fail2ban/jail.d/sshd.conf 配置文件如下:

[sshd]
ignoreip = 127.0.0.1/8 192.168.0.1/24 192.168.4.1/24
bantime = 1h      # 后來(lái)干脆改成 30d 了
findtime = 300
maxretry = 5
enabled = true
filter = sshd
action = nftables[name=SSH, port=ssh, protocol=tcp]
logpath = /var/log/myauth.log

然而,這樣之后仍不能成功把待封禁 IP 填進(jìn)防火墻。記得之前用 /etc/init.d/firewall restart 重啟防火墻是會(huì)有提示

Section @include[0] option 'reload' is not supported by fw4

于是查看 /etc/config/firewall,最后部分果然有 reload

config include
        option path '/etc/firewall.fail2ban'
        option enabled '1'
        option reload '1'

我猜,一個(gè) config 段只要有問(wèn)題就無(wú)法被防火墻成功加載,這個(gè)不被支持的 reload 使得 fail2ban 相關(guān)的這部分設(shè)置并沒(méi)有生效。于是去掉 reload 這一行再重啟防火墻,待禁IP被成功加入防火墻,一切正常了!

5. 或許就用 dropbear 也行

我發(fā)現(xiàn) fail2ban 里有 /etc/fail2ban/filter.d/dropbear.conf 這個(gè)文件,這說(shuō)明不用把 dropbear 換成 sshd 或許也行,只不過(guò)需要從日志中提取 dropbear 相關(guān)條目,然后在 fail.d 中創(chuàng)建 dropbear.conf 而不是 sshd.conf 應(yīng)該就可以了。

6. 最后

發(fā)現(xiàn)日志中有好多如下的行并沒(méi)有被處理,既沒(méi)有識(shí)別其 IP 也沒(méi)有封禁。

Fri Aug 23 03:11:29 2024 sshd-session[3896]: Unable to negotiate with 170.64.167.224 port 41802: no matching host key type found. Their offer: ecdsa-sha2-nistp256, ......,ssh-rsa,ssh-dss [preauth]

原來(lái)是因?yàn)槟J(rèn)的 /etc/fail2ban/filer.d/sshd.conf 規(guī)則中使用的是 mode=normal 模式。試了改成 mode=extra 模式后是可以識(shí)別出失敗的 IP 的,但是不封禁;如果改成 mode=aggressive 的激進(jìn)模式則既可以識(shí)別也可以封禁 IP,就用它了! 可見(jiàn),sshd.conf 還是定義的比較全面的,反觀 dropbear.conf 就比較簡(jiǎn)單,內(nèi)容也不多。

另外,如果某個(gè) IP 被誤封,可以手動(dòng)解除封禁

fail2ban-client unban IP     # 也可以指定多個(gè) IP,以空格隔開(kāi)
fail2ban-client unban --all  # 手動(dòng)解除所有封禁
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容