Learning Convolutional Neural Networks for Graphs

图卷积网络(Graph Convolutional Network),顾名思义,就是把图像处理中的卷积层运用到图上,图卷积网络能够处理如下两类问题[1]——

  • 给定一系列图作为训练集,可以训练出一个函数,该函数能够对未知的图进行分类或回归。
  • 给一张很大的图,学习图的表示函数(representation),并对于未知的图,推导出一些性质,诸如判断一个节点的类型,或是消失的边权等等。

回顾卷积神经网络,一个像素的特征值,来自于该层输入中,这个像素空间上临近点的像素特征。卷积神经网络的成功,从某种意义上来说,正式借助了这种隐含的空间特征。对于NLP也是同理

但是,对于大部分图而言,并没有这么好的特征可以利用,要将CNN迁移到图上面,需要解决这两个问题——

  • 找到一部分中间点,这些中间点将各自总结其邻域节点的特征。
  • 计算每个中间点临近图的正则化表示,即向量空间中的一个可以编码这个图的表示

定义术语

首先,需要定义图的节点的标号(labeling)和排名(ranking)。标号是一个给图上每个节点赋予一个权值的映射l(u)。而排序是将图上每一个节点权值从小到大排名后的排名映射r(u)。即满足对于任意u, v \in Vr(u)<r(v)当且仅当l(u)>l(v)

倘若r(u)函数和l(u)函数都是单射的,那么使用r(u)对于图中的节点编号进行置换,可以得到A^l(G)

上述定义其实是有道理的,假设l(u)是一个能够描述节点位置的函数,那么使用r(u)映射后的图G'可以用来当做一个图的标准化(Canonicalization)结构,这个结构能够用来比较两个图是否同构(Isomorphism)。

l(u)的最优化是NP的,但是可以构造出相对有效的l(u)——用距离“中心节点”的距离函数作为l(u),这里的“中心节点”是Node Sequence Selection函数的结果。

算法流程

Node Sequence Selection

为了对图进行卷积操作,我们需要定义卷积的stride和width。实际的算法非常简单,既然我们假设了r(u)函数能够有效刻画节点空间位置,那么在按照r(u)排序后的节点序列中,使用一个width大小stride步长的滑动窗口就可以完成节点的选择了。

Neighborhood Assembly

这一个步骤,试图对于上一步得到的若干个节点,分别找到一个大小为k的领域,这里用了简单的广度优先搜索算法。

Graph Normalization

图的规范化操作使用上一步得到的中心节点及其领域,重新对于领域中的节点进行标号,进而通过标号的排名进行置换,此时的图就相对规范了。由于距离不是单射函数,所以文中引用了NAUTY的方法,对于同样距离的节点进行区分。

Convolutional Architecture

文中的模型能够同时处理点权和边权,仅需要改变CNN的stride参数即可,具体实现略

评价

  • 没有公开代码,可复现性存疑
  • 适合作为GCN的入门论文,但和现在主流的GCN不一样。

引用

  1. Niepert M, Ahmed M, Kutzkov K. Learning convolutional neural networks for graphs[C]//International conference on machine learning. 2016: 2014-2023.

云计算平台故障事件与相关研究

今年来,云计算平台发生了多起故障事件,而其原因的分析以及损失估计被很多学者所研究,本文将分别列举规模较大的云计算故障事件,并加以分析,同时对于学界对云计算研究成果做综述性摘要。

经典事件

阿里云停机事件

2019年3月3日,阿里巴巴旗下阿里云发布通报称,华北2地域可用区C部分ECS服务器(云服务器)等实例出现IO HANG(IO不响应),经紧急排查处理后已全部恢复。在这一次事件中,华北相当多的互联网公司的App、网站全部瘫痪,大量程序员、运维晚上从被窝里面被拉回公司修复错误。

Amazon AWS宕机事件

2017年2月28号,一名亚马逊程序员在调试系统的时候,试图运行了一条脚本,以删除少量用于支持支付操作的服务器。但是他输错了命令,导致大量服务器被删。而被误删除的服务器集群中中,有两个非常重要的系统,一个是存放了该区域所有托管服务器的配置信息,用于处理所有GET, LIST, PUT 和 DELETE 请求的。另一个系统用于负责新服务器的分配。

为了修复这个错误,亚马逊不得不重启整个系统。对于数年没有重启过得系统,而重启系统后的完整性和安全检查耗费了非常多的时间。最终导致了震惊全球的Amazon S3宕机4个小时事件。

事后,亚马逊官方网站通告总结事件时,称整个事件的触发程序,是一个支持快速移除大量负载的命令,而我们已经将该命令进行修改,使得负载的移除更加缓慢,并且增加了足够的安全保障,当某个节点移除后,其对应的子系统剩余节点没有能力负载所有的访问,则该移除指令不会被执行。另一方面,亚马逊也修改了恢复系统,保障在将来错误发生时,恢复不再会花费那么多时间。

Azure服务器中断事件

在2012年2月28日,微软旗下的Azure云服务器发生中断,事件长达7小时,据微软官方网站通告,该中断是由于服务中一处关于闰年的计算失误导致的。问题发生后,工程师快速部署了修复代码,并在7小时候恢复了服务器的访问。

其他安全事件

对于云服务商来说,设备故障并不是唯一的灾难,安全性漏洞更为致命,在7 Most Infamous Cloud Security Breaches文章中写道,微软、Dropbox、LinkedIn、Apple iCloud、Yahoo都曾经经历过安全漏洞攻击。并产生了很大的损失。

相关研究

硬件故障是云计算平台故障中,一个非常古老的错误,有非常非常多的研究者对他进行过研究。随着云计算的发展和商业化,硬件故障所扮演的角色也在随之改变,在Wang et al. (2017)的研究中指出,这些变化有积极和消极的方面。
从积极的方面来讲,云服务商的硬件设备的质量越来越可靠,更完备的故障检测系统也被部署到了云计算平台上,从而使得故障的恢复更加高效。而且由于云计算已经是一门非常成熟的技术,面对故障,运维也有足够的经验。这一系列变化都会倾向于降低对故障事件的损失。
但是从消极的方面来讲,由于市场扩大,更多的服务商进驻云计算行业,使得运营商们更加注重成本。自然而然的,他们就会倾向于使用那些不那么可靠,但是便宜的设备。

在Lloyds ́ and AIR (2018)的研究中,对于云服务商的故障损失进行了估计,发现美国的云服务商停机3-6天对应损失可达69亿美元。其中,制造业和零售批发业首当其冲,而其中损失最严重的是财富1000强的企业。

为了控制由于云服务商故障导致的损失,催生出一个全新的保险行业,叫做网络保险(cyber-insurance),这种保险以投保者的网站的可用性作为保险项目。不同于传统的保险,网络保险作为一个新兴的品种,仍没有被大众以及保险公司所接受,一方面是人们并没有正确的认识到服务商故障的损失,另一方面是网络保险有极大的系统性风险。一个云服务商的故障可能同时美国导致124万企业的经营遭受影响,此时大规模的赔偿可能会对保险公司带来巨大的流动性风险。

对于云服务的故障原因,文章Calvesbert (2018列举了四类原因:
1)环境原因,包括自然灾害在内的,无法认为控制的故障。
2)敌对攻击,主要包括竞争对手或黑客,尝试利用网络的漏洞进行攻击。
3)意外原因,指的是日常操作维护的误操作。
4)结构性故障,由于结构缺陷、资源耗尽而产生无法预知的错误。

当然,云平台的故障并不局限于大规模停机,频次更高的是局部性错误。在Chen et al. (2014)的研究中,将这类错误分类为应用错误、配置错误与云错误。配置错误是开发者认为错误配置、重复提交任务导致的,由于开发者在发现任务失败后倾向于重复提交,因此配置错误是所有故障中最多的。其次就是应用错误,其原因为云平台本身的资源限制、以及硬件错误。最后是云错误,其来源于运节点的添加、删除与维护。

总结

经过大规模的资源不可访问的问题的四种成因,意外原因和结构性故障居多,因为这两种成因比较难以估计,与之相反,敌对攻击和环境原因都会有非常完善的防范措施。因而在近现代的宕机事件中,并不常发生。同时可以发现,不同公司在事件后的翻译也不尽相同,这可以通过修复时间,以及事后事件成因分析看出。其中,亚马逊事件后,官方公布了详细的故障原因,以及改进措施,不仅给用户一个交代,也对我们的研究有很大帮助。反之另一些宕机事件,则官方没有公布调查结果,或是寥寥几句,给用户和研究者都带来 极大的困惑。

现有的研究从各个方面为降低云计算错误做了非常重要的贡献,包括损失估计,频率分析,原因总结等等。为云计算厂商优化平台算法,增加可靠性有非常积极的作用。

引用

  • AWSCloud. 2017. Summary of the Amazon S3 Service Disruption in the Northern Virginia (US-EAST-1) Region. (2017). https://aws.amazon.com/message/41926/.
  • Contel Bradford. 2018.7 Most Infamous Cloud Security Breaches.(2018).https://blog.storagecraft.com/7-infamous-cloud-security-breaches/.
  • Gian Calvesbert. 2018. Cloud Service Failure: 3 Things to Know. (2018). https://www.air-worldwide.com/Blog/Cloud-Service-Failure–3-Things-to-Know/.
  • Xin Chen, Charng-Da Lu, and Karthik Pattabiraman. 2014. Failure analysis of jobs in computeclouds: A google cluster case study. In2014 IEEE 25th International Symposium on SoftwareReliability Engineering. IEEE, 167–177.
  • Bill Laing. 2012. Windows Azure Service Disruption Update. (2012). https://azure.microsoft.com/en-us/blog/windows-azure-service-disruption-update/.
  • Lloyd ́s and AIR. 2018.Cloud Down: Impacts on the US economy. Technical Report.
  • G. Wang, L. Zhang, and W. Xu. 2017. What Can We Learn from Four Years of Data Center Hardware Failures?. In 2017 47th Annual IEEE/IFIP International Conference on Dependable Systems and Networks (DSN). 25–36. https://doi.org/10.1109/DSN.2017.26

FaceNet: A Unified Embedding for Face Recognition and Clustering 阅读笔记

简介

该论文试图去解决人脸识别的课题,人脸识别有三个研究方向,分别为

  1. 验证(verification),用于判断两个图像是否为同一个人
  2. 识别(recognition),用于识别一个图像是哪个人
  3. 聚类(clustering),在一系列图片中,找到一个经常出现的人

通常的人脸识别算法流程是这样的——

与之相反,论文提出的模型,以直接生产特征向量为目标,也就是说,特征向量不再作为一个中间信息,而是一个模型实实在在优化的目标。论文中的这种损失函数称为Triplet Loss。

模型

我们希望构造函数f(x),将图片x映射到特征空间\mathbb{R}^d,使得所有相同身份的人脸拥有较小的欧几里得距离,反之不同人脸的距离较大。在Triplet Loss的构造中,为了满足尺度的恒定,还额外规定f(x)位于单位球体上,即|f(x)| = 1

模型希望相同人脸特征距离近,不同人脸特征距离远,量化到数学公式上就是

|f(x_i^a)-f(x_i^p)|^2 + \alpha < |f(x_i^a)-f(x_i^n)|^2

其中x_i^a为基准图片(anchor),x_i^p为同一身份的不同图片(positive),x_i^n为不同身份的不同图片(negative). 而\alpha被称为TripletLoss的边缘距离(margin)

由于算力的原因,不能计算出所有可能的x_i^ax_i^px_i^n组合,即所有Triplet。因此,选择有代表性的Triplet是非常有必要的。一种非常暴力的做法是,找到上述不等式中前半部分的最大值以及后半部分的最小值,即argmax|f(x_i^a)-f(x_i^p)|^2argmin|f(x_i^a)-f(x_i^n)|^2,他们的组合一定是优化的瓶颈部分。我们将他们作为Hard Triplet,单纯优化他们就可以较快收敛。

由于图片画质以及误标记等原因,全局的argmax和argmin表现并不好,不过将其改成mini-batch内部的argmax与argmin就好了。

从零开始编写并托管WordPress插件:NoBaidu抵制百度插件

最近被一篇称为《搜索引擎百度已死》的文章被刷屏了,笔者本身就非常不喜欢百度,趁放寒假没有事情干,琢磨这在自己的网站上写一个插件。当访问者从百度进入网站,则在页面顶部显示一段用户自定义的阻止标语。顺便搞清楚Wordpress插件的原理。

上图就是NoBaidu的一个截图,本文按照我的编写顺序,分为——

  • 如何编写一个Wordpress插件
  • 如何将编好的插件托管到云端

另外,插件的源代码在我的github中开源,读者可以对照理解。

如何编写一个wordpress插件

编写Wordpress插件的教程网上很多,我就不重新造轮子了,我自己是在 如何开发一个WordPress如何开发一个WordPress插件 这篇文章中学到的,其核心要义就是钩子函数——

在Wordpress渲染一个页面的时候,在很多关键位置设置钩子(比如页面渲染开头,渲染器启动后等位置),而插件可以自定义的在任何钩子上挂载自己的函数,这样当页面渲染到了指定位置时,插件可以做一些自己的事情。

比如下面代码就可以在robots.txt渲染时,运行 $this->robots_txt_edit 指定的插件处理模块。

而以NoBaidu插件为例,我们需要支持如下逻辑——

  • 当普通用户访问时,检查用户的请求头的REFERER域是不是baidu域名下的URL
  • 当用户来自百度时,注册一个钩子函数,在页面渲染开始时,加入一个固定在页面顶部的,包含了自定义文字的HTML元素。
  • 当请求robots.txt时,返回禁止Baidu爬虫的robots文字

除此之外,还需要一些额外的代码,来保证我们的插件可以正常使用

  • 在用户是管理员的时候,生成插件设置页面,在其中可以设置显示的自定义抵制文字,用户选择是否组织百度爬虫,以及抵制文字是显示在顶端还是页面中部等等…
  • 编写插件安装、卸载时的逻辑,保证安装时初始化配置信息,卸载时删除配置信息,做到无残留

上述的逻辑,都集中到了下面的代码中,该代码使用一个类包裹了所有的函数(其作用类似于C++中的Namespace,用于最小化命名冲突)

看懂了上面的代码,是不是觉得Wordpress编写插件非常简单? 上述代码中引用的其他php代码,大家可以在我的github中自行查阅。

将自己写好的插件托管到wordpress云端

WordPress官网的Plugin目录最低端,有一个Add Your Plugin分区,这个分区详细介绍了该如何将你的Wordpress插件托管至wordpress.org,一般来说,读完上述的文章,你就已经能够自主把自己的插件丢到云端了。不过我准备从自己的经历出发,来大致讲一讲流程。

WordPress.org自己维护了一个svn仓库,最终会获得自己插件的专属仓库,你可以使用svn提供的版本控制,自行升级、修订等等。而想要获得自己插件的svn仓库,你就需要把自己的插件的最初版提交给官方审核。提交入口在这里。这里写几个提交的注意事项吧——

  • 最重要的是要知道php没有命名空间之说,所以一切全局变量都应该防止冲突。一个比较取巧的做法就是像上文一样,将你自己的程序包裹在一个class里面,而class以自己的插件名称命名。(我就因为配置的class命名为MySettingClass被官方打回来了)
  • 不要有额外的文件,之前写插件的时候,把网上别人插件的代码拷贝到了自己的目录,本来只是想照着抄一抄,结果忘删了,这个也被审核人发现了。
  • README.txt按照官方的标准格式写。

网站上面说的是7个工作日,结果我第一天晚上提交了初版的zip包,第二天早上就收到了审核者的邮件。按照要求修改了一些类名,并删除了无关文件后,我直接把zip包附在了回复中,第三天早上就拿到了通过的消息,并且获得了svn仓库的访问权限。开源社区真的非常强大👍

第一次要求修改的邮件
成功通过审核

接下来就是上传仓库了,如果读者会使用git的话,就别自己去学svn了,照着官方指南走一遍,就完全学会了。和git的pull, add, commit, push, tag如出一辙。

当你的first commit上传到远程仓库,并且readme.txt没有什么问题的话,你应该是可以立即在插件商店中搜索到自己写的插件的。

到这里我们在wordpress上面第一个插件就做好啦!

如果你觉得本文有用的话,欢迎到我的github仓库Star或Contribute~

让我们一起抵制Baidu吧~

参考文章

  • 【一个前人的代码】:http://ju.outofmemory.cn/entry/222836
  • 【如何开发Wordpress插件】:https://www.wpdaxue.com/writing_a_plugin.html
  • 【官方文档】:https://wordpress.org/plugins/developers/

Identity-Aware Convolutional Neural Network for Facial Expression Recognition 阅读笔记

这篇论文核心目标是提高人脸表情识别的精度。经典的表情识别算法,会将表情图片映射到特征空间(feature space)中的特征向量,而两个特征向量的欧几里得距离来衡量两个表情的相似度。

作者发现常规模型容易将“同一个人(indentity)”的特征向量放在一起而非“同一个表情(expression)”。这个问题表现在模型训练的时候,模型容易“偷偷”记录下训练数据中人物的面貌,并基于此进行判断。倘若随便换一个测试集,模型的准确度就有非常大的下降。(比如模型会记录下某黑人胖子A的吃惊的表情特征,但是之后测试集中,倘若是一个黑人瘦子B吃惊的表情,那么模型就不怎么容易判别出来了)

如下图,现有的模型的特征向量如图(a)所示依赖于人物,而作者的模型能挖掘和人物无关的表情特征,反映到特征空间中如图(b)所示。

文章提出的模型称为identity-aware convolutional neural network (IACNN) ,其核心思想是学习与表情有关(expression-related)的特征,并在同时,故意学习一个和人物有关(identity-related)的特征,后者虽然不利于网络的实际识别,但是却有利于让前者变得与身份无关(identity-invariant).

同时,该文章提出了一种距离的计算法则,能够让相似的表情的特征向量相距较近,而不相似的表情的特征向量相距较远。(不过这个计算法则感觉并不算亮点或是创新)

首先定义欧几里得距离作为接下来的距离公式——

D(f^E(I_1), f^E(I_2)) = |f^E(I_1), f^E(I_2)|^2

下面是一个自定义的损失函数公式——

L^{exp}_{Contrastive} = \frac{z_i^E}{2} * D(f^E(I_{i, 1}), f^E(I_{i,2})) + \frac{1-z_i^E}{2} * max(0, \alpha^E - D(f^E(I_{i, 1}), f^E(I_{i,2})))

这个公式看着很长,实际上非常简单,当两个图片属于同一个表情(exp),那么z_i=1 ,优化损失函数倾向于让他们的特征向量靠近;而倘若不属于同一个表情,z_i=0,优化损失函数倾向于让他们至少有\alpha^E的距离。这个损失函数可以用于训练提取表情特征的网络f^E(x)。顺便一提f^E是一个基于CNN的网络。

与上面相似,我们也可以创造一个L^{ID}_{Contrastive}专门用来训练提取身份特征的网络F^{ID}

L^{ID}_{Contrastive} = \frac{z_i^E}{2} * D(f^{ID}(I_{i, 1}), f^{ID}(I_{i,2})) + \frac{1-z_i^{ID}}{2} * max(0, \alpha^{ID} - D(f^{ID}(I_{i, 1}), f^{ID}(I_{i,2})))

通过上述的网络f^{ID}f^E,我们对于一个图片能够生成表情相关的特征FC_{exp}和身份相关特征FC_{ID},令他们的组合特征为FC_{feat}.

使用FC_{feat}进行预测,得到损失函数L^1_{softmax}L^2_{softmax}(1和2分别是两张图片),使用FC_{exp}进行预测,得到L^{exp1}_{softmax}L^{exp2}_{softmax}

最终损失函数如下

L = \lambda_1 L^{ID}_{Contrastive} + \lambda_2 L^{Exp}_{Contrastive} + \lambda_3 L^1_{softmax}+ \lambda_4 L^2_{softmax}+ \lambda_5 L^{exp1}_{softmax}+ \lambda_6 L^{exp2}_{softmax}

可以发现,优化损失函数L,身份特征相关的信息倾向于聚集在FC_{ID}中,从而使FC_{Exp}的信息是纯粹的面部无关信息。那么最后测试集上,单纯使用FC_{Exp}进行预测,就不会存在模型对于训练集人物过于依赖的问题了。

Visdom教程(3):绘制折线图

这是Visdom教程的第三篇文章,主要讲了绘制折线图的方法。


Visdom中,使用函数vis.line绘制折线图,该函数参数表如下——

折线的Y坐标是必要参数。它可以是一个一维数组表示一条直线,也可以是二维数组表示多条折线。该函数的调用可以看示例代码的demo1函数。

line函数还可以设置update参数为’append’。在这种情况下,可以每次只传入新增的数据。示例代码demo2即使一个使用append优化了的绘制深度学习loss函数的例子。

Visdom教程(2):实时展示图片

这是Visdom教程的第二篇文章。主要讲了如何使用Visdom在本地查看服务器上的一个图片。


我们常常使用Visdom实时展示模型训练时刻的图像输出。Visdom支持展示numpy数组形式的若干张图片。展示图片用到了如下两个函数

  • visdom.image(img, win)
  • visdom.images(imgs, win)

第一个函数在win指定的窗口,展示单张图片,而第二个函数则用来展示一系列图片。

  • img是一个表示图片的numpy数组,形状(3,width,height)或者(width,height)形状
  • imgs是表示一系列图片的numpy数组,形状为(batch, 3, width, height)。
  • win表示窗口id,应该可以为任意类型。如果不指定win,服务端将自动新建一个窗口放图片,然后你的浏览器中将堆满密密麻麻的图片窗口。

下面是一个例子——

Visdom教程(1):开启Visdom服务

这是Visdom教程系列文章的第一篇,主要介绍了Visdom的安装。


Visdom是一个Python的远程可视化工具,经常用于配合深度学习训练进行可视化。

Visdom的工作原理是先在远端服务器上面运行一个Server,该服务器将绑定localhost:8097,同时,任意远端运行的Python程序可以通过引入visdom包,实现与该Server的交互。

Visdom服务端假设在服务器上的8097端口,我们只需要执行

安装visdom,并且执行

打开服务端,此时服务端将自动监听8097端口。

下面是一个最简单的visdom程序,该程序在example环境中,新建了一个text_window号窗口,里面写上了Here is the text这句话。

值得注意的是,Visdom中的环境可以理解为工作区,比如一个训练神经网络的程序,训练loss折线图可以输出到train环境中,而模型的内部可视化信息则输出到model环境中。这样可以使我们的工程井井有条。

我们既可以直接通过 server_of_hostname:8097 访问可视化界面,也可以通过ssh命令,将服务器上面的端口映射到本地,并进一步通过 localhost:8097 访问。

ssh name@host.com -p 3522 -L 8097:*:8097 .

 

An Introduction To Compressive Sampling 阅读笔记

通常我们讲的采样都要求采样率至少两倍于带宽,这是香农在1948年就提出了的。而本文讲的则恰恰相反,本文试图介绍如何使用压缩感知(Compressive Sampling/Sencing)的方式,使用尽量少的样本,刻画出信号本身。

从实用性角度来看,尽管本文的所有算法都可以拓展至连续信号,但是本文将单纯讲述离散信号在欠采样时的CS,毕竟这才是对工业界最有意义的。因为在离散前采样的信号中,有一个很重要的问题——

压缩感知的原理

假设有一个离散信号f \in R^n,是否有可能构造出m \ll n个波形,能够“几乎”完整刻画原来f所携带的信息?

首先向讲一讲关于稀疏性(Sparsity)的问题,令f =  \Psi x,其中\Psi是一个n\times n的矩阵。我们可以理解为将f使用特征x进行表征,而倘若我们提取x中前S大的值,而将其他位置强行置0(这样便于压缩,且不会显著对于结果产生影响),则称呼得到的向量x_S为S稀疏向量(S-sparse). 此时,我们可以通过x_S计算出f_S  = \Psi x_S

那么,接下来,m的取指大概为多少可以保证信号能够被“几乎”完整恢复呢?论文通过一系列推导,给出了一个式子

m \geq C \cdot \mu^2(\Phi, \Psi) \cdot S \cdot log n

其中\mu函数表征了感知基\Phi和表征基\Psi的相关程度,S是指x是S-sparse向量,C是某个常数。

而上述公式带入实际的图像压缩中,每一个缺失项倘若对应至少四个不连续的采样点,就能准确恢复原来的图像。

若干难题

文中提出并解决了基于上述算法的两个问题——

  1. 对于极其欠采样的样本,是否可以恢复如此高的分辨率?
  2. 实际的检测设备都存在噪音,噪音将如何影响该算法?

为了解决上述两个问题,作者提出了一个叫做restricted isometry property(RIP)的限制条件,倘若条件满足,不仅欠采样样本可以被完整恢复,而且还可以将误差限制在一个较小的区间中。而RIP的细节这里不叙述。

感知基的选择

感知基选择非常随便,只要满足RIP准则就可以。而文中提到了在单位球体上面随机取点,或者使用标准正交基与一个随机矩阵的乘积生成。

应用

  1. 数据压缩
  2. 信道编码
  3. 数据获取

等等

参考文献

  • E. J. Candès and M. B. Wakin, An introduction to compressive sampling, IEEE Signal Processing Magazine, 21-30, March 2008.

ICMP攻击及防范

ICMP协议概述

IP协议本身无法处理诸如“得到一个包发送失败的事实”,“对网络进行诊断”这些操作。ICMP协议就是为了上述操作而包含在IP协议中的一个子协议。

ICMP协议(Internet Control Message Protocol)全称Internet控制报文协议,是TCP/IP协议族的一个子协议,用于在主机,路由器之间传递控制信息。最常见的是我们使用的ping命令就是通过发送ICMP包实现的。

ICMP包位于IP包内部,ICMP的包头一般来说紧跟着IP包头(通常IP包头为20字节,则ICMP包头从第21字节开始)。

ICMP包包含Type, Code, Checksum和Data域,其中Type指定了ICMP的类别,可大致分为两类——一种是请求及其回应,另一种是错误信息反馈。

以Echo请求为例,一个Type=8的包发向目标IP,如果目标服务器成功收到,回复一个Type=0请求。倘若中间出现路由错误,则中间路由器返回一个Type=3的包。

ICMP攻击及其防范

ICMP攻击有非常多不同的种类,接下来将列举一些常见的攻击。

ICMP隧道

首先讲一讲ping指令的原理,ping指令首先发送一个ICMP的ECHO REQUEST包给目标IP,并在data域包含一个唯一的16位标识符(这个标识符在Linux中是顺序生成的,而在Windows中是随机生成的),通常操作系统还会在data域后面添加一些无用的信息使得ICMP包长到达一个指定的长度。目标主机收到了ping指令后,将data域原封不动包裹在一个ECHO REPLY包中发回来。

对于一个ICMP ECHO REQUEST/REPLY包,由于其做的是类似于网络控制方面的事情,故通常不会被防火墙在意(除非防火墙一一分析每个包的内在data域有没有异常),而其data域可以携带任意的数据,因此可以借助ICMP包实现一个从服务器发送消息的程序。我在github上面也找到了一个实现ICMP隧道的程序,大家可以参考一下。

对于ICMP tunneling的攻击,有一些非常原始的防范方式,包括限制包的大小以及直接丢弃所有的ICMP包。但是在实际上这些方式都不可行。也有一些比较复杂的防范方式,包括在本机监听包,并在发现异常是,通过网络中的控制节点拦截攻击的流量。

DDOS攻击

PING FLOOD攻击

两个对称的主机,攻击者在一个主机上使用多线程发送大量包向目标主机。只要攻击者的主机的带宽大于被攻击者,被攻击者的带宽就会被完全占满,而真正的包无法到达。

对于这类攻击,可以在子网入口的路由器上设置过滤表,拦截攻击者IP。

Smurf攻击

Smurf-attack是一种原始的DOS攻击,攻击者伪造目标主机的IP为source IP,并发送一个广播的ICMP ECHO REQUEST指令。当指令被网络的其他主机回应后,回应的ECHO REPLY将涌入目标主机,导致目标主机瘫痪。

一般Smurf-attack攻击的解决方式有——对于主机,设置相应的网段,不在该网段的ICMP ECHO REQUEST都不会被相应。或者是对于一个子网路由器,丢弃掉发入子网的广播ECHO REQUEST。由于现在新的路由器都默认disable广播流量,因此smurf攻击基本已经成为历史了。

伪造IP的方式不一定在攻击者主机上面实现,比如在 DNS Amplification Attack 攻击中,攻击者可以通过UDP包,将目标主机的真实地址关联一个无关的IP,注入DNS服务器,将大量无关请求全部导向目标主机。

网络信息收集

通过ICMP攻击可以用来收集网络拓扑结构,首先,通过ECHO REQUEST可以探知一个主机的存在性,而通过一个TTL依次递减的一系列ECHO REQUEST包,观察其ICMP Time Exceeded 包的发送源即可获得一条网络的边。

甚至通过ECHO REPLY包,我们还可以探知目标机器的OS类型。返回TTL=128的机器是Windows系的,而TTL=64的机器是Linux系的。同时,对于一个任意Code域非空的ICMP包,Windows系主机将返回一个Code域为0的包,而Linux则不会。进一步,不同的系统版本对于TIMESTAMP REQ包的回应也不尽相同,我们可以借此更进一步确认。

这类行为因为不会造成严重的后果,故一般没有进行防范。

Ping of Death攻击

通过发送若干段IP超大包,并让目标主机接受后,拼接出一个大小超过65536的包,导致栈溢出。这种攻击仅发生在早起服务器上,新的服务器都通过修改其收包算法的边界条件判定解决了这个攻击。

总结

对于ICMP攻击的防范一般都需要用户服务器精细配置防火墙,或是在边界路由器中设置过滤规则。普通的丢弃ICMP包也是可行的,但是会使得很多网络诊断工具不可用。在参考了有限资料后,我认为ICMPv4和ICMPv6在上述攻击的防御上几乎没有区别,ICMPv6协议本身没有增加额外的防范机制的支持。

参考文献

ICMPv4 and ICMPv6: https://notes.shichao.io/tcpv1/ch8/

ICMP attacks:  https://resources.infosecinstitute.com/icmp-attacks/#gref

ICMP tunnels: https://www.notsosecure.com/icmp-tunnels-a-case-study/

ICMP floods: https://www.cloudflare.com/learning/ddos/ping-icmp-flood-ddos-attack/