利用fwknop给sshd加一道门,向暴力黑客Say no-way!

相信不少Linux服务器的机主对各类暴力攻击是深恶痛绝的了,尤其是那些针对sshd的愚蠢黑客,成功率极低还给机主带来不少麻烦。
对付这些拿着毫无技术含量的脚本到处乱撞的低级黑客(在我眼中,称他们为黑客是擡举他们),比较常见的有fail2ban、denyhosts、以及knockd,前两者的原理是通过对日志文件的分析找出攻击者ip,然后设置防火墙屏蔽之,属于被动防御,对于受攻击频率不高的机器还有点用处;后者则反其道而行,先设置防火墙拒绝任何访问,合法访问者须通过“正确”的敲门动作打开门才可连接登录,属于主动防御。
主动防御的思路是不错的,但是knockd的敲门方式私密性不佳,黑客可侦听并简单模仿敲门动作而成功连接,安全性低。
下面介绍一款我认为安全性较高的主动防御工具:fwknop,她与knockd的最根本区别在于其采用经过加密处理的“单包认证”敲门方式,私密性好得多。
详细原理及配置就不细说了,有兴趣可以去他的官网慢慢看:
http://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html

本文将安装、配置的过程简单罗列出来,分享给有需要的朋友们,少走弯路节省时间。

一、操作系统、工具环境
1.客户端:Windows 7, Visual Studio 2008或以上版本;Linux。
2.服务器端:CentOS 6.8, gcc等常用开发工具;CentOS 7, firewalld防火墙。

二、安装、配置客户端
客户端是Linux的,根据系统的情况下载安装整个软件包,这样服务端和客户端就都有了,配置方法参考其官网的教程。
Windows需要下载fwknop源码自己编译客户端,下载地址:https://github.com/mrash/fwknop/releases
1)下载、解压fwknop-master.zip,进入其win32子目录;
2)如果你使用的是VS2008,把libfko.sln、libfko.vcproj、fwknop-client.vcproj删除或改名,把后缀名为.vs2008的三个文件改为刚刚被删除的那三个文件名;否则用纯文本编辑器打开libfko.vcproj和fwknop-client.vcproj,找到"..\lib\fko_util.c"、"..\lib\fko_util.h"、"..\lib\strlcat.c"、"..\lib\strlcpy.c"这几处地方,把其中的lib改为common,保存。
3)双击打开libfko.sln,编译其中的Release-full-static或者Release-static版本,得到单一的可执行文件fwknop.exe;
4)新建一个空文件夹(譬如D:\fwk)并把此文件拷贝过来,打开一个命令行窗口,然后执行:
D:
cd \fwk
fwknop --version
看到版本信息表明编译成功了。
5)下载wget:http://www.interlog.com/~tcharron/wgetwin-1_5_3_1-binary.zip,解压其中的wget.exe,放在和fwknop.exe同一个文件夹里;
6)在此文件夹内,用纯文本编辑器新建一个文件:bwget.bat,内容只有一行:@wget --no-check-certificate %1 %2 %3 %4 %5 %6 %7 %8 2>nul,保存;
7)在刚才打开的命令行窗口内,执行命令:
fwknop -n cen6 -A tcp/22,tcp/4432 -a 192.168.0.137 -D 192.168.0.186 --use-hmac -p 62201 -P udp -k --save-rc-stanza
下面逐项作解释:
-n cen6 给后面的参数起一个名字,方便以后调用;
-A tcp/22,tcp/4432 请求服务端打开的端口及其协议;
-a 192.168.0.137 客户端的IP地址;
-D 192.168.0.186 服务端的IP地址;
--use-hmac 采用hmac加密认证方式;
-p 62201 服务端等待请求的侦听端口;
-P udp 服务端等待请求的协议;
-k 生成一个加密密钥;
--save-rc-stanza 保存以上参数的执行结果。
现在,用文本编辑器去打开用户工作路径里的.fwknoprc文件(在我的机器上是C:\Users\suntongo\),其内容如下:
[default]
[cen6]
SPA_SERVER_PROTO            udp
SPA_SERVER_PORT             62201
ALLOW_IP                    192.168.0.137
ACCESS                      tcp/22,tcp/4432
SPA_SERVER                  192.168.0.186
KEY_BASE64                  0hLAT/i8uBuvwU+GiAZQ/X0MkiCq4waCyMWiF8ROkaQ=
HMAC_KEY_BASE64             0hLAT/i8uBuvwU+GiAZQ/X0MkiCq4waCyMWiF8ROkaQyUvkHV7FYJRe2vdkNTl+8gD7Y/picCtdspuKrX0qo5Q==
USE_HMAC                    Y
上面打那么长的命令行,就是为了生成这么一堆内容,对比一下命令行里的参数,大致都明白其中每行的含义了,其中KEY_BASE64和HMAC_KEY_BASE64就是-k参数自动生成的。
读者可能会注意到ALLOW_IP设置了固定值,如果客户端的IP经常变化那怎么办呢?很简单,这配置文件内的每一行都可以被命令行参数覆盖的,后面会有范例。
另外,如果服务端在外网且有域名,客户端是在ADSL宽带拨号的情况下又怎么办呢?
且看这个命令行:
fwknop -n cen7 -A tcp/22,tcp/4432 -R -w bwget.bat -D my.server.com --use-hmac -p 62201 -P udp -k --save-rc-stanza
让我们来看看结果:
[cen7]
SPA_SERVER_PROTO            udp
SPA_SERVER_PORT             62201
ACCESS                      tcp/22,tcp/4432
SPA_SERVER                  my.server.com
KEY_BASE64                  PZVdrTcVnMNvrfdm6gDYQ64pJEP1sjQoyPGP/mNNdIc=
HMAC_KEY_BASE64             PZVdrTcVnMNvrfdm6gDYQ64pJEP1sjQoyPGP/mNNdIdNDiPoE0MLwGxjON7OHaxHNxAL0ydfrPGhUo9wI/e8Wg==
USE_HMAC                    Y
RESOLVE_IP_HTTPS            Y
WGET_CMD                    bwget.bat
在这小节中,SPA_SERVER不再是IP而是域名了,ALLOW_IP不见了,fwknop执行时会调用bwget.bat现场取得你的机器的公网IP用来代替ALLOW_IP,是不是很灵活方便?
OK,客户端的配置基本完成了,cen6小节的配置适合于客户端和服务端在同一局域网内的情况,cen7则适合服务端在公网、客户端为无固定IP的情况,下面开始分别展开对CentOS6及CentOS7服务端的配置工作了。

三、安装、配置服务端(CentOS 6)
fwknopd是需要调用iptables的,CentOS 6官方的iptables版本过低,与fwknopd不适合,虽然fwknopd有一个--no-ipt-check-support的选项可回避这个问题,但我还是建议你自己编译一个较高版本的iptables。
下载iptables源码包:wget http://www.netfilter.org/projects/iptables/files/iptables-1.4.11.1.tar.bz2
解压:tar xf iptables-1.4.11.1.tar.bz2,然后cd进入子路径里;
编译:无非就是 ./config; make; make install。
1)安装fwknop:yum install fwknop
2)编辑配置文件

vi /etc/fwknop/access.conf

#客户端IP,建议设置为ANY,除非客户端的IP是固定的。
SOURCE                 ANY
#服务器网卡的IP,建议设置为ANY,如果有多个网卡,则设置为你需要“开门”的那个网卡的IP。
DESTINATION            ANY
#“敲门”成功后须打开的协议及端口。
OPEN_PORTS             tcp/22,tcp/4432
#根据实验,这个必须设为N,否则死活都敲不开这道门。
REQUIRE_SOURCE_ADDRESS N
#复制自客户端生成的数据(必须保持与客户端相同)。
KEY_BASE64             0hLAT/i8uBuvwU+GiAZQ/X0MkiCq4waCyMWiF8ROkaQ=
HMAC_KEY_BASE64        0hLAT/i8uBuvwU+GiAZQ/X0MkiCq4waCyMWiF8ROkaQyUvkHV7FYJRe2vdkNTl+8gD7Y/picCtdspuKrX0qo5Q==

vi /etc/fwknop/fwknopd.conf

#网卡的名称,可用ifconfig查看得到。
PCAP_INTF               eth0;
#“门板”的侦听协议及端口,推荐用udp。
PCAP_FILTER             udp port 62201;
UDPSERV_PORT            62201;
ENABLE_UDP_SERVER       Y;

#“门板”的侦听协议及端口,在不宜使用udp的场合(如通过“巨型防火墙”访问外网),也只好这样啦。
#PCAP_FILTER             tcp port 62201;
#TCPSERV_PORT            62201;
#ENABLE_TCP_SERVER       Y;
#ENABLE_UDP_SERVER       N;

#“敲门砖”有效期限制,不建议选N。
ENABLE_SPA_PACKET_AGING Y;
#“敲门砖”有效期(秒)
MAX_SPA_PACKET_AGE      60;
#两次“敲门”之间的“不答应”时间。
PCAP_LOOP_SLEEP         100000;
#“敲门砖”的最大尺寸。
MAX_SNIFF_BYTES         1500;
#为了安全,不建议设为Y。
ENABLE_SPA_OVER_HTTP    N;
#以下两项决定了“敲门”成功后fwknopd对防火墙的操作行为,具体就不解释了。
ENABLE_DESTINATION_RULE N;
IPT_INPUT_ACCESS        ACCEPT, filter, INPUT, 1, FWKNOP_INPUT, 1;
#如果使用的防火墙不是系统原配的iptables,那你就需要指明其路径。
FIREWALL_EXE            /usr/local/sbin/iptables;

3)检查防火墙的设置,确保fwknopd侦听的端口及协议是畅通的,如有必要,增加一条规则:
iptables -I INPUT -p udp -m udp --dport 62201 -j ACCEPT
4)先让服务端进入测试状态:
[root@s51 ~]# fwknopd -f -t -v
[+] Writing my PID (20359) to the lock file: /var/fwknop/fwknopd.pid
Starting fwknopd
Using Digest Cache: '/var/fwknop/digest.cache' (entry count = 29)
Kicking off UDP server to listen on port 62201.

5)运行客户端进行“敲门”测试:
fwknop.exe -n cen6

服务端看到类似以下内容的信息(注意最后一行),则表示“敲门”已经成功:
udp_server: Got UDP datagram (225 bytes) from: 192.168.0.137
(stanza #1) SPA Packet from IP: 192.168.0.137 received with access source match
SPA Packet: ....(太长了,省略)
[192.168.0.137] (stanza #1) --test mode enabled, skipping firewall manipulation.

(思考实验题:制造一次能看到“敲门砖”内容但“敲门”失败的测试,查看其与成功“敲门”之差别。)
6)在服务端操作窗按Ctrl-C退出测试状态,可以启用fwknopd服务进入工作状态了:
service fwknopd start
7)防火墙设置
先查看一下现有的设置:
iptables-save

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-N FWKNOP_INPUT
-A INPUT -p udp -m udp --dport 62201 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p udp -m udp --dport 1194 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 4432 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -i tun+ -j ACCEPT
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
可以看到,fwknopd启用之后,防火墙多了一条规则链FWKNOP_INPUT,其内容是空的。
用客户端丢一个“敲门砖”过来,然后在服务器端用iptables-save查看一下(动作要快),会发现多了两条规则:
-A FWKNOP_INPUT -s 192.168.0.137/32 -p tcp -m tcp --dport 22 -m comment --comment _exp_1482021946 -j ACCEPT
-A FWKNOP_INPUT -s 192.168.0.137/32 -p tcp -m tcp --dport 4432 -m comment --comment _exp_1482021946 -j ACCEPT
说明“敲门”动作已经成功,防火墙按照预期打开了设定的协议以及端口。
由于fwknopd默认在打开门30秒之后会重新关上(这点可以通过用iptables-save反复查看来证实),敲门之后应尽快尝试进行连接。
那么,在开门期间建立的连接会不会因关门而中断?还有就是关门是否真的能阻止非法的访问?
答案是看你的防火墙配置是否符合要求!
要求(1):-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 这一条规则不可缺少,且其位置应相对靠前;
要求(2):有效的关门条件必须成立。就拿前面的配置来分析吧,由于存在 -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT 这一条,无论fwknopd开门还是关门,端口22的ssh连接都是畅通的(端口4432也是如此),所以应删除相关端口的放行规则。
对防火墙的配置也有流派之分,有人喜欢默认放行,然后逐条DROP规则实施必要的阻止;有人则喜欢默认阻止,然后逐条ACCEPT规则选择性地放行,fwknopd对这两种流派都能有效发挥作用,总的原则是该放行的就放行,该阻止的就阻止,配置防火墙时周密细致的安排是必不可少的。
顺便举个例子,如果客户端IP不是原来设置的值,可以用命令行参数-a覆盖而不必改动.fwknoprc的内容:
fwknop.exe -n cen6 -a 192.168.0.110
OK,关于CentOS 6的内容就到此为止,接下来讲CentOS 7吧。

四、安装、配置服务端(CentOS 7)
如果你不打算用CentOS 6作为服务器操作系统,也请先阅读一下前一章,有很多只说了一遍但还是挺重要的内容在后文省略了。
CentOS 7默认安装中舍弃了iptables服务,保留了iptables及其相关的工具,取而代之的是firewalld服务,有不少习惯了iptables的人总是想法子禁用firewalld服务和恢复iptables服务,如果你继续坚持这种“前朝遗老”式的心态,那么fwknopd真的不适合你!
0)先确认一下firewalld服务能正常启用:
which firewalld
如果没有,先安装:yum install firewalld
systemctl status firewalld.service
如果firewalld已经正常运行中,直接跳过,进行步骤1);
如果曾被禁用,还须启用之:
systemctl enable firewalld.service
并禁用与之冲突的服务:
systemctl disable --now iptables.service
systemctl disable --now ip6tables.service
systemctl disable --now ebtables.service
systemctl disable --now ipset.service
systemctl start firewalld.service
然后用firewall-cmd根据你的需要打开相关的服务端口。

1)安装fwknop:yum install fwknop
2)编辑配置文件
vi /etc/fwknop/access.conf
SOURCE                 ANY
DESTINATION            ANY
OPEN_PORTS             tcp/22,tcp/4432
REQUIRE_SOURCE_ADDRESS Y
KEY_BASE64             PZVdrTcVnMNvrfdm6gDYQ64pJEP1sjQoyPGP/mNNdIc=
HMAC_KEY_BASE64        PZVdrTcVnMNvrfdm6gDYQ64pJEP1sjQoyPGP/mNNdIdNDiPoE0MLwGxjON7OHaxHNxAL0ydfrPGhUo9wI/e8Wg==

vi /etc/fwknop/fwknopd.conf
PCAP_INTF                   enp3s0;
ENABLE_UDP_SERVER           Y;
UDPSERV_PORT                62201;
PCAP_FILTER                 udp port 62201;
ENABLE_SPA_PACKET_AGING     Y;
MAX_SPA_PACKET_AGE          60;
ENABLE_SPA_OVER_HTTP        N;
ENABLE_DESTINATION_RULE     N;
FLUSH_FIREWD_AT_INIT        Y;
FLUSH_FIREWD_AT_EXIT        Y;
ENABLE_FIREWD_FORWARDING    Y;
ENABLE_FIREWD_LOCAL_NAT     N;
ENABLE_FIREWD_OUTPUT        N;
FIREWD_INPUT_ACCESS         ACCEPT, filter, INPUT, 1, FWKNOP_INPUT, 1;
FIREWD_FORWARD_ACCESS       ACCEPT, filter, FORWARD, 1, FWKNOP_FORWARD, 1;
ENABLE_FIREWD_COMMENT_CHECK N;
FIREWALL_EXE                /usr/bin/firewall-cmd;

3)设置防火墙,确保fwknopd侦听的端口及协议是畅通的:
firewall-cmd --permanent --new-service=fwknop
firewall-cmd --permanent --service=fwknop --add-port=62201/udp
firewall-cmd --permanent --add-service=fwknop
firewall-cmd --zone=public --add-service=fwknop

4)仔细核对各项配置符合你的环境及需要,然后开始测试:
fwknopd -f -t -v
5)运行客户端进行“敲门”测试:
fwknop -n cen7
(测试细节见前文。)
6)在服务端操作窗按Ctrl-C退出测试状态,可以启用fwknopd服务进入工作状态了:
systemctl start fwknopd.service
7)防火墙设置
先查看一下现有的设置:
firewall-cmd --list-all

public (active)
  target: default
  icmp-block-inversion: no
  interfaces: enp3s0
  sources:
  services: dhcpv6-client fwknop http https ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  sourceports:
  icmp-blocks:
  rich rules:

用客户端丢一个“敲门砖”过来,再在客户端查看防火墙有什么新情况:
iptables -L
....
Chain FWKNOP_INPUT (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  113.168.160.52         anywhere             tcp dpt:ssh /* _exp_1482301574 */
ACCEPT     tcp  --  113.168.160.52         anywhere             tcp dpt:4432 /* _exp_1482301574 */
....
以此推知,“敲门”成功,防火墙也把相应的端口打开了,现在可以正式把ssh的门关上,抵御各路黑客们的暴力攻击了:
firewall-cmd --zone=public --remove-service=ssh

题外话:关于denyhosts
本人很早就使用denyhosts来进行防御了,因为她配置比较简单而且效果还是不错的,但是也有被动防御工具们共同的缺陷:反应滞后、对高密度攻击抵抗力差。
另外,denyhosts还曾经把机器主人也屏蔽了,究其原因是攻击者与机主共享公网IP,很多校园网、办公楼网以及某些无良的“宽带”奸商都是大批用户通过NAT或者其他方式共享公网IP上网的,如果恰好攻击者的公网IP与机主相同,那么机主也被denyhosts无情地拒绝了。
题外话1:关于ssh
1.改端口问题,很多讨论是通过改端口来躲避ssh攻击,这个方法确可以让大多数低级黑客无功而返,但是对修为稍微高一点的黑客是无效的。还有一个严重的问题是某巨型防火墙对非22端口的ssh连接一律判定为可疑动作而干扰、阻止,迫使你还得使用22端口。
2.禁止root用户登录,这是个好主意,大大降低了被入侵的机率。
3.弃用口令验证,采用密钥验证,这绝对是明智之举,配合方法2,堪称万全。
题外话2:关于fwknop
1.既然已有万全之策,何必再来个fwknop?先分析一下黑客的ssh暴力攻击行为,黑客测试目标主机的22端口,如可以连接,即保持此连接开始尝试破解,此时会占用机器的少量资源,也会在机器的日志文件中留下记录,如果多个黑客同时密集攻击,机器将面临沉重的负荷而性能下降、日志文件体积暴增,因此,关门谢客才是最佳选择,黑客连最初的连接动作都失败,自然就不会有后续的攻击尝试了,实测效果证明,以前denyhosts每天都新增几百个攻击者IP黑名单,多的时候甚至过千,自从安装了fwknopd,妈妈再也不用耽心我的服务器主机了。
2.fwknop真的就没有缺陷吗?当然不是,就拿上述共享公网IP的情况来说,一旦你“敲”开了门,使用相同公网IP的所有机器都可连接,不过因为开门的时间很短,危险系数还是很低的(除非哪位技术很高的黑客一直在盯着你),就让那些漫无目的到处乱扫的黑客们到别处凉快去吧。
3.本文介绍fwknop采用HMAC加密,有支持更安全的加密方式吗?有,去他的官网看看她关于配置gpg加密的范例。
4.除了防御ssh暴力破解,fwknop还能干些什么?防御ssh暴力破解是fwknop主要目的之一,就其“开门”机理来说,是可以灵活应用的,譬如服务器上安装了某个(或多个)端口的服务是给自己女朋友专用的,为安全起见平时也是要把这个端口关上的,那么你可以在她的电脑上专门配置一个客户端(Android、iphone也可以哦),然后在服务端增加一个配置小节,这样就可以你用你的端口她用她的端口,互不干扰。(悄悄问一句:你有几个npy?)
题外话3:关于fwknop客户端的-R参数
-R是让fwknop客户端通过公网服务器读取公网IP,默认情况下是由外部命令wget https://www.cipherdyne.org/cgi-bin/myip实现的,wget访问https是需要配置信任证书的,比较麻烦,可以加上--no-check-certificate选项来回避(前文提到的bwget.bat就是为解决这个问题的)。另外,默认的网址反应速度比较慢,如果自己有反应快且已配置https支持的web服务器,可以写几行代码实现之,本人正好有一个符合要求的web服务器,是由node.js+express编写的,改编是如此的简单:
进入web服务器程序所在路径后,vi app.js,在适当的地方加入两行:
....
var getip = require('./routes/getip');
....
app.use('/getip', getip);
....

然后新建一个文件:
vi routes/getip.js

var express = require('express');
var router = express.Router();
/* GET visitor's IP. */
router.get('/', function(req, res, next) {
  res.end(req.connection.remoteAddress + '\r\n');
});
module.exports = router;
保存,重启web服务。
客户端:fwknop -n cen7 --resolve-url https://my.server.com/getip或者在.fwknoprc文件的cen7小节内添加一行:
RESOLVE_URL  https://my.server.com/getip
即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章