Shell's Home

May 5, 2015 - 1 minute read - Comments

电池标注不好,你上不了飞机

问个问题。谁知道锂电池上飞机的标准。 我在这个页面找到了解释。这是首都机场的主页,还是比较可信的。 单块电池能量应小于100Wh。100-160Wh的电池需要航空公司批准,160Wh以上的不得上飞机(其实可以按照危险物品托运)。 在飞机上的锂离子电池,应当随身携带,不应当托运。做好绝缘隔离保护,不要在飞行过程中充电。 电池总量应小于160Wh(关于这点我不确定,规定相当含糊,解读也可能完全不同)。 OK,上面的事情很多人可能都知道。所以呢?这篇文章重点在哪里? 按照普通锂电池放电电压3.7V计算,100Wh的锂电池大约合27000mAh。目前主流的两万毫安时电池还不足以达到这个标准,但是看起来很快了。最大能带上飞机的电池规格,应该是25000mAh这个级别。 按照这篇注解。如果你的锂电池没有标明能量,也没有标明放电电压,只有一个电池容量。是不能上飞机的。哪怕只有1000mAh,没有标注放电电压的电池,从标准执行可能性上就会被没收。 2也许出乎很多人意料外。1000mAh的电池,要满足100Wh标准,其放电电压需要高达100V。目前好像没有任何一种材料的放电电压能达到这么高(变压转换除外)。但是在执行上,硬生生就成了二等公民。 电池的要点并不在2W mAh,而是标注。因此买电池的时候,请注意电池外壳上是否带有清晰的容量标注。 当然,很多机场是压根不执行这么严密的限定的。如果你对这点很有信心,那不妨当我没说。但是这次在太原武宿机场,就正好碰到了这待遇。 笔记本电池电量大的多,更容易碰触到100Wh的限制(例如我的笔记本,三芯电池60Wh,六芯多数就要超标了)。这种情况下,万一不让上飞机很麻烦。考虑到这点,如果你要新买笔记本的话,建议你买一个电池能量100Wh以下的。

Apr 22, 2015 - 1 minute read - Comments

python代码写给你看 [广告]

最近有个朋友问我有没有意向写点和python有关的东西。我说没啥想法。要入门,看dive into python足矣。要学最准确的用法,当然是看python manual。两者都有很不错的中译本了,我还有什么可写的呢。朋友说看了这俩可不代表会写程序啊。我说要真的学会,你只有亲自来看我是怎么写的了。朋友说正好,我们这里就是录电子课程的。。。 所以我就录了这份python代码写给你看。其实录的很粗疏,并不适合纯粹的初学者。因为里面并没有“讲解”python是什么,print是什么,对象是什么。这些东西基本都是在课程中随口提到的。如果没有看过入门书的人,直接看视频的结果就是看一个点卡一个点。也因此,我只推荐“看完了python入门书”,希望“能够像真正的python程序员一样工作”的人来看。 同时,这份视频在求解的时候经常思路卡在那里。因为我追求“必须让观看者看到我真实的代码过程”,所以里面的大部分问题,并没有提前准备过程。我觉得,提前把代码写好,然后到录的时候咔咔敲出来,漂亮是漂亮了,还不如让你直接看源码来的方便。这里的很多问题,我都是当场推论如何解决的。有些问题甚至上来思路错了。但是我觉得这些都不重要。我觉得看到如何使用各种手段去发现,改正错误,比看到正确的代码更有用。 录到最后。我和朋友说,我觉得不能再录下去了。整个视频里提供的问题已经太凌乱没有体系了,再录下去就变成了“现场用python解决各种奇怪问题的,没有人看的大杂烩集合”了。谁愿意总是看一个胖子程序员在那里唠叨一堆问题他是怎么解决的呢?但是我又不大满意。仅仅这里提供的几个例子,并不能完整的反映一个python程序员日常工作中碰到的各种问题和如何解决。比起上百小时的实际工作来说,录像能提供的时间无疑太短了。 无论如何,我最终决定,还是把现在的工作放在这里,放给大家看。希望能够成为大家在python入门之路上的,一颗微不足道的小石子。也希望将来,我能为这份教程去芜存菁。 请大家批评指正,谢谢。 PS:音量的问题就别吐槽了。我们设法改善了几次,最后发现有很多听不清的内容是因为我的“小黄鸭调试法”。简单来说就是没思路的时候就开始自言自语,描述一个个部分的用途,试图发现里面的问题。结果这些自言自语变成了背景里的念经。。。 也许下会我会专门录个“shell读kernel”当睡前读物录音。因为那会更加的颠三倒四语无伦次。。。

Apr 21, 2015 - 1 minute read - Comments

ppa的使用

最近用ppa做了backport,这里记录一下用法。 编译简述 ppa的大概工作原理,和mentors非常类似。 包一个deb包,然后build这个包,生成dsc,deb,build和changes。 上传这些文件,然后ppa丢弃所有deb(是的,ppa不接受编译好的包,因为可能在编译过程中被做手脚),从源码编译所有文件。 ppa生成了一堆deb文件,并丢到一个特别的目录下。 ppa为这堆deb文件做签署。 最终用户将这个目录添加到apt源中,就可以安装这些包了。 这里有几个细节: 服务器怎么知道是你上传的包? 答案是在打包时进行签署,所以dput是不验证身份的。也因此,你需要将自己的gpg key上传到服务器。 既然不需要deb,如何构建一个没有deb的编译? 答案是debuild -S。当然,这也可能有变化。如果是建立一个已经存在的包,是-sd,否则是sa。后面还可以用-k\来指定 最终用户如何构建信任? 答案是由ppa编译,由ppa签署。用户并不导入维护者的任何key。但是如果用户不信任维护者,那么维护者可以在包内夹杂任何恶意代码。因此ppa只解决安全传递和构建,而不解决维护者信任问题。 申请ppa 不废话,自己去launchpad申请。这个是要ubuntu one帐号的,然后openid认证。不过不算太麻烦。 添加key 首先需要生成gpgkey,这里不解释如何生成key pair。 然后需要将key pair上传到ubuntu key server。我不知道其他key server最终会不会同步,但是即使会,同步时间也是长的那啥。 gpg --keyserver keyserver.ubuntu.com -send <keyid> 这样就行了。 设定dput 在这个页面有解释。在ubuntu 9.10以上版本,可以直接dput ppa:userid/ppa <source.changes>来上传。如果是更老版本(或者像我一样用debian),可以设定~/.dput.cf来工作(刚刚的页面下面有样例,照着改就行)。 添加ppa 使用add-apt-repository ppa:userid/ppa就行了。本质上,他做了两件事。 在/etc/apt/sources.list.d/下面生成一个文件,将你的repository添加到系统中。 将ppa的sign key导入到系统中,并添加信任。

Mar 24, 2015 - 1 minute read - Comments

EFI和GPT的研究

EFI和GPT的关系 关于EFI和GPT的解释我就不说了,相信来看我blog的人应该能自己搜到。 关于两者的关系,我简要点说吧。如果你需要用EFI引导,你就应该用GPT分区。如果你需要用GPT分区,你就应该用EFI引导。反之交叉组合,不一定会失败,但是折腾和兼容性不保证是必然的。从这两年的经验上看,越来越多的系统开始支持EFI+GPT模式的组合。所以大家可以提前演练一下EFI+GPT模式引导。 GPT和MBR分区互换 在windows下可以用磁盘管理器直接换,在linux下可以用parted或者gdisk来做。当然,如果你有图形界面,可以上gparted这个神器。非常好用。 linux下用parted更换分区表的方法[1]: # parted /dev/sdd GNU Parted 3.1 Using /dev/sdd Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) mklabel New disk label type? gpt (parted) 但是目前我看到的可靠转换方案,都是在无数据情况下进行分区表互换。带数据转换有很多前置条件,而且肯定有风险。所以建议初始化硬盘的时候搞,不然后面可能代价很高。 GPT分区的划分要求 GPT有很多优势,例如没有主分区和扩展分区的区别,硬盘大小可以超过2T,分区可以打很多flags,等等。但是使用GPT也不是说全无要求。基础来说,GPT分区划分有几个建议。 第一个分区划分为EFI分区,并且保留至少20M,推荐100M的大小。 第二个分区划分为GPT分区,保留同上。 其他分区安装使用频繁程度和大小从前向后装。 1是因为EFI推荐为第一个分区。3是因为万一你需要为某个分区扩展大小,你当然希望移动比较小的分区。 EFI引导 终于到了今天的重头戏,EFI引导。EFI+GPT模式下,引导变得异常简单,多重引导的支持也非常容易。大家再也不用去抢MBR了。 在linux下,有个工具叫做efibootmgr,可以man一下看文档。简单来说,这货有三个功能。 efibootmgr -v,查看当前引导表项。 efibootmgr -c,增加引导表项。 efibootmgr -B,删除引导表项。 至于引导表项,具体是什么呢?简单点说,就是某硬盘的某分区,分区ID多少多少,上面的某路径下,有个按照EFI规范写的文件,你给我引导起来。就这么简单。 当然,EFI认识的文件系统格式比较少,我确定的只有FAT一种。但是好在EFI文件引导起来后,后面跑什么文件系统就无关了。所以这也是为什么有EFI分区的原因。这个分区以FAT格式化,然后所有的启动管理器都安装在上面(其实就是放了一个文件)。最后加一个表项就可以引导了。 通常情况下,linux下由grub-efi这个包来提供这个efi文件。当efi文件被引导后,会找到boot分区,并且加载上面的grub主程序和附加模块。最后进入grub主系统。我查看了一下,在我的系统上(debian jessie, 2015-03-24),efi被挂载到/boot/efi,而efi文件在/boot/efi/EFI/debian/grubx64.efi,大小为119808字节。 硬盘安装windows 上面说了这么多EFI有关的东西,下面说说贝壳最近的烦恼。 最近换了一台机器,挺不错的。但是由于机箱小,所以硬盘拆卸困难,基本就当作内置硬盘了。所以把硬盘拆下来安装系统就做不到了。同时又没有光驱。所以安装系统的方案只有U盘一种。 当然,对于linux来说,这都不是事。debian很快就安装完成,整个系统的重初始化没用两个小时。但是windows上就卡壳了。Windows7不支持dd到U盘引导,而微软推出的iso to udisk工具理所当然的只能跑在windows下——可当时所有windows实例都挂了正在重装中。 所以我就借了一个USB光驱来装系统,然后发现另一个悲剧的事实。当初为了多引导方便,使用了GPT分区模式。而Windows的安装,居然是EFI引导才能往GPT上装,BIOS引导只能往MBR上装。这个为了防错的愚蠢设计的结果就是,Windows7的原始安装光盘,只要从光驱一引导,就必定只能装到MBR上。。。 当然,后面介绍的内容,可以帮助你推理出如何修改安装光盘,来实现EFI下的ISO引导。不过这种事情对当时的我一点帮助都没有。 所以核心问题就是EFI引导了。于是,我开始了上面的研究。而研究完EFI引导,我发现——其实好像连U盘都不用的。因为本质来说,Windows的安装程序也是一个Windows。我只需要分一个FAT的分区,把安装程序丢上去,然后设法添加一项EFI表项,指向正确的EFI加载文件即可。有一份如何制作EFI引导的U盘的文档也支持我这个想法[2]。

Feb 26, 2015 - 1 minute read - Comments

FIN-WAIT-1的问题一例

这是一个早应该知道的事情。但是还是被整了半天。 引子 tcp关闭时有多少个状态? 当当,别数了,应该是6个,不算CLOSED。分别是FIN-WAIT-1/FIN-WAIT-2,CLOSING, TIME_WAIT, CLOSE_WAIT,LAST_ACK。如果不能瞬间想起一个方块来,说明tcp状态不算熟。 问题 今天的故事来自今天BI同事提出的一个问题。在线上,他发现这么一个现象。在一组系统中,客户端全都FIN-WAIT-1了,但是服务器还是ESTAB。 我的第一反应很简单,这明显差了一个FIN包的距离。而且鉴于两者在同一网络中,而且重复出现。建议他首先排查中间的防火墙设备和防火墙设置。 会找上我的问题,当然没这么简单。中间没有任何防火墙或软件防火墙设定。 分析 下一步呢?有点没方向了。抓包分析。发现FIN端向ESTAB端不停的发起ACK,但是看起来和FIN没什么太大关系。 偶然,同事注意到所有出现现象的链接都有写缓冲区数据。这是一个不常见的现象。写缓冲区一般会有点数据,但是应该很快就被消费,而不会长期堆积,更不会长期维持同样的数字。这是写缓冲区满。结合刚刚的ACK,其实本质是对端停止消费数据。 这是一个TCP的边角。当读缓冲区满的时候,tcp协议栈会声明window=0。当读缓冲区恢复的时候,读方会用ack with window来重新宣告可用缓冲区。但是在tcp里,ack是不重传的。所以这个ack会丢失。因此写方有责任定期请求确认读方window,来确定整个过程不会卡死。这就是刚刚看到的不停ACK的现象。 而这里就有个非常重要的可能性——FIN包的处理方式。为此我阅读了源码。源码告诉我们,FIN包被接收到的时候,并不是即时处理的。实际上,在ESTAB状态收到的FIN,正常path下会进入tcp_data_queue。这个函数会将包堆积到队列中,并根据当前seq来处理包。主要包括三种seq,当前包,过去包,未来包。只有在以下两种情况下,fin包才会被处理: 当前收到一个fin包。 当前收到一个包,完成处理后out of order队列中有数据,因而进入tcp_ofo_queue。而队列中有fin包。 而不幸的是,当前包处理流程第一步就是判断tcp_receive_window。如果没空间了,会进入out_of_window过程。后者会快速的触发一个ack返回,然后就把包给丢了。 我猜对了开头,可是没有猜到结局。 结论 通过python的快速复现,验证了这个结论。建立一对连接,其中一个不接收任何数据,而其中一个发送足够长的数据。当读缓冲区满后,再去close,出现一端FIN-WAIT-1,一端ESTAB的现象。 因此,结论如下: 当写缓冲区满之后,收到的fin包会被丢弃,而发送端并不会重发。而只要写缓冲还有剩余空间,哪怕一个字节,都可以正常处理。 内核参数 根据文档,可能有几个内核参数与此有关。 net.ipv4.tcp_max_orphans net.ipv4.tcp_orphan_retries 测试表明,net.ipv4.tcp_max_orphans可以抑制这个现象。当减低这个数值后,再进入FIN-WAIT-1状态的连接会自动消失。ss -natp不能看到连接。有趣的是,如果进程尚未关闭的话,可以在/proc/[pid]/fd下面看到fd仍然存在,而且还可以读出数据。 抓包表明,连接实际是被一个RST干掉的。阅读源码,在tcp_close的最后部分,可以看到tcp_too_many_orphans被调用了。如果超过限制,就会发出reset,并且关闭连接。 而tcp_orphan_retirs,根据我的理解和测试,和这事没有关系。这主要是指这么一种现象:当对端机器poweroff(而不是shutdown)的情况下,你所发出的报文会丢失。因此理所当然的,写者的写缓冲区会很快充满。此时会发起连接探测,以确定对方是不是掉线了。套在close的这个case上,就是一边是FIN-WAIT-1,另一边死不响应。需要通过多次探测来宣告对方死亡。因此,如果对方机器死机导致不响应你的FIN,才是用tcp_orphan_retirs的场合。

Feb 9, 2015 - 1 minute read - Comments

p2p vpn的部署方法

p2p vpn的基本概念 p2p vpn这个概念的提出,是因为openvpn在数据传输上的一个特性——虚拟链路都是从拨入端到服务器的。例如vpn网关在北美,上海电信的两个人要通讯,数据就要从北美绕一圈。这个特性在多节点打通上无疑很扯,于是催生了很多p2p vpn。他们的基本理念是——尽力从端到端,不成再绕。而且为了解决端到端,顺便得解决NAT问题——也就是带有STUN打洞。 tun模式的三层转发表 先说明一点,大部分p2p vpn都是tun模式。这也很正常,tunnel用的么。但是大家在配置openvpn的时候,不知是否注意过iroute这个指令。为什么会有iroute指令的存在? tun模式是三层模式,相信大家都有数。也就是说,报文传递的时候只带有三层地址,openvpn也凭借三层地址来找到要转发给谁。这里和普通的网络就显示出区别了——普通网络使用ARP协议来自管理转发规则,而openvpn则是凭借内部写好的转发表。 例如vpn gateway的虚地址是192.168.100.1,节点1是100.5,节点2是100.10。那么节点2发送报文给节点1时,报文大约长这个样子。 192.168.100.10 -> 192.168.100.5 在普通网络中,第一步会查路由表,确定是eth0(虚拟网络是tun0)。然后在上面广播ARP请求,获得MAC地址。最后填写MAC地址,发送报文。但是在tun虚拟网络中,仔细看你的路由表,是不是整个虚网络都被交给了一个叫做100.4之类的奇怪gateway转发?甚至如果你没有打开client-to-client,整个虚网络只有一台可见,这台还是交给这个gateway转发的。 这是因为你到这个奇怪的IP之间还是走ARP过程,但是这个奇怪的IP收到你的报文后,就可以是纯三层过程了。你可以把这个IP视为本地openvpn的化身。openvpn会把你的报文发送到openvpn gateway,然后openvpn gateway再转发给正确的机器。也就是说,openvpn gateway必须知道某个目标IP需要转给哪个节点,物理地址多少,对吧? 作为纯虚网络,知道节点的IP很容易——毕竟是openvpn gateway管理的地址分配过程。但是作为tunnel和多地址打通,这里就有点困难了。例如节点1还有个网段是192.168.80.0/24,节点2还有个网段是192.168.60.0/24,那么如下一个报文从节点2中出去,你让openvpn gateway怎么办? 192.168.60.15 -> 192.168.80.15 你也许会说,我当然有配节点1的网关转给openvpn的拨入端。问题是,这个动作,openvpn的拨入端尚且不知,何况openvpn gateway?于是我们派生了route/iroute这两个指令。 route/iroute表示这个地址段归属于这个节点所有,区别在于route同时修改路由表,而iroute不修改路由表。配合push,可以由服务器端下发指令修改客户端路由表。 p2p vpn也有类似的问题。甚至,由于没有统一配置端,因此连每个节点的虚IP都不能很容易的得到。在配置中必须注意这点。 n2n n2n的模式比较简单,也比较有局限性。基本分为两个端,supernode和edge。supernode类似于hub,把所有edge拉到一起。edge都是对等的。 supernode: supernode -l port edge: edge -a [address] -c [name] -k [password] -l [supernode:port] -u [userid] -g [groupid] 解释一下。开一个supernode,不用做任何设定。反正supernode也不会持有edge别的信息。edge要设定supernode的ip和端口,然后提交name和password。name和password相同的,就进入同一个虚拟网络。然后自己的虚拟ip是address。最后的userid和groupid必须是数字。主要是因为开tun需要root权限,因此可以在获得完权限后退化成普通用户,以防权限太高。 这里好玩的就是,理论上address可以天南海北,完全不用管路由怎么走。甚至172.16.0.1可以和10.0.0.1通讯(我没实际确认)。因为大家都是看彼此的IP是否经过注册,而不是计算路由表。 但是这里就有个缺点,我看到man文档中只提到address,没提到可以提交一个网段。所以无论我怎么设定,使用三层方案做隧道的时候,n2n是转不过去的。因为他不知道这个网段归哪个节点管。 所以,n2n的p2p模式很便利,但是没法打tunnel(至少我不知道怎么玩)。 tinc tinc和n2n一样,也是一种p2p vpn。不过好处在于,tinc允许你在一个节点上配置多个网络,因此可以打tunnel。 在配置之前,我先约定两个词。“配置名”和“节点名”。一个配置是接入同一个网络的多个节点,还有他们如何拓扑。节点名就是一个节点的名字。所以,和配置有关的有以下两个。 /etc/tinc/nets.boot: 这里写上想自动启用的配置的名字 /etc/tinc/[configname]: 配置的根路径,以下路径全是相对路径。 配置 下面就是某个配置中的一堆文件。注意这些配置都是配置自己节点的属性信息。 tinc.conf: Name = [nodename] Device = /dev/net/tun ConnectTo = xxx tinc-up:

Feb 4, 2015 - 1 minute read - Comments

openvpn的几种基本模式

vpn的原始模式 vpn的最简模型,相当于在两台机器上插一块虚拟网卡,然后中间连一根虚拟网线连通。因此vpn才得名vpn(virtual private network)。 其复杂之处在于,这块虚拟网卡如何配置网络,和别的网卡是什么关系。再加上多个节点间如何通讯。种种都够新手喝一壶。 虽然openvpn在科学上网上是废了,但是在不出国的网络上用来保护通讯,还是非常好用的。 tap模式 tap模式的特点是二层打通。典型场景是从外部打一条隧道到本地网络。进来的机器就像本地的机器一样参与通讯,你分毫看不出这些机器是在远程。 优点: 配置简单。 不需要在所有机器上配置或者动网关。 缺点: tap在部分设备上不支持(例如移动设备)。 wlan加入网桥后不一定可以工作。 广播包会散发到虚拟网络中,可能极大消耗流量。 特别解说一下wlan。部分AP对一个客户只接受一个MAC地址,因此无法做网桥。这应该是wifi网络的常规问题了。解决方法是换AP,或者做mac-nat。 操作方法: 你需要先在当前网络中,为vpn预留一些地址。这些地址应该足够拨入用户使用,不应和dhcp撞车,不应有其他人使用。 而后,建立一个br,将当前工作的eth迁移过去。(具体细节就不说了,每个系统小有差别)再建立一个tap vpn,在启动脚本中指定加入这个br。 example 假定内网地址为172.19.0.0/24,其中保留172.19.0.16-172.19.0.31供vpn使用。 服务器配置: port [port num] proto udp ; 参考我上一篇[vpn不要走tcp协议](http://blog.shell909090.org/blog/archives/2722) dev tap ca ca.crt cert server.crt key server.key server-bridge 172.19.0.16 255.255.255.0 172.19.0.17 172.19.0.31 ; 或者可以采用这句 ; server 172.19.0.16 255.255.255.240 ; 注意掩码实际上等于/28,做掩码运算后,这段地址和上面的保留地址重合 script-security 2 up vpn-start ; 建议使用绝对路径,避免版本坑 down vpn-stop vpn-start: brctl add br0 $dev vpn-stop:

Feb 2, 2015 - 1 minute read - Comments

vpn不要走tcp协议

和大家唠叨一件小事。 vpn不要走tcp协议。 我原本以为这是个常识。因为当网络发生丢包时,vpn的那个tcp会等到超时,然后重发。但是vpn里面封装的tcp链路多半也超时了,也要重发。所以一旦发生丢包,整个链路上就会突然一下子变拥堵了。 那么能不能调整链路超时重发机制呢?这个比较困难。链路的超时重发是靠RTT(round-trip time)来工作的,因此VPN的RTT一定小于里面所封装tcp的RTT。如果你的vpn工作在一根很好的链路上,而tcp链路的对端要通过一个延迟非常高的网络。那么vpn的重发对tcp链路的影响并不大。但是我看到的大部分情况下,vpn是穿越互联网(而且大多是跨国或者跨洲网络)的,而vpn的双端都落在内部网络里。因此vpn构成延迟主体。这时候,vpn的RTT和里面所封装tcp的RTT几乎相差无几,两者会几乎同时超时。 什么时候会发生丢包呢?最常见的理由是带宽跑满。当路由器来不及处理数据的时候,就只有丢包了。例如某出国网络丢包三成,这就是拥塞爆了。当然我们也不否认其他理由,例如无线,天生就是有丢包的。即便没有上述理由,有的时候就是运气不好,无理由的发生一下丢包,也完全不需要奇怪。 所以,在大部分网络上,丢包是常态。而丢包后,内外两层tcp同时超时会引起严重的重传问题。所以tcp协议不是特别适合做vpn。 结果某vpn居然被配置到了tcp模式,而且还不能改。。。郁闷啊。。。

Jan 27, 2015 - 1 minute read - Comments

Charlie and Dave

公司希望弄一套双授权的安全系统,老大提供了一套算法,求大家review。如果这个方案确实可行,那么我们会做完然后开源出来给大家用。 Author and License Author: 韩拓 保留所有权利 All Rights Reserved 以下内容不以cc-by-sa3.0发布。(因为根本不是我的创作) 场景 Alice希望登录到Bob上执行操作。 两者的基本控制协议为ssh。 假定 攻击者名叫Mallory。 如果Alice的私钥泄漏,管理者必须有权停止Alice到Bob的访问而不需要更换所有Bob的公钥。 除去Alice和Bob外,参与通讯过程的所有机器(即下文中的Charlie和Dave)中可能随机被攻破一台。 服务都在内网,但是如果网关和被攻破的机器是同类系统,Mallory即可具有内网监听和伪造数据报文的权限。 Alice不会利用获得的Bob的权限故意执行危害性指令(但是可能被诱骗)。 Alice和Bob不会被攻破。 方案 假定有两台机器,Charlie和Dave,Dave和网关不得是同类系统。根据假定4,两台机器不会同时被攻破。 Alice通过SSL和Dave建立连接,上报自己的用户名,需要访问的设备和帐号,并提交一个临时生成的ssh pubkey(username, account, host, pubkey)。 Dave根据预先设的IP-username-sslkey验证用户身份为Alice,并且根据ACL确认其具有访问权限。 如果通过验证,那么Dave用自己的key,通过SSL联系Bob上的某个程序,将Alice的pubkey提交到Bob的合适帐号上(account, pubkey)。 Bob通过sslkey验证提交者确系Dave,将pubkey临时加入account中。 Bob完成此事后,通过Dave向Alice返回成功。 Alice通过SSL和Charlie联系,上报自己的(username, account, host)。 Charlie根据预设的IP-username-sslkey验证用户身份为Alice,并且根据ACL确认其具有访问权限。 如果通过验证,那么Charlie用自己的key,通过SSL联系Bob上某个程序,为Alice开通到Bob的22端口的tcp盲转发。 Alice利用开启的tcp通道,和自己的临时ssh private key验证登录Bob。 在Alice连接Bob上的程序后,删除alice留在Bob上的临时pubkey。 验证 假定Charlie被攻破。 方案1-5没有影响。 Charlie拥有能够在任意一台机器上开启盲转发的权限。 但是Charlie并不能影响Dave去添加pubkey。 假定Dave被攻破。 Dave拥有在任意一台机器上添加pubkey的权限。 但是Dave并不具有打开到任意一台机器ssh端口的权限。

Jan 5, 2015 - 1 minute read - Comments

无题

路过南京,突然想起前几年在狮子桥吃的鸭血粉丝汤。什么味道其实已经忘了,只是在干完了活后等火车回上海。看时间,与其在火车站无聊还不如在狮子桥吃点东西。 其实这不是我头一回吃这家。刚毕业的时候,没钱,但是又想出去玩。于是就一个人去了南京。那时南京倒是还有个朋友,可是我放假的时候人家也放假,所以还是一个人在南京到处跑。有天晚上,就是在狮子桥吃的晚饭。同样的店,同样的座位。 我已经想不起来两次看到的景观有什么细微的差别。大概来说,无非就是几个消防栓什么的。但是几年间,他们居然没有什么太大变化。 我又想起了外婆家,我长大的地方。从大体上看,好像也没什么太多的变化。但是细微处还是变了。我结婚搬了出去,外公也走了,留外婆一人独住。于是,很多东西都开始凑合了起来。原本电饭锅坏了大概是会去换一个的,现在也懒得换了。冰箱里也塞满了隔夜菜,有些甚至会隔月。 有形的东西总是会坏的,无形的东西总是会被忘记的。无论什么,消失才是大多数的宿命。和宇宙比起来,这地球只能算是沧海一粟。和时间比起来,人的生命只不过是白驹过隙。就在这小小的地球上,有多少匹白驹曾经越过溪水呢?你记住了几匹?又有几匹,曾经看到过我看的东西。狮子桥的消防栓,我的博客,火车站的长椅。他们总也有坏掉的一天,也有被人忘记得一天。记得他们的人,也有离去的一天,写下他们的文字,总有丢失的一天。直到有一天,他们的形体早已经消亡,痕迹再也不能从地球上找到。甚至记得他们痕迹的人的痕迹都已随风而逝。这时候,他们就像其他的白驹一样,成为了一个数字。