knockd:CVM云主机的隐形斗篷

我们管理CVM服务器的时候经常需要远程登录服务器。直接Telnet已经比较少人用了,大家比较广泛的使用ssh,再配合上证书或者高强度的密码登录,这样虽然安全了很多,但是把ssh端口暴露在外网仍然会召来黑客的探测和攻击,但是不开放接口的话自己都上不去了?

很多年前看一部流行的网络小说《我是一个黑客》,里面作者介绍了一个黑客们的小技巧:

但是要和其他系统通讯,端口肯定是必须要的。这个有经验的人用端口扫描一扫,一般也能看出多了一个端口。或者系统本来没有开的服务怎么开了等? 对付这种技术,曾经废了我很一段脑筋。 但是最后我还是想出一个办法。成功的解决了这个问题。 其实端口扫描就是和对方建立一个连接,如果连接成功,说明端口开发,否则就是没有开发的。 由于普通的网络程序,采用的都是tcp/ip的标准,所以当然你开了端口,程序都能连接。 但是我的后门,我拦截了连接函数。并且拦截了数据包。如果数据包不是我特殊的数据。我就知道是普通的扫描软件。我就不响应。于是对方就认为没有开发这个端口。 如果是我的程序的话,我是有特殊数据标识的。我的程序就会响应。

类似这样的手段其实在10多年前就已经不只是黑客手段,而成为了一种很好的安全手段了,还有了个很酷的名字: port knocking (介绍 / 中文介绍)。网站上收集了数十个port knocking的实现,其中有像小说一样通过ip包的端口+payload来实现的,更多的是通过依次knock一系列的端口号来实现的。假如每个端口号可以有65536种可能性(16bit),那么连续3个端口号就相当于一把48bit的密钥,已经具备相当的安全性了。

其中的一个port-knocking实现就叫knock(敲门),项目开源在github上 ,需要各种操作系统版本的knock工具可以在knock主页 下载到(注意mac和windows下的knock工具都是命令行工具,不要直接点击运行,要在cmd或者terminal窗口里面执行)。

什么是knock

敲门(knock)指的是我们从自己的客户端设备(pc、笔记本或者手机)向服务器IP发送一系列实现约好的暗号,而服务器上需要相应的安装接收暗号的服务knockd,它在接收到正确的暗号的时候,会临时性的为敲门者开一段时间的门并随后关上(当然也能够配置成一直开着),我们要在这几秒钟里面登录成功并且保持连接,如果不小心断了连接就要重新敲门。

knock动作的实质就是连续的向指定的ip的约定的端口连续的发送多个tcp或者udp包,比如我们可以通过*telnet 服务器地址 端口号* 命令来发送tcp包,也可以直接在浏览器地址栏里面用 http://服务器地址:端口号 的方式来让浏览器发出与服务器指定端口tcp握手的SYN包。但是最好用的还是直接下载knock工具(windows版mac版),用 knock 服务器地址 端口号 的方式来实现敲门

(这里使用了-v 参数来显示敲门过程)

什么是konckd

如果说knock是敲门的来宾,knockd就是应门的门童。inux下的守护进程(Linux Daemon )常用XXXd来命名,比如apache的守护进程httpd,knockd就是knock的守护进程,所以服务器只有安装了knockd,才能正确的相应客户端的knock暗号。

安装knockd前的准备(CentOS)

下载knockd

konck项目的主页在 http://www.zeroflux.org/projects/knock 我们可以从官网找到最新版的下载链接。不过为了避免可能遇到的GFW之类的问题,我们下载了一个版本放在腾讯云cos上,所以你可以通过执行下面这个命令,从腾讯云cos上下载knockd到服务器上(以下操作假设你在当前用户的的~目录下操作):

wget http://404-1252074372.cosgz.myqcloud.com/knockd/knock-0.7-1.el7.src.rpm 

安装rpmbuild

上一步下载到的是knockd的rpm文件,接下来我们要编译knockd,就需要使用到rpmbuild命令。

rpmbuild --rebuild knock-0.7-1.el7.src.rpm 

但是因为centos系统默认不带rpmbuild这个工具的,你会看到一个错误提示,那么我们就需要先用yum命令吧这个工具安装上去。

yum install -y rpm-build

安装 libpcap-devel

安装好了rpmbuild工具以后,我们再次尝试安装knockd:

rpmbuild --rebuild knock-0.7-1.el7.src.rpm

这次很可能提示变成了了“libpcap-devel is needed”,因为centos默认也不带libpcap-devel这个工具。那么一样的,我们可以用yum命令把它安装好:

yum install -y libpcap-devel 

安装 gcc

安装好了rpmbuild工具以后,我们再次尝试安装knockd:

rpmbuild --rebuild knock-0.7-1.el7.src.rpm

这次我们会看到一系列的自检,最后出现了这样的一些检测失败:

checking for x86_64-redhat-linux-gnu-gcc... no checking for gcc... no checking for x86_64-redhat-linux-gnu-cc... no checking for cc... no checking for x86_64-redhat-linux-gnu-cl.exe... no checking for cl.exe... no configure: error: in '/root/rpmbuild/BUILD/knock-0.7': configure: error: no acceptable C compiler found in $PATH

这说明,现在系统里面还缺一个C编译器,我们用yum来装一个:

yum install -y gcc

编译knockd

现在,我们终于可以编译 knockd 了:

rpmbuild --rebuild knock-0.7-1.el7.src.rpm 

安装knockd

执行以下指令安装knock工具:

rpm -ivh /root/rpmbuild/RPMS/x86_64/knock-*

配置和验证knockd

修改日志文件位置

一般我们会把knockd的日志记录到knockd.log文件中,这一步你可以自己编辑/etc/knockd.conf文件,把UseSyslog改成 LogFile = /var/log/knockd.log

如果不熟悉vi工具的话也可以直接执行这个命令

sed -i 's/UseSyslog*/LogFile = \\/var\\/log\\/knockd.log/g' /etc/knockd.conf

修改敲门暗号

和上一步一样,你可以在/etc/knockd.conf 中编辑进去自己的敲门暗号,当然也可以直接用默认的暗号,但是因为默认暗号都是一样的,所以太容易被猜到了。

为了方便,这里我们也可以用三行sed命令来完成对暗号的修改

sed -i 's/sequence.*/sequence = 63654:tcp,59472:tcp,31023:tcp/g' /etc/knockd.conf
sed -i 's/tcpflags.*/tcpflags = syn/g' /etc/knockd.conf
sed -i 's/start_command.*/start_command = iptables -I INPUT -s %IP% -p tcp --dport ssh -j ACCEPT/g' /etc/knockd.conf

第一行:在这里我们使用的暗号是:连续通过63654、59472和31023这三个端口通过tcp协议各敲一次门。你也可以编辑自己的暗号。

第二行:我们只接受tcp的syn握手包作为敲门信号。

第三行:我们把原来默认的iptables规则的修改方式从append(附加到最后面)改成insert(插入到最前面)

启动knockd服务

现在我们可以启动 knockd 服务来侦听我们设置的暗号了,运行一下指令:

/etc/init.d/knockd start

也可以打开knockd计划任务,这样系统重启的时候也能自动启动了

chkconfig knockd on

然后我们可以检查一下knockd是否如期望启动了:

/etc/init.d/knockd status

如果看到Active: active (running)就说明运行良好,如果看到Active: failed 的话就要检查一下日志文件(在前面的步骤中我们指定了/var/log/knockd.log文件)的错误记录了。

本地敲门测试

现在knockd已经开始监听敲门声了,我们首先可以在服务器上就地运行一次敲门:

knock -v ${runtime.vars.cvmIpAddress}  63654  59472 31023 

这样会依次用TCP协议从本服务器的公网接口向自己的63654、59472、31023端口发送三个数据包作为敲门暗号。

本地敲门验证

然后我们检查/var/log/knockd.log文件。在日志文件中,如果第一个暗号被接受了,会记录下来:

$xxx.xxx.xxx.xxx : opencloseSSH: Stage 1

随后依次接收到后面的暗号会触发 Stage2、Stage3,之后接着会执行/etc/knockd.conf文件中的[opencloseSSH]段里面的 start_command指令,并在日志文件中记录:

running command: /sbin/iptables -A INPUT -s xxx.xxx.xxx.xxx -p tcp --dport ssh -j ACCEPT

这条命令会在本机的iptables中的INPUT链上增加一条规则,允许发出正确敲门暗号的来源IP通过ssh端口访问服务器。

在经过10秒(在配置文件的cmd_timeout中可以修改)后,会接着执行 stop_command 。所以10秒后,再打开日志文件,会多看到两条:

$xxx.xxx.xxx.xxx: opencloseSSH: command timeoutopencloseSSH: running command: /sbin/iptables -D INPUT -s $xxx.xxx.xxx.xxx -p tcp --dport ssh -j ACCEPT

这条命令会把15秒前临时打开的后门又重新关掉。所以我们必须要在敲门成功后的10秒内通过ssh登录上服务器。

下载knock工具

你可以在knock的主页的Other Downloads段那里下载到knock工具的各种版本。比如假如你是是windows电脑可以下载Native Win32 Client ,如果是mac当然就下载MacOS Client了。

下载下来的压缩包里面可能有各种源码,不要管它,在window client包里面直接解压出来knock-win32.zip\knock-win32-port\Release\knock.exe这个文件放到一个控制台容易访问的位置,比如 C:\Windows\System32下面。 如果是MacOS client的话解压出来就只有一个knock文件,把它放在容易调用的路径(比如~)就可以了。

真实远程敲门测试

从安装了knock工具的的台式机或者笔记本上执行:

knock -v xxx.xxx.xxx.xxx  63654  59472 31023 

然后再检查确认一次 /var/log/knockd.log文件中, 是否出现了新的从opencloseSSH: Stage 1opencloseSSH: Stage 3的敲门记录和随后的opencloseSSH: running command记录。

因为敲门是通过发送ip包实现的(即使我们选择了tcp协议,敲门过程实际上也并不会真的建立任何tcp连接,只是tcp和udp本身成为暗号的一部分而已),所以ip包到达服务器的时间有可能是乱序的,这回导致敲门失败,如果遇到只看到opencloseSSH: Stage 1或者opencloseSSH: Stage 2,看不到opencloseSSH: Stage 3的情况,可以多试几次,或者手工依次执行:

knock -v xxx.xxx.xxx.xxx  63654
knock -v xxx.xxx.xxx.xxx  59472
knock -v xxx.xxx.xxx.xxx  31023 

如果仍然不行,有可能部分端口被禁止了,可以换端口试试看;也有可能网络不通(假如服务器开启了icmp协议的话可以tracert / traceroute 看看链路是否有问题)

开始隐身吧

隐身前的准备

到现在,敲门策略已经生效,我们可以通过自己定制好的暗号来让knockd执行特定的任务(临时增加一条iptable)了,那现在我们可以披上隐身斗篷了。接下来的操作要非常小心,如果操作错误,有可能这台服务器从此就真的隐身了,我们再也登录不上去了。

首先,非常重要的一条,先执行这个命令:

iptables -I INPUT -p tcp --dport 22 -m state --state ESTABLISHED -j ACCEPT 

这个命令会允许已经建立的tcp连接不会被我们下一步增加的规则封堵,这里使用I参数来确保这条规则被放在最上面。为了确保策略生效,我们需要运行这个命令:

iptables -L 

如果看到

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh state ESTABLISHED

这个信息,就说明规则添加成功了。

放一颗后悔药(非必须)

为了防止万一误操作导致服务器穿上隐身衣以后再也找不到了,我们可以先放好一颗后悔药:

echo "iptables -D INPUT -p tcp --dport 22 -j DROP " | at now + 30 minutes

这条计划任务会在30分钟后把我们的下一条指令添加的规则清除掉,你可以通过atq命令来查看它是否成功计划了。

这样如果在后面一切操作都顺利的话,我们可以用

atq

命令查到这个计划任务的编号,然后用

atrm 编号

命令吧这条计划任务删除。

留一个后门

在开始隐身之前,还可以把当前的登录ip加到白名单中以防万一。我们可以从last命令中找到still logged in的登录记录看到自己的登录ip来加到iptables里面,或者也可以用这样一行代码来完成:

last|grep "still"|sed  "s/root\s*pts\/0\s*\([0-9.]*\)\s*.*\s*still logged in/iptables -A INPUT -s \1 -p tcp --dport ssh -j ACCEPT/" |sh

如果登录用户不是root的话需要对命令做相应的修改。

一样的,我们需要检查确认生效:

iptables -L

开始隐身

现在我们要在iptables中添加一条规则,除了已经建立好的ssh连接和白名单IP之外,不允许任何人再建立新的ssh连接

iptables -A INPUT -p tcp --dport 22 -j DROP 

如果前面的每一步都做对了,那么这一步我们的服务器连接还是持续的,如果万一服务器成功隐身了并且服务器和主机失去联系了了,,如果是你自己购买的主机,你可以通过控制台上的“登录”功能,用vnc登录服务器来删除刚刚添加的规则。或者你也可以等上一步操作埋下的后悔药自动生效,把刚刚添加的规则删除掉。

在vnc控制台上删除指令是

iptables -D INPUT -p tcp --dport 22 -j DROP 

敲门登录

现在直接通过我们的笔记本、台式机进行ssh登录的行为已经被iptables规则给drop掉了,所以新建的会话根本登录不上去。以后如果需要登录的话我们可以这样做:

knock -v xxx.xxx.xxx.xxx  63654  59472 31023 
ssh root@xxx.xxx.xxx.xxx

或者在putty/secureCRT中登录服务器前先在控制台执行一次:

knock -v xxx.xxx.xxx.xxx  63654  59472 31023 

然后马上登录。

至此,我们成功的用knockd工具把随时端口隐藏起来了。如果有需要,我们还过配置 /etc/knockd.conf 文件来隐藏其他端口或者让服务器根据暗号执行其他任务。

万一网络不稳定怎么办

有的时候网络不稳定,难以保证敲门序列依次到达服务器,我们可以用sleep命令来控制每个knock包发出的时间,从而尽量确保ip包到达次序:

knockhost=myhostname
./knock $knockhost -v 63654 ;sleep 0.1s;./knock $knockhost -v 59472;sleep 0.1s;./knock $knockhost -v 31023;sleep 0.1s;ssh root@$knockhost

这里的第一行要修改成自己的服务器域名或者ip,后面的每个sleep都是0.1秒,可以根据具体网络情况做调整。

设置开机启动

我们前面已经通过 chkconfig knockd on 命令设置了knockd开机启动。但是这样每次服务器重启的时候我们设置的iptables设置都会丢失。为了在重启的过程保存和恢复iptables设置,我们可以在knockd命令中增加相应的操作:

在stop中添加保存设置

iptables-save>/etc/sysconfig/iptables

在start中恢复设置

iptables-restore</etc/sysconfig/iptables

我们可以通过这样一行命令把这两行添加到knockd文件中:

sed -i  -e 's/^start() {/start() {\n  iptables-restore < \/etc\/sysconfig\/iptables/'  -e 's/^stop() {/stop() {\n  iptables-save > \/etc\/sysconfig\/iptables/' /etc/init.d/knockd 

这样应该算是标准做法,但是这样做有一个风险就是,如果一个人刚好knock进来,iptables中刚好保存了他的白名单,那么这个白名单就会被永久保存下去了。如果要回避这个风险,也可以直接只在start中添加我们的两条iptables规则,像这样:

sed -i 's/^start() {/start() {\n  iptables \-I INPUT \-p tcp \-\-dport 22 \-m state \-\-state ESTABLISHED \-j ACCEPT\n  iptables \-A INPUT \-p tcp \-\-dport 22 \-j DROP/'   /etc/init.d/knockd

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏企鹅号快讯

微信小游戏重磅上线,H5游戏和页游迎来新天地?

关注游戏的小伙伴都知道,前不久《QQ飞车》手机版上线了,一大波老司机正在上线,毕竟曾经端游的QQ飞车带给玩家无数欢乐和记忆,而这次手Q别开生面的QQ飞车H5小游...

22510
来自专栏王拥军的专栏

盛大盒子:误判的野心——《互联网陷阱:流量战争》

很多人说盛大盒子太超前了,所以失败了,事实真的是这样的么?在笔者眼里,盒子不是太超前了,而是太落后了。而首富陈天桥之所以押注“盒子”,完完全全是因为野心太大,而...

3550
来自专栏企鹅号快讯

微信小游戏正式上线,H5游戏迎新机遇

游戏头条 微信号:gametoutiao(←长按复制) 中国首家顾问式新媒体定制属于您自己的媒体内容 导语:12月28日,微信更新至 6.6.1 版本。微信公众...

2119
来自专栏知晓程序

这款「沾花惹草」的小程序,帮你找回遗失的好奇心 | MINA 奖 #14

家门口的大树、路边的花草,每天走着看着,只知道那是树,是花,是叶,却从来叫不出它们的名字,好像……也并不想要知道。

792
来自专栏机器人网

厉害了机器人,这栋3层楼高建筑物从设计到施工全搞掂

各个领域都有机器人出现,也许有一天建筑工地上也会出现机器人的身影。瑞士苏黎世联邦理工学院(ETH)计划把机器人和 3D 打印技术结合,搭建一栋 3 层楼的建筑物...

3094
来自专栏知晓程序

干货十足!张小龙公开课现场玩「跳一跳」,曾拿过 6000 多分

2017 年 1 月 15 日,微信公开课 PRO 版如约在广州保利世贸博览馆举行。

551
来自专栏企鹅号快讯

2018年首发:最值得推荐的5大青少年编程学习网站,大人也适用

‍‍‍‍‍‍ ? 时间的车轮飞速转动,一转眼已是2018年,距离国家全面落实新一代人工智能产业发展三年行动计划,也只剩下600多天的时间。 如何让孩子在人工智能...

2015
来自专栏人称T客

预测:历史惊人的相似 三星正走向诺基亚

三星电子(Samsung Electronics)日前公布该公司 2013年第四季财报,当季营业利润为8.31兆韩元(约77亿美元),比分析师先前所预期的少了2...

2754
来自专栏企鹅号快讯

微信公布上线小程序游戏 腾讯应用宝安卓平台首发

12月29日,微信6.6.1新版本在腾讯应用宝平台重磅首发,该版本正式上线微信小游戏,玩家可直接点击游戏体验,无需下载安装,即点即玩。同时,小游戏还加入了社交元...

1968
来自专栏镁客网

诺基亚的VR,不是“救命稻草”,只是“小试牛刀”

703

扫码关注云+社区