0 更新记录
- 2024-11-28:初始版本
- 2024-11-30:修复因绑定WireGuard接口IP在系统重启时SSH启动失败的问题 3.2.1 修改监听地址和端口
上篇文章搭建一台PT下载主机的最后提到计划写一些提高安全性的内容,原本是打算鸽一阵的。毕竟这台机器位于校园网内,本身没有公网IPv4地址,校园网的IPv6也是关闭入站连接的,我一度认为还是比较安全的。
然而,今天偶然看了一下登录失败日志,发现居然有内网设备在暴力破解SSH。
看来校园网内也并不十分安全,还是需要做一些必要的措施增加一些防护能力。
实际上关于Linux主机安全性方面有一些非常全面的文章,这些文章从各种角度介绍了如何加强Linux系统安全性。如ArchLinux-Security和Securing Debian Manual等。其中ArchLinux-Security建议完全读一遍,篇幅不长,语言也可以切换到中文。而Securing Debian Manual则更为详细,但是篇幅较长,适合对具体章节针对性的深入阅读。
实际选择的安全策略总是安全与便利的平衡,本文主要从实际操作的角度来记录我对这台PT下载机的配置。
注意时效性!
文章更新于2024年11月,以下内容基于当时的知识和技术状况。
随着时间的推移,新的安全威胁和解决方案可能会出现,一些配置项可能会被移除(如SSH配置中Protocol
项在当前版本已经被移除)或者替换,注意文章内容的时效性!
1 概述
计划从我现在能想到的如下几个方面来提高下载机的安全性,当前主要是防御来自于网络的攻击,不涉及数据安全、备份、系统及软件更新已经硬件层面的安全防护(例如硬盘被偷)等方面的内容。
- 保护密码
- 保护SSH
- 只开启必要的服务
- 设置防火墙
- 封禁可疑IP
2 保护密码
2.1 使用强密码
下载机这一使用场景中,涉及到的密码主要有:
- Ubuntu root 用户密码;
- Ubuntu ubuntu 普通用户密码;
- Ubuntu 系统用户密码;
- qBittorrent WebUI 用户密码;
- Samba 用户密码。
root用户的密码在安装系统后设定,建议使用密码生成工具生成随机密码,尽可能同时包含大小写字母、数字和符号以提升密码强度。root密码设置好后很少使用,妥善保存即可,并不需要考虑是不是容易用大脑记住。
普通用户ubuntu的密码在登录SSH、使用sudo
运行命令等场景会频繁用到,建议在能记住的情况下尽量提高复杂性,即尽可能同时包含大小写字母、数字和符号,并且足够长(>=16位)。
其实Ubuntu用户名使用ubuntu
是一个反面案例,用户名也不应是容易猜到的字符串。
Ubuntu的系统用户在搭建一台PT下载主机-使用独立的用户运行部分简单介绍过,在新建系统用户(或者低权限的普通用户)时,要确保这个用户不能通过Shell和SSH登录。
qBittorrent WebUI和Samba的用户密码与Ubuntu普通用户的规则相同,用户名不容易被猜到,密码复杂。
2.2 妥善保管密码
密码应当被妥善保管,既要确保不会被别人获取,也要保证不会丢失。有时候不丢失密码可能会更重要,否则复杂的密码最终只能挡住你自己……
另外密码不要用明文写在命令中,在有选择的情况下,可以将密码保存在文件中,并妥善设置权限。如搭建一台PT下载主机-挂载其他主机的SMB共享中对登录远程NAS的Samba用户名和密码的使用。
3 保护SSH
下载机SSH版本:OpenSSH_8.9p1 Ubuntu-3ubuntu0.10, OpenSSL 3.0.2 15 Mar 2022
3.1 使用密钥连接SSH
SSH是连接下载机的主要方式,首先需要设置使用密钥连接SSH,不再使用密码。在本机(不是下载机)操作:
3.1.1 生成密钥(可选)
这是一个可选的步骤,如果本地之前生成过SSH密钥,并且想使用原来的密钥,可以跳过这个步骤。
生成新的密钥:ssh-keygen -t ed25519 -C "your@email.com"
,按提示生成即可。生成的默认路径 ~/.ssh
,公钥的默认文件名为id_ed25519.pub
,私钥的默认文件名为id_ed25519
。
3.1.2 上传公钥
注意上传的是公钥id_ed25519.pub
,一般以pub
为拓展名,别把私钥传上去了。两种方法任选:
- 使用命令上传:
1 | ssh-copy-id -i ~/.ssh/id_ed25519.pub ubuntu@192.168.50.219` |
验证用户ubuntu的密码后即可上传成功。
- 手动上传
首先打开公钥文件id_ed25519.pub
,复制其内容。
然后在Ubuntu下载机操作(使用SSH密码连接,方便复制粘贴):
将公钥内容粘贴到authorized_keys文件中,authorized_keys文件开始时是不存在的,需要自己创建:vim /home/ubuntu/.ssh/authorized_keys
。
保存后修改authorized_keys文件的权限为600,只允许用户ubuntu对该文件读写:sudo chmod 600 authorized_keys
。
3.1.3 重启sshd服务
公钥上传完成后,重启SSH服务:sudo systemctl restart sshd
,在本机退出SSH后重新登录,无需输入密码。
3.2 修改sshd配置文件
配置文件位于/etc/ssh/sshd_config
,sshd表示SSH Server的设置,而ssh_config
是SSH Client的设置。修改的内容有些设置项存在于配置文件中,但是没有使用(被注释),需要取消注释并将值设置为以下推荐的内容:
打开配置文件:
1 | sudo vim /etc/ssh/sshd_config |
3.2.1 修改监听地址和端口
2024-11-30更新:建议先看!修复因绑定WireGuard接口导致SSH启动失败的问题
SSH默认监听任意IPv4/IPv6地址的22端口,使用命令sudo ss -tnlp | grep sshd
或sudo netstat -ntlp | grep sshd
查看:
这里修改为只监听IPv4地址;只允许来自于局域网(192.168.50.0/24)和WireGuard局域网(192.168.70.0/24)的设备连接,修改监听地址为下载机自身在有线网卡和WireGuard接口wg0上的IP;使用一个不常用的端口降低被扫描到的可能。
这里有必要再放一下下载机所处的网络结构图:
修改配置文件/etc/ssh/sshd_config
:
1 | # 修改端口 |
修改保存后重启SSH服务sudo systemctl restart sshd
,再次查看监听情况sudo ss -tnlp | grep sshd
:
如果重启后连接断开,需要使用新端口连接SSH,在ssh命令中指定端口:
1 | ssh -p 53156 ubuntu@192.168.50.219 |
推荐本机SSH的config文件中设置主机别名和端口,操作更便捷一些,参考同时使用不同的GitHub账号管理仓库-修改ssh配置文件
3.2.2 登录设置
不允许root用户通过SSH登录:
1 | PermitRootLogin no |
不允许使用密码登录,不允许空密码:
设置不允许密码登录前确保已经正确配置密钥登录!
1 | PasswordAuthentication no |
设置超时自动断开连接:
1 | ClientAliveInterval 300 |
参数ClientAliveInterval
指定服务器向客户端发送“存活”消息的时间间隔(以秒为单位),设置为300,表示服务器每5分钟向客户端发送一个存活消息。
参数ClientAliveCountMax
指定在断开连接之前服务器可以发送多少个连续的、未被响应的“存活”消息,设置为0,表示服务器将不会多次发送存活消息,只要有未响应的消息就会立即导致客户端连接被关闭。
设置用户白名单:
1 | AllowUsers ubuntu |
4 只开启必要的服务
这里按需关闭,下载机只用于下载,可以关闭其他不相关的服务。使用命令sudo netstat -ntulp
查看使用的端口和占用端口的进程(想看到进程名需要使用sudo
)。
4.1 关闭cups
Ubuntu Desktop默认有打印机共享服务cups,关闭这个服务并禁止自动启动:
1 | sudo systemctl stop cups |
4.2 关闭avahi
avahi-daemon提供基于mDNS(Multicast DNS)和DNS-SD(DNS Service Discovery)的零配置网络服务。这个服务使设备能在本地网络中自动发现其他设备和它们提供的服务。不需要自动服务发现可以关闭:
1 | sudo systemctl stop avahi-daemon |
4.3 关闭nmbd
nmbd是Samba套件中的一个守护进程,主要用于提供基于NetBIOS名称服务的网络功能。在Windows中,NetBIOS名称服务允许主机通过网络名称(如计算机名,代替了IP)相互通信。我一直都是使用IP访问SMB,不需要主机名,关闭nmbd服务:
1 | sudo systemctl stop nmbd |
4.4 关闭Samba在IPv6上的监听
我不使用IPv6传输文件,这里关闭Samba在IPv6上的监听:
Samba使用参数bind interfaces only
和参数interfaces
来控制Samba服务器的网络行为:
bind interfaces only
参数用于限制Samba服务是否在“指定的接口或地址”上监听,可选值为yes
和no
,默认值为no
表示监听所有可用的接口和地址;interfaces
参数用来指定接口或地址,可以指定接口名称、IP地址或者二者同时存在,例如interfaces = eth0 192.168.2.10/24 192.168.3.10/255.255.255.0
。
下载机只会在局域网(192.168.50.0/24)中与NAS和其他主机互传文件,所以这里只设置(192.168.50.0/24),此外使用smbpasswd
命令修改密码时需要监听localhost/127.0.0.1
,127.0.0.1
也应当添加到接口列表。这里不能监听lo
接口,因为lo
接口包括IPv6的回环地址::1
。
1 | # 添加到 /etc/samba/smb.conf [global] 部分 |
保存后重启smbd服务,查看设置结果:
不要试图在interfaces
参数里添加WireGuard接口,或者WireGuard接口的IP,不会生效!
而且由于设置了bind interfaces only = yes
,原本可以通过WireGuard连通的SMB也会无法访问。
For file service it causes smbd(8) to bind only to the interface list given in the interfaces parameter. This restricts the networks that smbd will serve, to packets coming in on those interfaces. Note that you should not use this parameter for machines that are serving PPP or other intermittent or non-broadcast network interfaces as it will not cope with non-permanent interfaces.
WireGuard接口是不支持广播的,图中wg0和wg6都是WireGuard接口:
参考:
- Samba is not listening on specified wireguard / vpn interface,但是选定的答案也是错误的,参考其他回复。
- Samba over Tailscale/Wireguard
这种情况只能使用allow hosts
来限定哪些IP可以访问SMB服务,不能使用interfaces
参数。
5 设置防火墙
5.1 Linux防火墙的简单认识
Linux防火墙一般由两部分组成,一部分是作为内核模块的Netfilter数据包过滤框架,负责数据包的捕获和处理。另一部分是运行在用户空间配置该框架的用户程序。传统的用户空间工具是iptables,用户使用iptables配置Netfilter规则。xtables是iptables在内核中的实现,是Netfilter框架的组成部分。
nftables是Netfilter框架的新一代的子系统,旨在替代xtables(及用户空间工具iptables、ip6tables等),它简化了规则管理,并提供更丰富的功能和更好的性能。
现阶段的Linux内核同时支持两种系统,从Ubuntu 22.04 LTS开始,防火墙后端默认使用nftables,传统的iptables用户空间管理工具仍然能使用,不过默认情况下使用nftables后端实现,同时还提供了新的nft用户空间工具,能够创建传统iptables不支持的更灵活的规则。
Ubuntu默认使用ufw-Uncomplicated Firewall作为防火墙程序,ufw是iptables的一个上层抽象和简化工具,便于普通用户使用,而在复杂网络环境或需要更高自定义水平时,直接使用iptables仍是必要的。
我这里选用iptables作为防火墙配置工具。其实对于一台普通的主机(例如这台下载机),只需要开放特定的端口,阻止非必要的入站连接(有时也称为传入连接)等非常基础的防火墙功能,ufw已经足够。选用iptables主要是我比较熟悉这个工具,而且可以配合使用Fail2Ban,该工具对iptables支持比较完善(ufw倒是也能用)。
为什么不用新的nft(nftables)?因为不会,另外iptables还不大可能在短时间彻底被nftables替换掉。
5.2 检查iptables是否可用
首先关闭ufw,使用命令sudo ufw status
查看ufw状态,默认是关闭状态inactive
。如果ufw已经启用,使用命令sudo ufw disable
禁用。
然后检查iptables版本sudo iptables -V
,我这里输出iptables v1.8.7 (nf_tables)
,这就是使用nftables作为后端的iptables工具。如果没有iptables命令,可能是没有使用sudo,或者需要用apt安装一下。
在一些情况下,可能会出现命令不兼容的或者命令不生效的问题,此时可以考虑回退到之前的iptables(iptables-legacy)
参考:
不过目前我仍然使用iptables-nft,没有出现问题。
5.3 针对一般主机的iptables配置
这部分主要参考了Simple stateful firewall,根据我的需要略作修改,非常建议去阅读原文。
注意iptables规则是立即生效的,如果使用SSH连接远程主机配置,一定小心别把自己挡在防火墙之外。
此外,以下操作没有考虑安装Docker的情况,Docker也使用iptables管理容器网络,如果直接清除规则可能会影响容器工作。TODO
iptables会按照顺序处理规则,一旦数据包匹配到某条规则,则不会在向后检查规则。应当将最常匹配到的规则放在前面,减少匹配规则的开销。另外由于这个特性,一些限定较为精准的规则应当放在限定比较宽泛的规则之前,允许访问的规则应当放在拒绝访问的规则之前。
举例:
规则一:允许来自IP为192.168.50.100的主机使用TCP协议访问本机12345端口,iptables规则为:
1 | iptables -A INPUT -p tcp -s 192.168.50.100 --dport 12345 -j ACCEPT |
规则二:拒绝IP地址段为192.168.50.0/24的其他主机的任何访问,iptables规则为:
1 | iptables -A INPUT -s 192.168.50.0/24 -j DROP |
规则一应当写在规则二之前,如果将规则二写在前面,来自192.168.50.100,目标端口为12345的TCP数据包,会因为先匹配规则二被丢弃。
针对一般主机的防火墙设置时,主要操作iptables的filter表,不使用参数-t <table>
指定表时,默认操作的就是filter表。
5.3.1 设置IPv4防火墙
- 恢复所有链的默认策略为ACCEPT,清除所有规则,将防火墙恢复为初始状态:
1 | # 先设置默认策略 |
清空后的iptables规则如图,iptables-save
的输出也可能为空,也是正常的。
- 添加自定义链,分别管理新到达的UDP数据包和TCP数据包:
1 | sudo iptables -N MY_TCP |
- 设置FORWARD链默认规则:
本机不用做NAT网关,不会有经本机转发到其他主机的数据,所以转发直接丢弃。同时检查内核是否开启了转发,默认是关闭的,如果开启了也要关闭。
1 | # FORWARD链默认丢弃 |
临时关闭内核转发(重启后恢复,临时关闭仅作命令参考,实际需要永久关闭):
1 | # 直接修改文件 |
永久关闭内核转发(如果默认已经关闭则无需操作):
1 | # 编辑配置文件 |
- 设置OUTPUT链默认规则:
OUTPUT链管理本机主动发出的数据(出站),一般来说不需要做什么限制,所以保持为全部ACCEPT即可。
- 设置INPUT链规则:
INPUT链管理所有外部主机发送到主机的数据(入站),在目的为本机的数据包到达接口后首先经过INPUT链过滤。对于入站数据我们只想接收允许的数据包,拒绝或者丢弃其他的数据,所以默认策略应当为DROP。
但是考虑到使用SSH连接主机,如果先配置默认策略DROP,SSH连接会被立即断开,INPUT规则先设置允许规则,在设置完自定义链规则后再设置INPUT默认规则。
1 | # 允许状态为RELATED或ESTABLISHED的数据包发送到本机 |
- 设置自定义链MY_TCP,MY_UDP的规则:
使用命令sudo netstat -ntulp
查看有哪些端口正在使用。注意之前在修改监听地址和端口,将SSH的默认端口号由22修改为53156。qBittorrent的WebUI的默认端口为8080,我这里修改为8789。
最终确定需要开放入站连接的端口和协议类型:
TCP协议需要允许:SSH连接(53156)、qBittorrent的WebUI(8789)、SMB连接(445,139)。
UDP协议无需开放任何端口入站。
1 | # 允许SSH连接 |
最后设置INPUT链默认规则为DROP,将所有未匹配到的数据包丢弃:
1 | sudo iptables -P INPUT DROP |
至此,IPv4防火墙配置完成。
使用命令sudo iptables-save -f iptables.rules
可以将当前的规则保存在文件iptables.rules
中,按上述设置过程得到的文件内容为:
1 | # Generated by iptables-save v1.8.7 on Thu Nov 28 00:06:39 2024 |
Notes:
这里记录一些我在配置规则过程中的一些问题与理解。
参数–ctstate指定的状态是什么?UDP是无连接协议,为什么会有状态?
参考:iptables tutorial-数据包在用户空间的状态、States for –ctstate、iptables扩展模块之state扩展
简单来说,iptables的状态机制是通过连接跟踪(Connection Tracking)实现,conntrack是Linux内核中负责监控活跃的网络连接的模块。conntrack依据源IP、目标IP、源端口、目标端口等信息确定一个逻辑上的“连接”,不论这个“连接”自身是否维护状态信息,如TCP协议自身维护状态信息,需要三次握手建立连接;而UDP和ICMP协议都是无状态的,自身没有状态信息,也不建立连接。对于这些协议,conntrack都会维护逻辑上的“连接”的状态。
连接状态有五种:NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED:
- NEW:conntrack模块看到的某个连接第一个包,对于TCP,一般是第一次握手的SYN数据包;对于UDP,如果这个包不属于任何已有的连接就会标记为NEW;
- ESTABLISHED:某个连接中在NEW之后的包都是ESTABLISHED状态,即是要发送的NEW接收了应答就会变为ESTABLISHED状态,可以认为这个状态代表连接已建立;
- RELATED:是一个新的连接,但是与一个状态为ESTABLISHED的连接有关;(不是很理解,常举的例子是FTP-data连接和FTP-control连接);
- INVALID:conntrack没有识别数据包的状态和所属连接,一般的处理方式是直接丢弃;
- UNTRACKED:UNTRACKED状态是由nftables引入的,用于标识那些不经过连接跟踪的包。
在设置收到ICMP、UDP、TCP连接的规则时,都加了参数--ctstate NEW
,即只有连接的第一个数据包会匹配到这一条规则,而接下来的数据包会直接匹配第一条--ctstate RELATED,ESTABLISHED
规则。
为什么要使用–reject-with设置拒绝原因?
在Simple stateful firewall中有过说明,设置不同的拒绝原因模仿了Linux的默认行为,同时明确告知对方通信被禁止而不是等待超时(DROP),有助于调试时清楚的知道连接请求失败的原因。
当然也可以全部改为DROP,不明确拒绝,不回应直到请求发送方超时,隐藏本机开放的端口信息。
为什么没有开放WireGuard端口(WireGuard使用UDP)?
WireGuard的确会监听接口配置文件中[Interface]
部分中指定的端口,但是对于一个没有公网IP的WireGuard节点来说,其他节点是无法直接连接这个节点的,[Interface]
部分中的端口甚至可以不设置,接口启动时会监听一个随机端口,用于和中转服务器通信。
本机的WireGuard接口作为“客户端”,需要主动向暴露固定监听端口的服务端发送心跳包维持WireGuard隧道连接,所有的连接的NEW状态数据包都是本机主动发出,属于出站数据,不受到限制(OUTPUT ACCEPT)。服务器回应的数据包会被视为ESTABLISHED状态数据包直接被接收。
类似的,一般主机发出DNS请求(UDP:53,备用TCP:53)时是DNS客户端,也完全不需要单独设置DNS请求的响应返回本机时的入站规则,对本机请求的回应入站时的状态是ESTABLISHED,不会被阻止。(如果本机作为DNS服务器,才需要设置目标端口53的入站规则)。
5.3.2 设置IPv6防火墙
和IPv4的配置内容基本相同,不过用户空间程序使用ip6tables,和ICMP协议有关的内容更新为ICMPv6对应的内容。
此外,在自定义链中开放了qBittorrent-nox监听的端口51934的TCP和UDP入站连接,这样其他PT用户才能连接到这台机器:
1 | sudo ip6tables -A MY_TCP -p tcp --dport 51934 -j ACCEPT |
类似的,使用使用命令sudo ip6tables-save -f ip6tables.rules
可以将当前的规则保存在文件ip6tables.rules
中,得到的文件内容为:
1 | # Generated by ip6tables-save v1.8.7 on Thu Nov 28 01:14:59 2024 |
Notes:
这里对相比于IPv4规则明显不同的部分做一些说明。
新增了两条规则:
1 | -A INPUT -s fe80::/10 -p ipv6-icmp -j ACCEPT |
这条规则接受从链路本地地址fe80::/10到达的ICMPv6数据包,邻居发现协议NDP(类似于IPv4的ARP)依赖于ICMPv6信息。
1 | -A INPUT -p udp -m udp --sport 547 --dport 546 -j ACCEPT |
这条规则接受从DHCPv6服务器(使用547端口)发往DHCPv6客户端(使用546端口)的数据包。如果要使用DHCPv6则需要允许数据包入站。
5.3.3 规则持久化保存
使用iptables、ip6tables命令设置的防火墙规则都是临时规则,重启后会被删除,想要持久化保存规则,最简便的办法是用netfilter-persistent服务。
安装:
1 | sudo apt update |
安装过程中会提示是否保存当前的防火墙规则,选择是,保存的规则文件位于/etc/iptables/rules.v4
和/etc/iptables/rules.v6
。文件的内容和之前使用iptables-save
命令保存的文件一致。
以后再修改防火墙规则,可以使用命令手动保存:
1 | sudo netfilter-persistent save |
6 封禁可疑IP
Fail2Ban是一款开源的入侵防护软件,用于保护服务器免受暴力破解等潜在的恶意攻击。它通过监控日志文件以检测出多次失败的登录尝试,并自动添加防火墙规则(如iptables)来暂时或永久禁止来自恶意IP地址的连接。
这里使用Fail2Ban监测SSH登录、qBittorrent的WebUI登录和Samba登录的失败尝试。
6.1 安装Fail2Ban
直接使用apt包管理器安装:
1 | sudo apt update |
6.2 默认设置
Fail2Ban的基本原理是实时监控由logpath
指定的日志文件,使用filter
中的规则匹配日志,如果在findtime
时段内,匹配次数达到了maxretry
,就会执行banaction
动作封禁IP,封禁时间由bantime
定义。其他参数的含义可以参考默认配置文件jail.conf的注释。
Fail2Ban提供了一些默认的日志匹配规则(位于/etc/fail2ban/filter.d
),一些默认封禁动作(位于/etc/fail2ban/action.d
)。
参考项目WiKi-Proper fail2ban configuration,在/etc/fail2ban/jail.d/
路径下创建自定义配置文件my.local
。这个目录中可能会有自动生成的配置文件,比如我这里有一个defaults-debian.conf
,直接删除即可。
Fail2Ban的配置项遵循一定的覆盖规则,总是自定义配置(*.local
)覆盖默认配置(jail.conf
),针对具体服务的设置(称为一个jail,监狱)覆盖[DEFAULT]
中的设置。先创建一个[DEFAULT]
部分,这部分设置是SSH、qBittorrent的WebUI和Samba三个配置块的“全局”配置。
使用较为严格的封禁策略,5分钟内有3次失败尝试直接封禁72小时。一旦某个IP被视为恶意的IP,那么该IP也不应该连接其他端口了,直接使用iptables-allports封禁所有端口。当然这是比较激进的封禁策略,也可以使用iptables-multiport仅封禁对应服务的端口(如果不是默认端口要用port
参数指定)。
自定义配置文件my.local
内容:
1 | [DEFAULT] |
6.3 保护SSH登录
其实SSH在修改为不常用的端口和禁止密码登录后已经变得相当安全,不过万一端口被扫到,还是会在系统日志(/var/log/auth.log
)中留下一些垃圾记录。SSH的配置十分简单,直接使用Fail2Ban提供的过滤规则即可:
在自定义配置文件my.local
中追加sshd的jail规则:
1 | [sshd] |
- port:SSH服务使用的端口,之前自定义为53156,如果是默认则填
ssh
或22; - filter:填
sshd
表示使用/etc/fail2ban/filter.d/sshd.conf
作为匹配规则文件,但不要加.conf扩展名。
6.4 保护qBittorrent-WebUI登录
Fail2Ban默认的过滤规则中,并没有直接适用于qBittorrent-WebUI登录失败的日志,不过我在issues#3738中找到了可以匹配的规则。
首先在/etc/fail2ban/filter.d
目录中新建一个规则文件qbittorrent.conf
,内容如下:
1 | [Definition] |
这个正则表达式能够匹配这种格式的WebUI登录错误日志:
1 | (W) 2024-11-28T01:35:23 - WebAPI login failure. Reason: invalid credentials, attempt count: 1, IP: 192.168.50.100, username: test |
在自定义配置文件my.local
中追加qBittorrent-WebUI登录的jail,filter
参数使用我们自己创建的规则文件,qBittorrent日志目录默认在运行qBittorrent的用户的home目录中:
1 | [qbittorrent] |
默认的WebUI的语言设置和区域属性(General\Locale)相关联,界面设置为中文,那么输出的日志也是中文,上述规则无法匹配。我目前使用第三方WebUI VueTorrent,这个WebUI中的界面语言可以单独设置,不影响Locale属性。这样原版UI中将语言选择为英语,日志用英语输出,在第三方UI中设置中文。修改语言后需要重启qBittorrent才能修改日志的语言。
另外的解决方法就是写一个支持中文的正则表达式去匹配中文日志,
1 | (W) 2024-11-28T01:49:53 - WebAPI 登录失败。原因:凭证无效,尝试次数:2,IP:192.168.50.100,用户名:test |
使用以下命令测试规则:
1 | sudo fail2ban-regex -l heavydebug ~/.local/share/qBittorrent/logs/qbittorrent.log /etc/fail2ban/filter.d/qbittorrent.conf |
最后,qBittorrent其实也有一个简单的封禁多次登录失败的IP的功能,也勉强够用:
6.5 保护Samba登录
同样Fail2Ban默认的过滤规则中,也没有针对Samba日志进行过滤匹配的规则,仍然需要自己创建规则。之前的Samba配置中对日志部分保持了默认,Samba默认的日志级别为0,只输出严重错误和启动停止信息。我们需要修改Samba设置输出用户认证的信息。
Samba用于输出用户身份验证信息的模块有auth、auth_audit和auth_json_audit,分别设置了一下发现日志输出格式不同。auth输出详细的验证过程日志,auth_audit输出的日志是“human_readable”日志,auth_json_audit使用JSON格式输出类似auth_audit的内容。
最容易匹配的是auth_json_audit输出的JSON格式日志,这里设置常规日志的输出等级为1,auth_json_audit输出等级为3(3:身份认证成功和失败都输出,2:只输出失败日志),auth_json_audit的日志单独输出到/var/log/samba/auth_json_audit.log
。
在Samba配置文件/etc/samba/smb.conf
的[global]
部分添加:
1 | log level = 1 auth_json_audit:3@/var/log/samba/auth_json_audit.log |
然后在/etc/fail2ban/filter.d
目录中新建一个匹配规则文件samba.conf
,内容如下:
1 | [Definition] |
过滤规则参考了Configuring Fail2ban for Samba-AD,匹配用户名不存在和密码错误两种情况。
最后在自定义配置文件my.local
中追加smbd的jail规则,Samba在验证身份时会建立两次连接,如果使用全局的maxretry=3
很容易造成因为输错密码被封IP,这里覆盖[DEFAULT]
设置,放宽对失败次数的限制:
1 | [smbd] |
还可以给一个(或几个)可靠的局域网网设备添加白名单(ignoreip参数),防止被意外封禁。
最终的my.local
文件:
1 | [DEFAULT] |
使用命令启动Fail2Ban,并设置为自启动:
1 | sudo systemctl start fail2ban |
Fail2Ban的日志记录在/var/log/fail2ban.log
,如果启动失败可以查看日志。
查看所有jail的状态,或者查看某个jail的状态:
1 | sudo fail2ban-client status |
最后看一下测试效果,我使用一台局域网设备(192.168.50.106)在WebUI用错误的用户名和密码登录两次,均被Fail2Ban日志记录。然后用SSH使用错误密码登录三次,IP被封禁,此时刷新WebUI发现也已经无法访问,符合预期,因为封禁策略使用的是iptables-allports,直接封禁IP的所有端口,查看iptables记录可见Fail2Ban通过添加一条阻止入站的规则封禁IP。
如果发生了误封,可以手动解封,需要指定jail和IP:
1 | sudo fail2ban-client set <JAIL> unbanip <IP> |
总结
断断续续终于把这篇文章写完了,对于一台工作在局域网的下载机,这些防御手段实在是有些过剩。
参考
- ArchLinux-Security
- Securing Debian Manual
- manpages-sshd_config.5
- smb.conf — The configuration file for the Samba suite
- Samba is not listening on specified wireguard / vpn interface
- Samba over Tailscale/Wireguard
- Ubuntu-Firewalls
- Simple stateful firewall
- IptablesHowTo
- Iptables指南
- iptables备忘清单
- fail2ban-jail.conf
- fail2ban-issues#3738
- Configuring Fail2ban for Samba-AD