免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2661 | 回复: 0

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

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

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

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

4.客户端可以访问了

Port Knocking 技术原理

  Port knocking会在数据链路层(TODOverify it)监听所有的网络数据,类似嗅探程序,所以在不开端口,防火墙不允许此端口都可以接受到一定状态的数据包(如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不能用于WebMail
Port knocking 实践
  好,现在是实践下的时候了,search了下yum,发现有个叫knockd软件包(port knocking的实现其实很多的,这里有个列表: http://www.portknocking.org/view/implementations)。
1.ssh管理,根据鸟哥的文章做了下面的配置:
主要思想:
敲对了开端口,敲开门后cmd_timeout超时后再关闭。因为SSH只要在这个时间连接后防火墙关闭SSH端口对已有连接不会有影响。
/etc/knockd.conf
[options]
    UseSyslog
[opencloseSSH]
    sequence      = 44440:udp44442:udp44441:udp
    seq_timeout   = 30
    tcpflags      = synack
    start_command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport ssh -j ACCEPT
    cmd_timeout   = 300
    stop_command  = /sbin/iptables -D INPUT -s %IP% -p tcp --dport ssh -j ACCEPT

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

启动port knocking daemon,这里开了调试和Verbose选项。
[root@CentOS1 ~]# knockd -D -v
config: new section: 'options'
config: usesyslog
config: new section: 'opencloseSSH'
config: opencloseSSH: sequence: 44440:udp44442:udp44441:udp
config: opencloseSSH: seq_timeout: 30
config: tcp flag: SYN
config: tcp flag: ACK
config: opencloseSSH: start_command: /sbin/iptables -I INPUT -s %IP% -p tcp --dport ssh -j ACCEPT
config: opencloseSSH: cmd_timeout: 300
config: opencloseSSH: stop_command: /sbin/iptables -D INPUT -s %IP% -p tcp --dport ssh -j ACCEPT
ethernet interface detected
Local IP: 192.168.1.111
listening on eth0...
客户端来敲下,使用了windows下的程序:
knockWin32客户端程序:
http://www.zeroflux.org/proj/knock/files/knock-win32.zip
C:\>knock.exe -v 192.168.1.111 44440:udp 44442:udp 44441:udp
hitting udp 192.168.1.111:44440
hitting udp 192.168.1.111:44442
hitting udp 192.168.1.111:44441

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

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

这个时候我的ssh客户端就可以登录了。
超过门敲开后的时间自动关闭。很安全的自动门吧。
192.168.1.110: opencloseSSH: command timeout
opencloseSSH: running command: /sbin/iptables -D INPUT -s 192.168.1.110 -p tcp --dport ssh -j ACCEPT
2.ftp管理:
ftp这个古老的协议虽然不安全,但是传输效率无疑是比较高的。
这里vsftpd命令端口监听在默认的21端口,数据传输使用passive模式,开放在500050010,初始情况下iptables不允许对21的访问。
建立两个port knocking序列,一个开,一个关。
/etc/knockd.conf
[options]
UseSyslog
[openFTPControl]
sequence = 55540:tcp55542:tcp55541:tcp
seq_timeout = 30
tcpflags = syn
command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport ftp -j ACCEPT
[closeFTPControl]
sequence = 55541:tcp55542:tcp55540:tcp
seq_timeout = 30
tcpflags = syn
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport ftp -j ACCEPT
Port knock服务器启动:
[root@CentOS1 ~]# knockd -D -v
config: new section: 'options'
config: usesyslog
config: new section: 'openFTPControl'
config: openFTPControl: sequence: 55540:tcp55542:tcp55541:tcp
config: openFTPControl: seq_timeout: 30
config: tcp flag: SYN
config: openFTPControl: start_command: /sbin/iptables -I INPUT -s %IP% -p tcp --dport ftp -j ACCEPT
config: new section: 'closeFTPControl'
config: closeFTPControl: sequence: 55541:tcp55542:tcp55540:tcp
config: closeFTPControl: seq_timeout: 30
config: tcp flag: SYN
config: closeFTPControl: start_command: /sbin/iptables -D INPUT -s %IP% -p tcp --dport ftp -j ACCEPT
ethernet interface detected
Local IP: 192.168.1.111
listening on eth0...

客户端knock
C:\>knock -v 192.168.1.111 55540:tcp 55542:tcp 55541:tcp
hitting tcp 192.168.1.111:55540
hitting tcp 192.168.1.111:55542
hitting tcp 192.168.1.111:55541

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

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

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

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

knock服务器是运行在最好直接运行在路由器上,比如我刷dd-wrtlinksys WRT54G就可以。
参见: http://www.dd-wrt.com/wiki/index.php/Knockd
  另一种适合大家的方法是在路由器做NATknock服务器程序运行在内网Linux中。
ssh为例,我们就需要为外网能knockCentOS1IP:192.168.1.111),成功后能访问ssh,需在路由器中设定NATPort forwarding)。

当然你自己内网访问就不需要每次连接前knock下这么麻烦了,在防火墙规则里加条允许内网的sshftp的连接。
iptables -I INPUT -s 192.168.1.0/24 -p tcp --dport 21 -j ACCEPT
iptables -I INPUT -s 192.168.1.0/24 -p tcp --dport 22 -j ACCEPT
可以将knockd配置成initd service的方式以方便开机启动,这个就交给大家自己实现了。
最后附上看到的一篇小诗[http://www.yuandao.com/dispbbs.a ... ID=32624&page=7]
文中提到的有些信息就不细讲了,请参考:
  • 一般sshd 安全配置:
http://www.foogazi.com/2006/11/29/modify-ssh-to-maximize-security/
  • fail2ban使用
http://www.fail2ban.org/wiki/index.php/Main_Page
  • portknocking介绍
http://www.portknocking.org/view/about
  • 本文使用的Port knocking实现
http://www.zeroflux.org/projects/knock
  • 鸟哥图文并茂的介绍:         
http://linux.vbird.org/linux_security/knockd.php
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP