中伊网战和DNS

今天见识到了国家级的网战较量。结果也不过于DNS攻击和DDOS。

硬件的问题是没办法说了,那个相当于军备竞赛,蛮无聊的说。DNS劫持就比较有趣。毕竟DNS只不过是一个电话簿。攻击了电话簿既没影响网站也没影响用户和中间的信道质量,其实影响力本不会这么大的。要说直接攻击一个网站,要破解服务器密码,或者通过系统漏洞拿到系统操作权限,对于成规模的企业级应用已经相当不易,更不要说国家级网站。不能钓鱼成功或者通过所谓“社会工程学”得到一些情报的话,直接攻破异常困难。像今天这样几个小时搞定一个网站估计是不太现实了。由于DNS服务器不断监听网络DNS报并且不断更新自己数据的这个“易变”的特点,才使得DNS攻击变得异常容易。

其实之前GFW不也是大量采用DNS劫持的手段嘛。那时候我就想过,如果DNS服务器能够分成动态和静态两套互补的体系,则安全性更强不易遭受攻击。(当然政府直接施压你就没辙了。。这个属于“社会工程学”范畴。。)静态DNS是记录长期稳定的DNS路由,不能轻易更新,也不会遭受突如其来的DNS污染。因为新来的DNS不会被他识别为“稳定”的,因此他会拒绝更新。而动态DNS部分则如传统DNS般不断更新。这样一旦出现DNS不稳定的情况,可以通过人工介入的方法(除了可以让管理员手动开启外,也可以考虑让访问用户举报这种方式。但是举报者又可使用DDOS来进行攻击,但攻击结果也不过是转成静态路由而已,对他们的好处不大),强制使用静态路由。当然使用了较为稳定的静态路由的缺点就是速度可能会严重下降。但这也是为了安全性而做的一点牺牲嘛。DNS机制没有仔细研究过,没办法直接在这里提出相应算法和解决方案。不过相信这个思路肯定是可行的。如果研究生期间还没出现类似产品或论文的话,我可以考虑做这方面的研究哈哈。。

另外,除了公共DNS服务可以静态化之外,个人host也可以静态化。这个我也很早就在想了,可惜一直没实际做出来。就是不断读取浏览器访问的域名和IP,然后全都记录下来。一旦发现域名劫持,可以把过去记录下来的域名/IP对导入host中去做一些尝试。一般来讲,封锁IP的速度会慢于域名劫持。所以在域名劫持之后原来的这些IP或许还有可以访问到的。当然啦,如果政府真的下力打击的话,这些IP早晚也还是会封光。。不过,至少。。还有喘息的机会嘛留一丝丝。。

对了对了,补充一点,本地记录IP,对一些公共DNS崩溃造成网络拥堵的情况也能缓解不少问题。甚至每个PC都可以成为一台小型DNS服务器。这样就像p2p的思路一样,大家互帮互助来进行DNS解析。当然大型公共DNS服务还是主力啦。

好吧今天看到DNS争夺战这么激烈,忽然想到以前想过的一些idea,算是做个记录吧。

数格子

我发现程序员最经常干又不太容易弄对的一件事情就是数格子。所以得好好整理一下。。
好吧,也说不上不容易弄对了。。是我智商太低总也弄不对。。。不能因此就认为别人也弄不对。。

举个最简单的例子。你有a个格子,要从第b个开始(包含)连续搬c个,怎么搬。
简单嘛,从b开始,到b+c和a中的较小值(不含)(注意b是从0开始计算的序号,并且0<=b<a ,a和c都是正整数)
搬动的区间是[b,min{b+c,a})

其实a,b,c都是我命名很完好的变量名:allitemNum, begin, count.恰好abc了。不知为何这么巧。

然后遇到一个反过来的例子,就把我搞晕掉了。还是这a个格子,但是这回要从后往前数第b个,连续向前搬c个。
我承认。。这个问题我反复搞错,整整弄了一天时间。。确实是智商有问题吧。。
先找出来这个反过来数到b,他的序号是多少呢?
数到b,所以是b+1个格子。于是前面差了a-(b+1)个格子。这么多格子里面并没有包含反过来数到b的那一个。如果要包含他,还得加一。于是包含反过来数到b的那个格子,从第0个到他,一共是a-(b-1)+1个格子。序号就应该是a-(b-1)+1-1,简单来说就是a-b-1。
(再次承认我肯定是想麻烦了。。不过就是想不明白。。画了好多图了。。哪位智商高的给我指条明路。。)
然后还需找出在向前数c个,那个格子在哪里。
这回好办了,到第b个总共b+1个格子,在向前数c个就是b+c+1个。他的序号是b+c。把这个序号替换掉上面的b就得到a-b-c-1。
要注意上面那个a-b-1这个格子还是要包含的(要搬走的),所以再向后续一个格子。而前面这个起始点,必须比0小。
于是得到搬动的区间是[max{a-b-c-1,0},a-b)

呼,就这么简单的几句话,想了我一整天。。真是糊涂啊糊涂。。而且到现在都想不出合适的理解这些代数的方法。。只能硬推。。肯定是小脑发育不全。。

能记录下来的还有一些可以算是定理的东西吧。就称之为数格子定理好了。

用两个序号相减,得到的是两个序号之间的格子数量,包含前端不含后端。
比如。。8-3=5
0,1,2,[3,4,5,6,7),8,9

因此同理,从某个序号加上一个数量,得到新的序号是包含他自己向后数那么多个的序号,含前端不含后端。

3+5=8
0,1,2,[3,4,5,6,7),8,9
8+(-5)=3
0,1,2,3,(4,5,6,7,8],9

总数量为a的格子里面,b与a-b-1轴对称
10-2-1 = 7
0,1,[2],3,4,5,6,[7],8,9

最后就是编程技巧,要搬格子的话,先算好区间[b,e),之后好办

for(int i = 0; i+b < e; i++){
dest[i] = source[b+i];
}

好吧再次承认这么脑残的东西我也搞不明白实在太傻逼了。。不过咱就是傻逼怎么着了!!
上次还遇到更傻逼的事情

UINT a = 2,b = 3;
if(0<a-b){...}

结果居然这个判断就掉进去了。我百思不得其解。为什么0<-1居然能是true呢,为什么为什么呢。。
终于悟了unsigned int 没有-1, -1是最大值。。。哭死。。果然还是上课没认真听讲下课没好好完成作业啊。。
这也是一个问题,就是格子的序号一般怕太多格子数不完了都用unsigned int的。但是一般也可能会需要用序号相减来计算之间的格子数量的情况。结果这里面就产生了矛盾。当然经常记着去比较一下大小先还是对的。但是那样也还是很麻烦哪。。。

手机的相关知识记录

虽然做了挺长时间手机开发了,对手机的最基本的功能完全没有了解。今天听了公司里面的一个讲座,讲STK的,顺便把SIM卡的功能之类的也一起做了research, 一起贴出来做个总结吧。网上很多资料是有关破解啦之类的邪恶内容,就不记录了,主要以了解大体的功能和原理为主。

手机的基础结构是一个叫做Mobile Equipment(ME)的芯片组和一片SIM卡构成的。它们两个合起来叫做Mobile station(MS)。智能手机处理复杂应用的那个部分,大多数情况使用了另外一片叫做Terminal Equipment(TE)的芯片,计算能力应该比ME来的要强一些。给我的感觉TE的构造就更加近似于PC的CPU了,此外多数智能手机还会有一片显卡芯片。

SIM卡里面也有一个简单的芯片,但是计算功能非常弱,它的功能仅是用于做一些加密计算(稍后提到)和一些简单的逻辑判断。因此基本上来说SIM卡就是一个纯粹的存储装置,没有任何计算和通信功能。打电话发短信上网等等功能,基本上都是ME配合无线设施完成的。

但是为何没有SIM卡就不能打电话发短信呢?这是因为SIM卡里面有一些与手机基站交互的必要信息。手机开机时,会对SIM卡做合法检测。SIM卡内有ICCID和IMSI两个明文信息和ki作为信令加密的密钥。ICCID包含了SIM卡的一些基本信息比如使用的服务类型,国家地区等等,而IMSI是SIM卡的全球唯一标识符。在手机运营商那里,这个标识符跟一个手机号码唯一对应。手机开机时,要对ICCID和IMSI做合法检查,确定SIM卡的合法性。同时将IMSI发送到基站,基站接收到该IMSI后,临时生成一个随机数RAND,发回手机,手机将该RAND传送给SIM卡,SIM卡使用存储在卡中的ki和硬连线在SIM卡中的加密算法,生成一长一短两个密文。分别使用的加密算法称作A3和A8。A3生成的短密文称作SRES,发送回基站,与基站生成的密文进行匹配确定是合法的SIM卡。A8生成的长密文当作接下来通信使用的加密密钥。通信加密将使用A5算法。注意到ki, A3, A8都是硬连线在SIM卡上的,并且运营商对这些信息保密,以防止SIM卡被破解和盗用。而A5算法是在ME上运行的,由于整个通信过程都要持续计算,这个算法必须非常简单,并且为了保证手机可以跨国漫游,这个算法其实是全球统一的。而A3, A8两个算法仅是定义了输入和输出的位数,没有要求加密的规范。各个运营商理论上可以采用各种不同的算法来保证安全性。但是事实上这些算法也有些通用的标准,导致某些SIM卡可以被破解。

由于运营商的惰性,导致事实上采取的A3A5A8算法都有通用算法。虽然这些算法被保密,但A3算法的一部分仍然泄漏,并在研究人员使用SIM卡读卡器,对比已知的明文和密文进行测试,推算出了未泄漏的其余部分。使用已知的算法,使用巧妙设计的输入并分析输出,就有可能破解任何SIM卡上的ki密钥。因此有些SIM卡一卡多号,或者例如iphone手机可以破解后加入到移动网络,就是利用这个漏洞。由于v1版本的A3算法被破解,国外后来又开发了v2版本的加密算法,目前没有泄漏,这种SIM卡就是无法破解的了。但是由于这种算法刚刚研发出来,技术上不稳定,因此国内运营商采取的办法是在v1算法上稍作修改,称作v0算法。此算法避开了原先v1算法被破解的某些漏洞,因此更难破解。但由于原理基本相同,实际上地下仍然有某些破解的办法。对于SIM卡破解的方法,此处不做任何讨论和记录。仅对SIM卡曾被破解的事实作为历史注记在此说明记录。

除此之外,手机启动入网时系统也需要对本机进行检查,手机上有一个设备码IMEI用于发至基站以检测该手机的合法性。

手机与基站通讯,首先手机定时与基站通信,使得基站确定手机的位置,判断手机应该属于哪个服务小区。这里涉及到一个很有趣的算法问题即如何生成Voronoi diagram,即beach-line算法。不在本文议题范围之内。

手机第一次与基站通讯,应该会得到基站的一个RAND并用ki计算出今后加密信道使用的密钥。此外基站会临时生成一个TMSI发送给手机并存储在SIM卡中。此后就不再传输IMSI而仅传输TMSI,避免其他组织个人监听信道频道获取个人信息。TMSI会定时更换以保证安全性(当然这些加密措施仅能阻止第三方的监听,很显然运营商当然能获取所有的通信资料以及手机所在的服务小区,因此有些运营商也提供API允许其他第三方获得这些数据,当然了,这就是出卖你的隐私吧,用手机是没有隐私可言的)。

ME与SIM卡通信采用规定的编码格式,除可从SIM卡中获取相关数据之外,还可通过SIM Application Tool Kit(STK)做其他的应用。比如动感地带SIM卡上自带的动感地带的一些服务,就是通过STK完成的。GSM 2G中的STK协议在GSM 11.14中定义。3G中STK被USIM Application Toolkit(USAT)取代。

由于负责计算和消息传输的都是ME,SIM卡本身存储的都是出场时预先写好的一些目录项和每个目录项对应的功能:例如深入一个子目录,或者接受一个输入框,或者弹出一段文字等。这些功能中如果有对应与基站通讯的,ME就将相应的消息发送的基站,并接受响应。这些相应在智能手机上,可通过TE来显示,可通过各种UI来展示。

好吧,能做的记录就是这些了。接下来还需要研究的内容有单片机的工作原理,ME的结构,手机与基站通信的物理机制,手机GPRS上网的机制,以及GMS,TDMA,CDMA,WCDMA这些网络的异同等问题。以后再慢慢查找资料慢慢做笔记吧。

下面列出引用的网址:wiki的链接已经在文中给出于是不再重列
http://www.moon-soft.com/program/bbs/readelite125680.htm
http://www.52rd.com/Blog/Detail_RD.Blog_xuanny_10418.html
http://ido.thethirdmedia.com/article/frame.aspx?…
http://www.mscbsc.com/27829/viewspace-7105.html

Lippam’s talk, first 5min

Today we will talk about ways of thinking about programming languages that i hope you find it’s interesting. Since it is relatively informal, feel free to ask questions as we go if you like otherwise you can go and all ask the questions later.

The image here is how actually I’d like to think about programming. Here in the middle I think projected two imaginal is real statical in the programming. It’s the elemence that you think you understand the program and the code and you do that on your computer terminal and you write your code. It’s really separated from the runtime of the program. So you do the best of you can imagining how the application should work. but its all that in your code that it’s really not going to change once it actualy executed. It’s a very static way of doing execution.

Lippman's talk in Jiading
Lippman's talk in Jiading

Then you have to work dynamic aspects of the programming. Those little alligators coming all of the program really of the character of the runtime. They go and they use their little movements and they go back to program. And that is more going dynamic aspects of the programming, and more interesting, but also more difficult, because those things are moving around. So you see aspects of code you know runtime and the internet that dynamic and more interesting in a way, and you can interact with the plasticsmatical programing ability to generate code at runtime. but it’s much slower and more challenging to be able to come that way. .NET is trying to do that. Java has the semantic specs in fact.

In c++ we  basicaly donging the part that is rejected. that’s the two imagional code. It’s staticaly runs very fast. so the static program doesn’t really look like that exciting is what the runtime machine runs really fast, and they fly the alligators and they think they’d like to get to. but its hard to know how to do that in the time frank. That let us get the result fast enough.

So a lot of more people is trying to do is geting the alligators walking around, and find out what it’s thinking trying to keep them fed and played. But a lot more actually hasn’t be done waiting for you actually run you program is not much you can do about it. So when you see in c++ program really there is nothing you can find out about program when it’s executed. You can find out the machine. You can always break through a c++ program and get access to the registers and memory. But you can’t really get access to the runtime. There is no way of doing that. We invented in c++, the ideas of runtime programming and meta programming and finding out about the code and  generating code. That really was feasible. In the late of the last ten years or so, you know .NET and java is in a movement that try to have more dynamic language. But problem is that they runs very slow and nobody is quite sure how to do it.

So in the sense we have transition that you keep just entering into in terms of programing because what we really like to be able to do is to have programs bodyfy and change themselves as the behavoir of the program goes to look more like living things, if you will. And I think it’s where the programming has to move but we don’t quite have to do it fast enough time in order to get the results or something in cooking.

today we will talk about ways of thinking about programming languages that i hope you find it’s interesting.
since it is relatively informal feel free to ask questions as we go if you like otherwise you can go and all ask the
questions later.
the image here is how actually I’d like to think about programming.
here in the middle i think projected two “imagional” is the very statical in the programming
it’s the “elamence” that you think you understand the program and the code and you do that on your computer terminal and
you write your code.it’s really seperated from the runtime of the program. So you do the best of you can imagining how
the application should work. but its all that in your code that it’s really not going to change once it actualy executed.
it’s a very static way of doing execution. then you have to work dynamic aspects of the programming.those little
alligators coming all of the program really of the character of the runtime. they go and they use their little movements
and they go back to program. and that is more going dynamic aspects of the programming,and more interesting. but also
more difficult because those things are moving around. so you see aspects of code you know runtime and the internet that
dynamic and more interesting in a way. and you can interact with the “platismatical” programing ability to generate code
at runtime. but it’s much slower and more challenging to be able to come that way.
.NET is trying to do that.java has the “synmatics specs” in fact.
in c++ we  basicaly donging the part that is rejected. that’s the two imagional code.
it’s staticaly runs very fast. so the static program doesn’t really look like that exciting is what the runtime machine
runs really fast and the “fly the alligators” and they think they’d like to get to. but its hard to know how to do that
in the time frank.that let us get the result fast enough.ok.
so a lot of more people is trying to do is geting the alligators walking around. and find out what it’s thinking trying
to keep them fed and played.
but a lot more actually hasn’t be done waiting for you actually run you program is not much you can do about it.
so when you see in c++ program really there is nothing you can find out about program when it’s executed.you can find out
the machine.you can always break through a c++ program and get access to the registers and memory.
but you can’t really get access to the runtime.there is no way of doing that.
we invented in c++, the ideas of runtime programming and meta programming and finding out about the code and  generating
code.that really was “feasible”. in the late of the last ten years or so, you know .NET and java is in a movement that
try to have more dynamic language. but problem is that they runs very slow. and nobody is quite sure how to do it.
so in the sense we have transation that you keep just entering into in terms of programing
because what we really like to be able to do is to have programs bodyfy and change themselves as the behavoir of the
program goes to look more like living things, if you will.
and I think it’s where the programming has to move but we don’t quite have to do it fast enough time
in order to get the results or something in “cookin”.

由于前面的几分钟没有PPT说明,听起来有点费劲,又是比较重要的开场白部分,就凑合着搞个字幕。。不过实在是听力有限单词量有限,尤其是灰色部分就是不知道了把发音乱标在那里。凑合可以看看就是了。

他后面就由此引起语言的发展历程了,最后加上对未来语言的猜测。

语言之争-学院派vs实用派

因为Lippman的来访,最近在bbs上跟同学聊语言的发展和竞争的问题,做个记录吧

首先用Lippman本人的话讲,语言最开始是纯应用的,是工业产物。是一种为了解决实际问题而产生的东西,他是bottom-up的,是哥白尼式的。而后来在语言的研究和发展中,学院派从纯粹理性的角度提出了完美的语言模型,比如OO、GP、函数式语言等。这些语言模型是直接从完美的模型角度出发向下设计的,是top-down的,因此往往缺乏实用能力,甚至无法直接编译成机器码(因为从设计的时候就没考虑过如何把这些语言的逻辑翻译成冯诺伊曼结构的通用机器的语言模型这些问题),只好运行在中间平台上(虚拟机之类),从实用主义的角度来说是完全不在上风的。但是由于他们的结构精妙,模型完美,在语言发展的领域做出的贡献则远远超过哥白尼式的语言,Lippman称他们为亚里士多德式的。

工业语言的代表有C/C++, Java, FORTRAN等,学院派语言的代表有smalltalk, lisp, scheme之类。

当然我们的讨论其实是集中在C,C++和Java这里了,因为很显然其他的语言接触的不多,有些仅是耳闻,还有不少根本没听说过,更无可讨论了。我们讨论的主要是从学院派/实用派的角度分析C,C++和Java的利弊取舍问题,而又以关注C++为主。

C是一门工业语言。他原本就是为了更好的服务Unix的迁移而编写的。但贝尔实验室的大牛们显然不乏学术实力,创造的实用工具都是如此的简单和纯粹。加之Unix的成功和推广和C的可移植能力,C在众多语言中脱颖而出成为一门伟大的语言,应是顺水推舟。并且C原本就是为了方便的翻译成机器码而设计的,他的编程范式完全遵循冯诺伊曼结构的机器模型,他的语法规则简单,也容易为他的代码写各种解析器来做自动生成代码等辅助工作。从我现在的眼光来看C真的是一门可以永垂不朽的语言。当然是在计算机模型不变的前提下啦。。
应该说C的设计是自然的,这正是他最成功和最合理的地方。学习C,除了学习计算机原理,体系架构和算法数据结构这些最基本的计算机理论之外,不需要任何额外的知识。对于他是用机器自身最自然最直接最根本的方式去操作机器。同时他又有着良好的形式定义,使人容易理解(不像汇编那么艰深)。这就好像老子说的无为而治,道法自然。如果人类的道要效法自然,编程的道就应该效法计算机模型。这正是他让人愿意接受的主要原因。

C++就不同了。自从smalltalk向程序世界引入了OO这种新的思想之后,淳朴简约的古风不再。C++是尝试在C的基础上,在不牺牲目标代码效率的前提下,尽可能的加入新的编程范式。最早是OO,之后是异常机制,GP,C++0x引入了lambda等,未来还有可能加入更多。多元化的编程范式带来的是丰富多彩的变化和无限的可能性。但是也带来了风险、不确定性和误解。Lippman在做讲座的时候说,写代码就是犯错误,写的代码越多,犯的错误也就越多。更多的可能性,就意味着更多不同种类的错误,更多不容易发现的bug,更多的未知领域。因此尽管C++为工业带来了许多机会和希望,最终却被工业放弃。
OwnWaterloo说,其实C++并非不适合工业,毕竟他不过是C的升级版嘛。只不过是C++的气氛太浮躁了,太花哨了,总是想尝试引入各种新技术新功能。结果反而自食其果。假如能去除这些浮躁,仅仅使用C,而非到迫不得已的时候,迫不得已,才使用C++的新功能,或许就能得到成功。但问题是,仅从实现角度,没有什么迫不得已的,毕竟C++能实现的功能,C都能用其它方式实现嘛,不过是或许代码丑陋一点没有那么花哨就是了。C++的目的是减轻程序员的负担,可以通过类的派生多态,模板的反复重载来实现最大程度的复用。然而如果这些复用的结果是导致程序员的负担越来越重,那就得不偿失了。

唉没想到最近事情好多啊,一篇博客都写不完。本来还想要记录关于Java的讨论的。。结果都这么多天了都抽不出空。干脆先这么发出去吧。以后有想法再另起一篇算了。