我没有特别的 SSH 安全配置技巧

1. 前情提要

今天又在盛传SSH被暴力破解了,其实大部分都是脚本小子24小时不停扫描公网暴露的SSH端口,只要你开着常见的SSH端口就会被扫描

我很早之前摸索的一套方法,应该算是对这种情况有所缓解,主要是高位端口+仅密钥登陆+22端口ssh蜜罐+fail2ban监听蜜罐和sshd全局封禁,可以预防绝大部分自动扫描了,以下是实践步骤

2. 实践步骤

2.1 设置 SSH 高位端口

在目录 /etc/ssh/sshd_config.d/下,新建任意名称配置文件,文件名后缀为.conf,写入如下内容即可,端口号建议填写 10000 - 65535 以内没有被占用的端口

Port 33445 

检查端口是否被占用:

lsof -i:33445

一键命令:

echo -e "Port 33445" | sudo tee /etc/ssh/sshd_config.d/00-custom_port.conf

设置完配置文件后,使用如下命令重启 SSH 服务

sudo systemctl restart ssh.service # Debian Ubuntu 等使用 systemd 的使用这个命令sudo rc-service sshd restart       # Alpine 等无法使用 systemd 的系统可以使用 openrc 管理 

⚠️警告⚠️:此时不要关闭当前终端窗口

如果有防火墙,请放行新的端口,并禁止旧的SSH端口访问

sudo ufw allow 33445 # 放行新的SSH端口sudo ufw deny 22     # 禁用原有SSH端口

修改完 ufw 规则后,使用命令启用防火墙

sudo ufw enable 

打开一个新的终端窗口,使用旧的端口和新的端口测试是否修改成功,再关闭当前的终端窗口,否则一旦你修改出错就只能去VNC里重新开启了

2.2 设置 SSH 仅密钥登陆

一键命令:

echo -e "PasswordAuthentication no\nPubkeyAuthentication yes" | sudo tee /etc/ssh/sshd_config.d/01-custom_auth.conf

与上面的重启SSH和检查端口方式相同,我就不再赘述

2.3 配置 Fail2ban 将 SSH 访问失败的 IP 封禁

安装 fail2ban 和 ufw 防火墙

sudo apt update && sudo apt upgrade && sudo apt install fail2ban ufw-y

其他系统安装方式可以参考 How to install fail2ban packages · fail2ban/fail2ban Wiki · GitHub

配置 fail2ban 的 jail.local

nano /etc/fail2ban/jail.local

写入以下配置,注意修改里面的 port为你的 SSH 端口

[DEFAULT]ignoreip = 127.0.0.1/8 ::1bantime = 86400findtime = 1800action = %(action_)sbanaction = ufw[sshd]enabled = trueport = 33445filter = sshdaction = ufwlogpath = /var/log/auth.logmaxretry = 3findtime = 604800sbantime = 604800susedns   = no

保存退出后,使用以下命令重启 fail2ban 服务,以应用配置

sudo systemctl restart fail2ban.service # Debian & Ubuntusudo rc-service fail2ban restart        # Alpine

ufw 防火墙注意放行你使用的端口,比如上面修改的 SSH端口、Nginx使用的80和443端口等,相关参数见

Usage: ufw COMMANDCommands: enable                          enables the firewall disable                         disables the firewall default ARG                     set default policy logging LEVEL                   set logging to LEVEL allow ARGS                      add allow rule deny ARGS                       add deny rule reject ARGS                     add reject rule limit ARGS                      add limit rule delete RULE|NUM                 delete RULE insert NUM RULE                 insert RULE at NUM prepend RULE                    prepend RULE route RULE                      add route RULE route delete RULE|NUM           delete route RULE route insert NUM RULE           insert route RULE at NUM reload                          reload firewall reset                           reset firewall status                          show firewall status status numbered                 show firewall status as numbered list of RULES status verbose                  show verbose firewall status show ARG                        show firewall report version                         display version informationApplication profile commands: app list                        list application profiles app info PROFILE                show information on PROFILE app update PROFILE              update PROFILE app default ARG                 set default application policy

修改完 ufw 规则后,使用命令启用防火墙

sudu ufw enable

查看 fail2ban 实时封禁日志(刚安装可能不会立刻有内容)

tail -f -n 50 /var/log/fail2ban.log

2.4 配置 SSH 蜜罐和 fail2ban 监听蜜罐实现全局封禁

⚠️警告⚠️

高级操作,请衡量你的Linux能力再研究,不确保适合每个系统

以上操作已经足够安全保护你的ssh不被轻松破解了

长期监听可能会影响系统性能,建议使用性能不太差的服务器

2.4.1 安装相关依赖
sudo apt update && sudo apt upgrade && sudo apt install ipset iptables -y 
2.4.2 安装简单 SSH 蜜罐fakessh

以下附上 docker-compose.yml

name: fakesshservices:    fakessh:        restart: always        ports:            - 22:22        container_name: fakessh        image: fffaraz/fakessh        logging:            driver: "json-file"            options:                max-size: "10m"                max-file: "3"

使用命令 docker compose up -d运行容器

然后运行以下命令查看 docker 容器直接保存的日志路径(之前尝试将容器日志使用外挂 volume 的方式导出失败了,有知道的大佬可以楼下补充)

docker inspect fakessh | grep LogPath

需要保存的日志路径形如:/var/lib/docker/containers/1586b2735886350e0e6cd285c76bf1737ea597a5c7c425550e086a453c73ae1b/1586b2735886350e0e6cd285c76bf1737ea597a5c7c425550e086a453c73ae1b-json.log

2.4.1 配置 fail2ban

新建/etc/fail2ban/filter.d/fakessh.conf文件,并写入以下内容

[Definition]failregex = ^{"log":".* .* <HOST>:\d+\\n","stream":"stderr","time":".*"}$ignoreregex =datepattern = {^LN-BEG} ExYear (?P<_sep>[/]) Month (?P=_sep) Day 24hour:Minute:Second (?:[.,] Microseconds)?

/etc/fail2ban/jail.local 底部添加 fakessh 规则如下,注意替换 logpath为你自己的容器日志路径

[fakessh]enabled  = truefilter   = fakesshaction   = iptables-ipset-proto6-allports[name=fakessh, bantime=1209600, chain=INPUT]logpath  = /var/lib/docker/containers/1586b2735886350e0e6cd285c76bf1737ea597a5c7c425550e086a453c73ae1b/1586b2735886350e0e6cd285c76bf1737ea597a5c7c425550e086a453c73ae1b-json.logmaxretry = 1bantime  = 1209600findtime = 604800usedns   = nobackend  = pollingignoreip = 127.0.0.1/8 ::1

在保证 fakessh 已经被写入外部扫描IP日志的情况下,使用下面命令测试规则是否生效

fail2ban-regex /var/lib/docker/containers/1586b2735886350e0e6cd285c76bf1737ea597a5c7c425550e086a453c73ae1b/1586b2735886350e0e6cd285c76bf1737ea597a5c7c425550e086a453c73ae1b-json.log /etc/fail2ban/filter.d/fakessh.conf

结果只要 Lines 里 matched 里有数量说明正常,因为只匹配 TCP 传入流量

# root @ LeasewebSG in ~ [12:18:19] C:130$ fail2ban-regex /var/lib/docker/containers/1586b2735886350e0e6cd285c76bf1737ea597a5c7c425550e086a453c73ae1b/1586b2735886350e0e6cd285c76bf1737ea597a5c7c425550e086a453c73ae1b-json.log /etc/fail2ban/filter.d/fakessh.confRunning tests=============Use   failregex filter file : fakessh, basedir: /etc/fail2banUse      datepattern : {^LN-BEG} ExYear (?P<_sep>[/]) Month (?P=_sep) Day 24hour:Minute:Second (?:[.,] Microseconds)? : {^LN-BEG} ExYear (?P<_sep>[/]) Month (?P=_sep) Day 24hour:Minute:Second (?:[.,] Microseconds)?Use         log file : /var/lib/docker/containers/1586b2735886350e0e6cd285c76bf1737ea597a5c7c425550e086a453c73ae1b/1586b2735886350e0e6cd285c76bf1737ea597a5c7c425550e086a453c73ae1b-json.logUse         encoding : UTF-8Results=======Failregex: 36987 total|-  #) [# of hits] regular expression|   1) [36987] ^{"log":".* .* <HOST>:\d+\\n","stream":"stderr","time":".*"}$`-Ignoreregex: 0 totalDate template hits:Lines: 73028 lines, 0 ignored, 36987 matched, 36041 missed[processed in 1.78 sec]Missed line(s): too many to print.  Use --print-all-missed to print all 36041 lines

重启 fail2ban 即可

如果你还需要让 docker 容器暴露的端口也服从上面的封禁规则,包括 fakessh 本体,可以运行添加下面的 iptables 规则

iptables -I DOCKER-USER 1 -m set --match-set f2b-fakessh src -j REJECT --reject-with icmp-port-unreachableip6tables -I DOCKER-USER 1 -m set --match-set f2b-fakessh src -j REJECT --reject-with icmp-port-unreachable

3. 效果展示