免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7100 | 回复: 4
打印 上一主题 下一主题

芝麻开门,芝麻关门 Port knocking 简介 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-10-12 00:45 |只看该作者 |倒序浏览
芝麻开门,芝麻关门 Port knocking 简介

需求来源:
家里的Linux主机平时对internet开放着ssh。
经常有人尝试来暴力破解,曾改过ssh的port,好多了,不过这只是模糊安全。也装了fail2ban来限制攻击者的IP,但是攻击者频繁换IP的话fail2ban也没辙。
这次找到了新的方式:Port Knocking,原理很简单,不过挺有创意的。
Port Knocking 简介
为了开放ssh,一般我们让iptables允许ssh进入,不管来自哪里的ip。其实我们只需要为要登录的IP开iptables就可以了(白名单),封锁其他地址对ssh的访问。
可是很多时候不同的外网访问,我们是动态IP,需要让iptables对动态的IP开放SSH如何来实现呢,下面就介绍Port knocking(端口试探/端口碰撞):
Port knocking类似于一次地下组织秘密接头,一种最基本的方式:发送一定序列的UDP、TCP数据包。当运行在主机上的daemon程序捕捉到数据包以后,如果这个序列正确,则开启相应的端口,或者防火墙允许客户端通过。
一次简单的“敲门”流程
1.sshd开放中默认22端口,但是目前防火墙iptables还未允许我的IP通过。
2.Port knocking服务端初始化接头暗号(先敲端口7000再敲8000,TCP协议)和对应操作(对了就对此IP开通ssh的访问)
3.客户端对服务器不同端口进行knock(先7000再8000),发送SYN连接请求。
4.这些端口的连接对上了服务器端就会做些预定义操作为此IP开SSH端口。
5.这时我客户端就可以去连ssh的22端口了。
上面的接头暗号可以是TCP,UDP甚至是ICMP。

借用http://www.portknocking.org/view/about的图示,比较生动形象:
1.默认情况下客户端对服务器的应用由于防火墙不能访问

2.客户端敲正确的端口序列

3.服务器端Port Knocking(PK)程序打开防火墙端口

4.客户端可以访问了

Port Knocking 技术原理

Port knocking会在数据链路层监听所有的网络数据,类似嗅探程序,所以在不开端口,防火墙不允许此端口都可以接受到一定状态的数据包(如TCP SYN,为TCP三次握手第一个报文),当符合规则的报文出现时,规则开始记录,接下去的报文为正确下一个序列继续,错误就清空。当满足一次正确序列时就可以认为是一次event,触发一个action。
Port Knocking 优缺点
优点:
Port knocking 没监听端口,而且也不需要防火墙先开放这些Knock端口,可以隐藏你开放的服务,别人没法知道你是否使用了Port Knocking。
信息是由一定的端口访问顺序来传输的,而不是网络报文内容,所以不容易被报文嗅探工具截获。
阻止0day攻击。当服务器bug还没补丁前,Port Knocking可以做为一层防护。
Port Knocking增加了一层保护,即使在PK和防火墙都失效的情况下,ssh本身的安全验证机制也能很好的保护系统。

缺点:
如果port knocking Daemon挂了话相当于你家的门坏了,有钥匙也进不了。这个称为单点故障,即此服务停止的话整个系统不能工作。不过新的实现一般都检测daemon是否正常。
不是很方便,连ssh前需要先knock下,要使用专门软件,当然很多能发送连接请求的程序都可以的,客户端要对这个端口序列的保密工作,
Port Knocking不能用于Web,Mail。

Port knocking 实践
好,现在是实践下的时候了,search了下yum,发现有个叫knockd软件包(port knocking的实现其实很多的,这里有个列表: http://www.portknocking.org/view/implementations)。
1.ssh管理,根据鸟哥的文章做了下面的配置:
主要思想:
敲对了开端口,敲开门后cmd_timeout超时后再关闭。因为SSH只要在这个时间连接后防火墙关闭SSH端口对已有连接不会有影响。
/etc/knockd.conf
  1. [options]
  2.     UseSyslog
  3. [opencloseSSH]
  4.     sequence      = 44440:udp,44442:udp,44441:udp
  5.     seq_timeout   = 30
  6.     tcpflags      = syn,ack
  7.     start_command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport ssh -j ACCEPT
  8.     cmd_timeout   = 300
  9.     stop_command  = /sbin/iptables -D INPUT -s %IP% -p tcp --dport ssh -j ACCEPT
复制代码


iptable未开放SSH
  1. [root@CentOS1 ~]# iptables -nL INPUT
  2. Chain INPUT (policy ACCEPT)
  3. target     prot opt source               destination
  4. RH-Firewall-1-INPUT  all  --  0.0.0.0/0            0.0.0.0/0
复制代码


启动port knocking daemon,这里开了调试和Verbose选项。
  1. [root@CentOS1 ~]# knockd -D -v
  2. config: new section: 'options'
  3. config: usesyslog
  4. config: new section: 'opencloseSSH'
  5. config: opencloseSSH: sequence: 44440:udp,44442:udp,44441:udp
  6. config: opencloseSSH: seq_timeout: 30
  7. config: tcp flag: SYN
  8. config: tcp flag: ACK
  9. config: opencloseSSH: start_command: /sbin/iptables -I INPUT -s %IP% -p tcp --dport ssh -j ACCEPT
  10. config: opencloseSSH: cmd_timeout: 300
  11. config: opencloseSSH: stop_command: /sbin/iptables -D INPUT -s %IP% -p tcp --dport ssh -j ACCEPT
  12. ethernet interface detected
  13. Local IP: 192.168.1.111
  14. listening on eth0...
复制代码


客户端来敲下,使用了windows下的程序:
knock的Win32客户端程序:
http://www.zeroflux.org/proj/knock/files/knock-win32.zip

  1. C:\>knock.exe -v 192.168.1.111 44440:udp 44442:udp 44441:udp
  2. hitting udp 192.168.1.111:44440
  3. hitting udp 192.168.1.111:44442
  4. hitting udp 192.168.1.111:44441
复制代码


服务器端监视到了正确的端口序列,触发动作,OPEN SESAME(芝麻开门!) 开放了SSH端口。
  1. 2009-09-12 00:27:25: udp: 192.168.1.110:54204 -> 192.168.1.111:44440 60 bytes
  2. 192.168.1.110: opencloseSSH: Stage 1
  3. 2009-09-12 00:27:25: udp: 192.168.1.110:54205 -> 192.168.1.111:44442 60 bytes
  4. 192.168.1.110: opencloseSSH: Stage 2
  5. 2009-09-12 00:27:25: udp: 192.168.1.110:54206 -> 192.168.1.111:44441 60 bytes
  6. 192.168.1.110: opencloseSSH: Stage 3
  7. 192.168.1.110: opencloseSSH: OPEN SESAME
  8. opencloseSSH: running command: /sbin/iptables -I INPUT -s 192.168.1.110 -p tcp --dport ssh -j ACCEPT
复制代码

iptables中已经加了允许条目。
  1. [root@CentOS1 ~]# iptables -nL INPUT
  2. Chain INPUT (policy ACCEPT)
  3. target     prot opt source               destination
  4. ACCEPT     tcp  --  192.168.1.110        0.0.0.0/0           tcp dpt:22
  5. RH-Firewall-1-INPUT  all  --  0.0.0.0/0            0.0.0.0/0
复制代码


这个时候我的ssh客户端就可以登录了。
超过门敲开后的时间自动关闭。很安全的自动门吧。
  1. 192.168.1.110: opencloseSSH: command timeout
  2. opencloseSSH: running command: /sbin/iptables -D INPUT -s 192.168.1.110 -p tcp --dport ssh -j ACCEPT
复制代码


2.ftp管理:ftp这个古老的协议虽然不安全,但是传输效率无疑是比较高的。
这里vsftpd命令端口监听在默认的21端口,数据传输使用passive模式,开放在5000~50010,初始情况下iptables不允许对21的访问。
建立两个port knocking序列,一个开,一个关。
/etc/knockd.conf
  1. [options]
  2.     UseSyslog
  3. [openFTPControl]
  4.     sequence    = 55540:tcp,55542:tcp,55541:tcp
  5.     seq_timeout = 30
  6.     tcpflags    = syn
  7.     command     = /sbin/iptables -I INPUT -s %IP% -p tcp --dport ftp -j ACCEPT
  8. [closeFTPControl]
  9.     sequence    = 55541:tcp,55542:tcp,55540:tcp
  10.     seq_timeout = 30
  11.     tcpflags    = syn
  12. command     = /sbin/iptables -D INPUT -s %IP% -p tcp --dport ftp -j ACCEPT
复制代码

Port knock服务器启动:
  1. [root@CentOS1 ~]# knockd -D -v
  2. config: new section: 'options'
  3. config: usesyslog
  4. config: new section: 'openFTPControl'
  5. config: openFTPControl: sequence: 55540:tcp,55542:tcp,55541:tcp
  6. config: openFTPControl: seq_timeout: 30
  7. config: tcp flag: SYN
  8. config: openFTPControl: start_command: /sbin/iptables -I INPUT -s %IP% -p tcp --dport ftp -j ACCEPT
  9. config: new section: 'closeFTPControl'
  10. config: closeFTPControl: sequence: 55541:tcp,55542:tcp,55540:tcp
  11. config: closeFTPControl: seq_timeout: 30
  12. config: tcp flag: SYN
  13. config: closeFTPControl: start_command: /sbin/iptables -D INPUT -s %IP% -p tcp --dport ftp -j ACCEPT
  14. ethernet interface detected
  15. Local IP: 192.168.1.111
  16. listening on eth0...
复制代码


客户端knock下
  1. C:\>knock -v 192.168.1.111   55540:tcp 55542:tcp 55541:tcp
  2. hitting tcp 192.168.1.111:55540
  3. hitting tcp 192.168.1.111:55542
  4. hitting tcp 192.168.1.111:55541
复制代码


服务器收到正确序列,执行动作,打开ftp端口。
  1. 2009-09-12 22:42:22: tcp: 192.168.1.110:51808 -> 192.168.1.111:55540 66 bytes
  2. 192.168.1.110: openFTPControl: Stage 1
  3. 2009-09-12 22:42:22: tcp: 192.168.1.110:51809 -> 192.168.1.111:55542 66 bytes
  4. 192.168.1.110: openFTPControl: Stage 2
  5. 2009-09-12 22:42:22: tcp: 192.168.1.110:51810 -> 192.168.1.111:55541 66 bytes
  6. 192.168.1.110: openFTPControl: Stage 3
  7. 192.168.1.110: openFTPControl: OPEN SESAME
  8. openFTPControl: running command: /sbin/iptables -I INPUT -s 192.168.1.110 -p tcp --dport ftp -j ACCEPT
复制代码


这个时候客户端可以ftp登录,通过原来开放的数据传输端口传文件。
使用完毕,通过另一个knock序列关闭ftp端口
  1. C:\>knock -v 192.168.1.111   55541:tcp 55542:tcp 55540:tcp
  2. hitting tcp 192.168.1.111:55541
  3. hitting tcp 192.168.1.111:55542
  4. hitting tcp 192.168.1.111:55540
复制代码


服务器端关闭ftp端口。
  1. removing successful knock attempt (192.168.1.110)
  2. 192.168.1.110: closeFTPControl: Stage 1
  3. 2009-09-12 22:49:08: tcp: 192.168.1.110:51917 -> 192.168.1.111:55542 66 bytes
  4. 192.168.1.110: closeFTPControl: Stage 2
  5. 2009-09-12 22:49:08: tcp: 192.168.1.110:51918 -> 192.168.1.111:55540 66 bytes
  6. 192.168.1.110: closeFTPControl: Stage 3
  7. 192.168.1.110: closeFTPControl: OPEN SESAME
  8. closeFTPControl: running command: /sbin/iptables -D INPUT -s 192.168.1.110 -p tcp --dport ftp -j ACCEPT
复制代码


家庭实际使用中,一般会有路由器,典型的网络拓扑:

knock服务器是运行在最好直接运行在路由器上,比如我刷dd-wrt的linksys WRT54G就可以。
参见: http://www.dd-wrt.com/wiki/index.php/Knockd
另一种适合大家的方法是在路由器做NAT,knock服务器程序运行在内网Linux中。

以ssh为例,我们就需要为外网能knock到CentOS1(IP:192.168.1.111),成功后能访问ssh,需在路由器中设定NAT(Port forwarding)。

SSH, knock port 44440~44442


当然你自己内网访问就不需要每次连接前knock下这么麻烦了,在防火墙规则里加条允许内网的ssh和ftp的连接。
  1. iptables -I INPUT -s 192.168.1.0/24 -p tcp --dport 21 -j ACCEPT
  2. iptables -I INPUT -s 192.168.1.0/24 -p tcp --dport 22 -j ACCEPT
复制代码


可以将knockd配置成initd service的方式以方便开机启动,这个就交给大家自己实现了。


文中提到的有些信息就不细讲了,请参考:
1)        一般sshd 安全配置:
http://www.foogazi.com/2006/11/2 ... -maximize-security/
2)        fail2ban使用
http://www.fail2ban.org/wiki/index.php/Main_Page
3)        portknocking介绍
http://www.portknocking.org/view/about
4)        本文使用的Port knocking实现
http://www.zeroflux.org/projects/knock
5)        鸟哥图文并茂的介绍:         
http://linux.vbird.org/linux_security/knockd.php

[ 本帖最后由 可可火山 于 2009-10-14 13:10 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-10-14 03:24 |只看该作者
不错,有点意思。不过最后那首诗。。。 反正我是不懂这个

论坛徽章:
0
3 [报告]
发表于 2010-03-07 14:55 |只看该作者
不错  有意思! 可作后门使用了!

论坛徽章:
0
4 [报告]
发表于 2010-05-30 12:20 |只看该作者
额外开发的3个端口,在knock没占用的情况下也给黑客多留了个后门

论坛徽章:
0
5 [报告]
发表于 2010-06-01 20:25 |只看该作者
额外开发的3个端口,在knock没占用的情况下也给黑客多留了个后门
linuxdiy 发表于 2010-05-30 12:20


其实这3个端口不必打开的,只需要尝试连接一下。
TCP协议我还要再深入下才能讲清楚,请其他高手解释下

加为精华咯,呵呵。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP