前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >knockd:CVM云主机的隐形斗篷

knockd:CVM云主机的隐形斗篷

原创
作者头像
黄希彤
修改2017-08-03 16:18:44
3.8K0
修改2017-08-03 16:18:44
举报
文章被收录于专栏:黄希彤的专栏

我们管理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到服务器上(以下操作假设你在当前用户的的~目录下操作):

代码语言:txt
复制
wget http://404-1252074372.cosgz.myqcloud.com/knockd/knock-0.7-1.el7.src.rpm 

安装rpmbuild

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

代码语言:txt
复制
rpmbuild --rebuild knock-0.7-1.el7.src.rpm 

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

代码语言:txt
复制
yum install -y rpm-build

安装 libpcap-devel

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

代码语言:txt
复制
rpmbuild --rebuild knock-0.7-1.el7.src.rpm

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

代码语言:txt
复制
yum install -y libpcap-devel 

安装 gcc

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

代码语言:txt
复制
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来装一个:

代码语言:txt
复制
yum install -y gcc

编译knockd

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

代码语言:txt
复制
rpmbuild --rebuild knock-0.7-1.el7.src.rpm 

安装knockd

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

代码语言:txt
复制
rpm -ivh /root/rpmbuild/RPMS/x86_64/knock-*

配置和验证knockd

修改日志文件位置

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

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

代码语言:txt
复制
sed -i 's/UseSyslog*/LogFile = \\/var\\/log\\/knockd.log/g' /etc/knockd.conf

修改敲门暗号

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

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

代码语言:txt
复制
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 服务来侦听我们设置的暗号了,运行一下指令:

代码语言:txt
复制
/etc/init.d/knockd start

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

代码语言:txt
复制
chkconfig knockd on

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

代码语言:txt
复制
/etc/init.d/knockd status

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

本地敲门测试

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

代码语言:txt
复制
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工具的的台式机或者笔记本上执行:

代码语言:txt
复制
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的情况,可以多试几次,或者手工依次执行:

代码语言:txt
复制
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)了,那现在我们可以披上隐身斗篷了。接下来的操作要非常小心,如果操作错误,有可能这台服务器从此就真的隐身了,我们再也登录不上去了。

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

代码语言:txt
复制
iptables -I INPUT -p tcp --dport 22 -m state --state ESTABLISHED -j ACCEPT 

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

代码语言:txt
复制
iptables -L 

如果看到

代码语言:txt
复制
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh state ESTABLISHED

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

放一颗后悔药(非必须)

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

代码语言:txt
复制
echo "iptables -D INPUT -p tcp --dport 22 -j DROP " | at now + 30 minutes

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

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

代码语言:txt
复制
atq

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

代码语言:txt
复制
atrm 编号

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

留一个后门

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

代码语言:txt
复制
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的话需要对命令做相应的修改。

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

代码语言:txt
复制
iptables -L

开始隐身

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

代码语言:txt
复制
iptables -A INPUT -p tcp --dport 22 -j DROP 

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

在vnc控制台上删除指令是

代码语言:txt
复制
iptables -D INPUT -p tcp --dport 22 -j DROP 

敲门登录

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

代码语言:txt
复制
knock -v xxx.xxx.xxx.xxx  63654  59472 31023 
ssh root@xxx.xxx.xxx.xxx

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

代码语言:txt
复制
knock -v xxx.xxx.xxx.xxx  63654  59472 31023 

然后马上登录。

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

万一网络不稳定怎么办

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

代码语言:txt
复制
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文件中:

代码语言:txt
复制
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规则,像这样:

代码语言:txt
复制
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

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是knock
  • 什么是konckd
  • 安装knockd前的准备(CentOS)
    • 下载knockd
      • 安装rpmbuild
        • 安装 libpcap-devel
          • 安装 gcc
            • 编译knockd
              • 安装knockd
              • 配置和验证knockd
                • 修改日志文件位置
                  • 修改敲门暗号
                    • 启动knockd服务
                      • 本地敲门测试
                        • 本地敲门验证
                          • 下载knock工具
                            • 真实远程敲门测试
                            • 开始隐身吧
                              • 隐身前的准备
                                • 放一颗后悔药(非必须)
                                  • 留一个后门
                                    • 开始隐身
                                      • 敲门登录
                                        • 万一网络不稳定怎么办
                                          • 设置开机启动
                                          相关产品与服务
                                          云服务器
                                          云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
                                          领券
                                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档