SSH auto login from lzheng@a to lzheng@b
login into A as lzheng
ssh lzheng@a
Generate ssh authentication key pair:
ssh-keygen -t rsa -b 1024
Append public key to b@B
SSH auto login from lzheng@a to lzheng@b
login into A as lzheng
ssh lzheng@a
Generate ssh authentication key pair:
ssh-keygen -t rsa -b 1024
Append public key to b@B
http://findproxyforurl.com/wpad-introduction/
https://code.google.com/p/pacparser/
Testing:
pactester -p pad.dat -f url.list
cat pad.dat:
function FindProxyForURL(url, host)
{
if (isInNet(host, “172.16.0.0”, “255.240.0.0”)||
isInNet(host, “192.168.0.0”, “255.255.0.0”)||
isInNet(host, “10.0.0.0”,”255.0.0.0″)||
isInNet(host, “127.0.0.0”,”255.0.0.0″)||
dnsDomainIs(host, “clouddevice.zhenglei.net”)||
dnsDomainIs(host, “blogdevice.zhenglei.net”)||
dnsDomainIs(host, “pydiodevice.zhenglei.net”)||
dnsDomainIs(host, “cloudhost.zhenglei.net”)||
dnsDomainIs(host, “blogdhost.zhenglei.net”)||
dnsDomainIs(host, “pydiohost.zhenglei.net”)
)
{ return “DIRECT”; }
if ( url.substring(0, 4)==”ftp:” )
return “SOCKET 127.0.0.1: 4567”
if (isPlainHostName(host) ||
shExpMatch(host, “*.local”)||
dnsDomainIs(host, “.cn”)||
dnsDomainIs(host, “www.taobao.com”)||
dnsDomainIs(host, “www.jd.com”)||
dnsDomainIs(host, “www.51buy.com”)||
dnsDomainIs(host, “www.yixun.com”)||
dnsDomainIs(host, “www.tmall.com”)||
dnsDomainIs(host, “.gtime.com”)
)
return “PROXY 172.24.61.252: 8080”;
return “SOCKET 127.0.0.1: 4567; PROXY 172.24.61.252: 8080”
}
cat url.list
http://clouddevice.zhenglei.net
http://blogdevice.zhenglei.net
http://pydiodevice.zhenglei.net
http://cloudhost.zhenglei.net
http://bloghost.zhenglei.net
http://pydiohost.zhenglei.net
http://blog.zhenglei.net
http://www.sina.com.cn
http://static.gtimg.com
http://www.51buy.com
http://www.jd.com
http://www.taobao.com
http://www.tmall.com
wnr2000v3 configuration:
LAN1-LAN4 (switch chip) <—-> eth1—-CPU—eth0 <—> WAN
A separate switch chip is used out of route CPU
The switch is initialized in Uboot, and can be configured via swconfig command in ddwrt.
http://www.ibm.com/developerworks/cn/linux/1310_xiawc_networkdevice/
抽象网络设备的原理及使用
网络虚拟化是 Cloud 中的一个重要部分。作为基础知识,本文详细讲述 Linux 抽象出来的各种网络设备的原理、用法、数据流向。您通过此文,能够知道如何使用 Linux 的基础网络设备进行配置以达到特定的目的,分析出 Linux 可能的网络故障原因。
1 评论:
和磁盘设备类似,Linux 用户想要使用网络功能,不能通过直接操作硬件完成,而需要直接或间接的操作一个 Linux 为我们抽象出来的设备,既通用的 Linux 网络设备来完成。一个常见的情况是,系统里装有一个硬件网卡,Linux 会在系统里为其生成一个网络设备实例,如 eth0,用户需要对 eth0 发出命令以配置或使用它了。更多的硬件会带来更多的设备实例,虚拟的硬件也会带来更多的设备实例。随着网络技术,虚拟化技术的发展,更多的高级网络设备被加入了到了 Linux 中,使得情况变得更加复杂。在以下章节中,将一一分析在虚拟化技术中经常使用的几种 Linux 网络设备抽象类型:Bridge、802.1.q VLAN device、VETH、TAP,详细解释如何用它们配合 Linux 中的 Route table、IP table 简单的创建出本地虚拟网络。
Bridge(桥)是 Linux 上用来做 TCP/IP 二层协议交换的设备,与现实世界中的交换机功能相似。Bridge 设备实例可以和 Linux 上其他网络设备实例连接,既 attach 一个从设备,类似于在现实世界中的交换机和一个用户终端之间连接一根网线。当有数据到达时,Bridge 会根据报文中的 MAC 信息进行广播、转发、丢弃处理。
如图所示,Bridge 的功能主要在内核里实现。当一个从设备被 attach 到 Bridge 上时,相当于现实世界里交换机的端口被插入了一根连有终端的网线。这时在内核程序里,netdev_rx_handler_register()被调用, 一个用于接受数据的回调函数被注册。以后每当这个从设备收到数据时都会调用这个函数可以把数据转发到 Bridge 上。当 Bridge 接收到此数据时,br_handle_frame()被调用,进行一个和现实世界中的交换机类似的处理过程:判断包的类别(广播/单点),查找内部 MAC 端口映射表,定位目标端口号,将数据转发到目标端口或丢弃,自动更新内部 MAC 端口映射表以自我学习。
Bridge 和现实世界中的二层交换机有一个区别,图中左侧画出了这种情况:数据被直接发到 Bridge 上,而不是从一个端口接受。这种情况可以看做 Bridge 自己有一个 MAC 可以主动发送报文,或者说 Bridge 自带了一个隐藏端口和寄主 Linux 系统自动连接,Linux 上的程序可以直接从这个端口向 Bridge 上的其他端口发数据。所以当一个 Bridge 拥有一个网络设备时,如 bridge0 加入了 eth0 时,实际上 bridge0 拥有两个有效 MAC 地址,一个是 bridge0 的,一个是 eth0 的,他们之间可以通讯。由此带来一个有意思的事情是,Bridge 可以设置 IP 地址。通常来说 IP 地址是三层协议的内容,不应该出现在二层设备 Bridge 上。但是 Linux 里 Bridge 是通用网络设备抽象的一种,只要是网络设备就能够设定 IP 地址。当一个 bridge0 拥有 IP 后,Linux 便可以通过路由表或者 IP 表规则在三层定位 bridge0,此时相当于 Linux 拥有了另外一个隐藏的虚拟网卡和 Bridge 的隐藏端口相连,这个网卡就是名为 bridge0 的通用网络设备,IP 可以看成是这个网卡的。当有符合此 IP 的数据到达 bridge0 时,内核协议栈认为收到了一包目标为本机的数据,此时应用程序可以通过 Socket 接收到它。一个更好的对比例子是现实世界中的带路由的交换机设备,它也拥有一个隐藏的 MAC 地址,供设备中的三层协议处理程序和管理程序使用。设备里的三层协议处理程序,对应名为 bridge0 的通用网络设备的三层协议处理程序,即寄主 Linux 系统内核协议栈程序。设备里的管理程序,对应 bridge0 寄主 Linux 系统里的应用程序。
Bridge 的实现当前有一个限制:当一个设备被 attach 到 Bridge 上时,那个设备的 IP 会变的无效,Linux 不再使用那个 IP 在三层接受数据。举例如下:如果 eth0 本来的 IP 是 192.168.1.2,此时如果收到一个目标地址是 192.168.1.2 的数据,Linux 的应用程序能通过 Socket 操作接受到它。而当 eth0 被 attach 到一个 bridge0 时,尽管 eth0 的 IP 还在,但应用程序是无法接受到上述数据的。此时应该把 IP 192.168.1.2 赋予 bridge0。
另外需要注意的是数据流的方向。对于一个被 attach 到 Bridge 上的设备来说,只有它收到数据时,此包数据才会被转发到 Bridge 上,进而完成查表广播等后续操作。当请求是发送类型时,数据是不会被转发到 Bridge 上的,它会寻找下一个发送出口。用户在配置网络时经常忽略这一点从而造成网络故障。
VLAN 又称虚拟网络,是一个被广泛使用的概念,有些应用程序把自己的内部网络也称为 VLAN。此处主要说的是在物理世界中存在的,需要协议支持的 VLAN。它的种类很多,按照协议原理一般分为:MACVLAN、802.1.q VLAN、802.1.qbg VLAN、802.1.qbh VLAN。其中出现较早,应用广泛并且比较成熟的是 802.1.q VLAN,其基本原理是在二层协议里插入额外的 VLAN 协议数据(称为 802.1.q VLAN Tag),同时保持和传统二层设备的兼容性。Linux 里的 VLAN 设备是对 802.1.q 协议的一种内部软件实现,模拟现实世界中的 802.1.q 交换机。
如图所示,Linux 里 802.1.q VLAN 设备是以母子关系成对出现的,母设备相当于现实世界中的交换机 TRUNK 口,用于连接上级网络,子设备相当于普通接口用于连接下级网络。当数据在母子设备间传递时,内核将会根据 802.1.q VLAN Tag 进行对应操作。母子设备之间是一对多的关系,一个母设备可以有多个子设备,一个子设备只有一个母设备。当一个子设备有一包数据需要发送时,数据将被加入 VLAN Tag 然后从母设备发送出去。当母设备收到一包数据时,它将会分析其中的 VLAN Tag,如果有对应的子设备存在,则把数据转发到那个子设备上并根据设置移除 VLAN Tag,否则丢弃该数据。在某些设置下,VLAN Tag 可以不被移除以满足某些监听程序的需要,如 DHCP 服务程序。举例说明如下:eth0 作为母设备创建一个 ID 为 100 的子设备 eth0.100。此时如果有程序要求从 eth0.100 发送一包数据,数据将被打上 VLAN 100 的 Tag 从 eth0 发送出去。如果 eth0 收到一包数据,VLAN Tag 是 100,数据将被转发到 eth0.100 上,并根据设置决定是否移除 VLAN Tag。如果 eth0 收到一包包含 VLAN Tag 101 的数据,其将被丢弃。上述过程隐含以下事实:对于寄主 Linux 系统来说,母设备只能用来收数据,子设备只能用来发送数据。和 Bridge 一样,母子设备的数据也是有方向的,子设备收到的数据不会进入母设备,同样母设备上请求发送的数据不会被转到子设备上。可以把 VLAN 母子设备作为一个整体想象为现实世界中的 802.1.q 交换机,下级接口通过子设备连接到寄主 Linux 系统网络里,上级接口同过主设备连接到上级网络,当母设备是物理网卡时上级网络是外界真实网络,当母设备是另外一个 Linux 虚拟网络设备时上级网络仍然是寄主 Linux 系统网络。
需要注意的是母子 VLAN 设备拥有相同的 MAC 地址,可以把它当成现实世界中 802.1.q 交换机的 MAC,因此多个 VLAN 设备会共享一个 MAC。当一个母设备拥有多个 VLAN 子设备时,子设备之间是隔离的,不存在 Bridge 那样的交换转发关系,原因如下:802.1.q VLAN 协议的主要目的是从逻辑上隔离子网。现实世界中的 802.1.q 交换机存在多个 VLAN,每个 VLAN 拥有多个端口,同一 VLAN 端口之间可以交换转发,不同 VLAN 端口之间隔离,所以其包含两层功能:交换与隔离。Linux VLAN device 实现的是隔离功能,没有交换功能。一个 VLAN 母设备不可能拥有两个相同 ID 的 VLAN 子设备,因此也就不可能出现数据交换情况。如果想让一个 VLAN 里接多个设备,就需要交换功能。在 Linux 里 Bridge 专门实现交换功能,因此将 VLAN 子设备 attach 到一个 Bridge 上就能完成后续的交换功能。总结起来,Bridge 加 VLAN device 能在功能层面完整模拟现实世界里的 802.1.q 交换机。
Linux 支持 VLAN 硬件加速,在安装有特定硬件情况下,图中所述内核处理过程可以被放到物理设备上完成。
TUN/TAP 设备是一种让用户态程序向内核协议栈注入数据的设备,一个工作在三层,一个工作在二层,使用较多的是 TAP 设备。VETH 设备出现较早,它的作用是反转通讯数据的方向,需要发送的数据会被转换成需要收到的数据重新送入内核网络层进行处理,从而间接的完成数据的注入。
如图所示,当一个 TAP 设备被创建时,在 Linux 设备文件目录下将会生成一个对应 char 设备,用户程序可以像打开普通文件一样打开这个文件进行读写。当执行 write()操作时,数据进入 TAP 设备,此时对于 Linux 网络层来说,相当于 TAP 设备收到了一包数据,请求内核接受它,如同普通的物理网卡从外界收到一包数据一样,不同的是其实数据来自 Linux 上的一个用户程序。Linux 收到此数据后将根据网络配置进行后续处理,从而完成了用户程序向 Linux 内核网络层注入数据的功能。当用户程序执行 read()请求时,相当于向内核查询 TAP 设备上是否有需要被发送出去的数据,有的话取出到用户程序里,完成 TAP 设备的发送数据功能。针对 TAP 设备的一个形象的比喻是:使用 TAP 设备的应用程序相当于另外一台计算机,TAP 设备是本机的一个网卡,他们之间相互连接。应用程序通过 read()/write()操作,和本机网络核心进行通讯。
VETH 设备总是成对出现,送到一端请求发送的数据总是从另一端以请求接受的形式出现。该设备不能被用户程序直接操作,但使用起来比较简单。创建并配置正确后,向 其一端输入数据,VETH 会改变数据的方向并将其送入内核网络核心,完成数据的注入。在另一端能读到此数据。
为了更好的说明 Linux 网络设备的用法,下面将用一系列的例子,说明在一个复杂的 Linux 网络元素组合出的虚拟网络里,数据的流向。网络设置简介如下:一个中心 Bridge:bridge0 下 attach 了 4 个网络设备,包括 2 个 VETH 设备,1 个 TAP 设备 tap0,1 个物理网卡 eth0。在 VETH 的另外一端又创建了 VLAN 子设备。Linux 上共存在 2 个 VLAN 网络,既 vlan100 与 vlan200。物理网卡和外部网络相连,并且在它之下创建了一个 VLAN ID 为 200 的 VLAN 子设备。
如图所示,当用户尝试 ping 192.168.100.3 时,Linux 将会根据路由表,从 vlan100 子设备发出 ARP 报文,具体过程如下:
1) 用户 ping 192.168.100.3
2) Linux 向 vlan100 子设备发送 ARP 信息。
3) ARP 报文被打上 VLAN ID 100 的 Tag 成为 ARP@vlan100,转发到母设备上。
4) VETH 设备将这一发送请求转变方向,成为一个需要接受处理的报文送入内核网络模块。
5) 由于对端的 VETH 设备被加入到了 bridge0 上,并且内核发现它收到一个报文,于是报文被转发到 bridge0 上。
6) bridge0 处理此 ARP@vlan100 信息,根据 TCP/IP 二层协议发现是一个广播请求,于是向它所知道的所有端口广播此报文,其中一路进入另一对 VETH 设备的一端,一路进入 TAP 设备 tap0,一路进入物理网卡设备 eth0。此时在 tap0 上,用户程序可以通过 read()操作读到 ARP@vlan100,eth0 将会向外界发送 ARP@vlan100,但 eth0 的 VLAN 子设备不会收到它,因为此数据方向为请求发送而不是请求接收。
7) VETH 将请求方向转换,此时在另一端得到请求接受的 ARP@vlan100 报文。
8) 对端 VETH 设备发现有数据需要接受,并且自己有两个 VLAN 子设备,于是执行 VLAN 处理逻辑。其中一个子设备是 vlan100,与 ARP@vlan100 吻合,于是去除 VLAN ID 100 的 Tag 转发到这个子设备上,重新成为标准的以太网 ARP 报文。另一个子设备由于 ID 不吻合,不会得到此报文。
9) 此 VLAN 子设备又被 attach 到另一个桥 bridge1 上,于是转发自己收到的 ARP 报文。
10) bridge1 广播 ARP 报文。
11) 最终另外一个 TAP 设备 tap1 收到此请求发送报文,用户程序通过 read()可以得到它。
和前面情况类似,区别是 VLAN ID 是 200,对端的 vlan200 子设备设置为 reorder_hdr = 0,表示此设备被要求保留收到的报文中的 VLAN Tag。此时子设备会收到 ARP 报文,但是带了 VLAN ID 200 的 Tag,既 ARP@vlan200。
当 bridge0 拥有 IP 时,通过 Linux 路由表用户程序可以直接将 ARP 报文发向 bridge0。这时 tap0 和外部网络都能收到 ARP,但 VLAN 子设备由于 VLAN ID 过滤的原因,将收不到 ARP 信息。
当外部网络连接在一个支持 VLAN 并且对应端口为 vlan200 时,此情况会发生。此时所有的 VLAN ID 为 200 的 VLAN 子设备都将接受到报文,如果设置 reorder_hdr=0 则会收到带 Tag 的 ARP@vlan200。
给 tap0 赋予 IP 并加入路由,此时再 Ping 其对应网段的未知 IP 会产生 ARP 发送请求。需要注意的是此时由于 tap0 上存在的是发送而不是接收请求,因此 ARP 报文不会被转发到桥上,从而什么也不会发生。图中右边画了一个类似情况:从 vlan200 子设备发送 ARP 请求。由于缺少 VETH 设备反转请求方向,因此报文也不会被转发到桥上,而是直接通过物理网卡发往外部网络。
用户程序指定 tap0 设备发送报文有两种方式:socket 和 file operation。当用 socket_raw 标志新建 socket 并指定设备编号时,可以要求内核将报文从 tap0 发送。但和前面的 ping from tap0 情况类似,由于报文方向问题,消息并不会被转发到 bridge0 上。当用 open()方式打开 tap 设备文件时,情况有所不同。当执行 write()操作时,内核认为 tap0 收到了报文,从而会触发转发动作,bridge0 将收到它。如果发送的报文如图所示,是一个以 A 为目的地的携带 VLAN ID 100 Tag 的单点报文,bridge0 将会找到对应的设备进行转发,对应的 VLAN 子设备将收到没有 VLAN ID 100 Tag 的报文。
以 Redhat6.2 红帽 Linux 发行版为例,如果已安装 VLAN 内核模块和管理工具 vconfig,TAP/TUN 设备管理工具 tunctl,那么可以用以下命令设置前述网络设备:
vconfig set_egress_map [VLAN DEVICE NAME] [SKB_PRIORITY] [VLAN_QOS]
vconfig set_ingress_map [VLAN DEVICE NAME] [SKB_PRIORITY] [VLAN_QOS]
综上所述,Linux 已经提供一套基本工具供用户创建出各种内部网络,利用这些工具可以方便的创建出特定网络给应用程序使用,包括云计算中的初级内部虚拟网络。
Configure PPTP client of ddwrt
Add start-up command as following:
#!/bin/sh sleep 120 PPTPSERVER=$(/usr/sbin/nvram get pptpd_client_srvip) PPTPGWY=$(/usr/sbin/nvram get wan_gateway) /sbin/route add -host $PPTPSERVER gw $PPTPGWY dev vlan2 /sbin/route del default /sbin/route add default gw $PPTPGWY metric 100 /sbin/route add default dev ppp0 iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
Android Handset
Envaya: (outbound)
https://github.com/youngj/EnvayaSMS
SMSSync (inbond)
http://www.xda-developers.com/android/increase-the-sms-limit-on-android/
Setting:
sms_outgoing_check_max_count=999999999999999999
Or:
sms_outgoing_check_interval_ms=0
Web Server:
SMStoXMPP
https://projects.jethrocarr.com/p/oss-smstoxmpp/
Drupal
人们常说,通往地狱之路,常由善意铺就[2][3]。好吧,我说的就是Oauth 2.0。
上个月我做出了一个痛苦的决定,彻底和Oauth 2.0标准断绝关系。我辞去首席作者和校订者,从规范中删掉自己的名字,然后离开了工作组。从一份呕心沥血3年之久的文档和超过24份的草稿中去掉自己的名字是多么的不容易;而决定离开一个我领导5年之久为之努力的领域则是多么的痛心。
我做出这个极端决定,并不是单一问题或者事件可以解释的。这是一次由数千次刀割所引发的死亡。随着工作接近尾声,我越来越深思究竟我们在干什么。到了最 后,我得出一个结论,Oauth 2.0是个烂协议,烂得和WS-*有得一拼,烂得我不想再和它产生任何关联。这是我事业生涯中最大的一次职业挫败。
无论是邮件列表、会议讨论、特别设计委员会还是秘密渠道,无数次艰难的争论和妥协,最终产出的规范却在两个最重要目标上双缺失——安全性和互操作性。实际上,有一份折中方案将它从“协议”重新命名为“框架”,而另一份则添加了一个免责声明,警告这份规范并不能阐述互操作性的实现。
和Oauth 1.0相比,Oauth 2.0规范更复杂,缺乏互操作性,实用性打折扣,更加不完整,最重要的是,更加不安全。
说得更明确些,Oauth 2.0如果在一个对互联网安全有深入了解开发者手上,实现结果大抵是安全的。然而,就这两年经历的情况来看,Oauth 2.0在大部分开发者手中明显出现了不安全的实现结果。
我们怎么到达这里的?
这个问题的核心在于,互联网(web)和企业(enterprise)这两个世界之间有着强烈且难以弥合的冲突。IETF的OAuth工作组始于强烈的互联网驱动气势。然而一年之后随着工作一拖再拖,互联网工作者已从最初的1.0社区一个个离去,结果工作组剩下的大部分都是企业人员……然后还有我。
互联网社区一直在寻找与1.0非常相似的协议,并且在某些缺乏的方面进行小改善:简化签名,增加轻量级识别层,标记native application,增加更多流程以适应新的client类型,还有增强安全性。而企业社区则在寻找一种可以最小化改动已有系统的框架,对某些人来 讲,还试图寻求一种通过定制获利的新来源。举个例子理解这种分歧之深——在早期会议中,互联网工作者想实现一种在浏览器内client的流程优化,而企业 人员则想实现基于安全断言标记语言(SAML)的流程。
由上述冲突产生的规范成为了一种基于委员会设计、且更多是为了服务企业方的东拼西凑妥协物。更确切来说,它并非用于满足企业所有直接的需求,它给予的是几乎无限制的可扩展性。正是这种可扩展性和必须要求的灵活性,把这些协议给毁了。现在几乎啥东西都不用费什么努力,就可以宣称达到“Oauth 2.0兼容”标准了。
要明白OAuth 2.0的问题,你需要了解它相比OAuth 1.0在核心架构上有哪些变化:
无绑定token(Unbounded tokens) – 在1.0中,client若要访问受保护资源(protected resource),则必须提供两组凭据:token凭据(the token credentials,即Access Token和Access Token Secret)和client凭据(the client credentials,即常说的应用APP KEY和APP SECRET)。在2.0中,client凭据已经不再被使用了,意味着token已经不再绑定于任何一个特定的client类型或者实例。这样的结果, 既削弱了access token作为一种认证(authentication)手段的作用,同时也增加了出现安全问题的可能性。[5]
无记名token(Bearer tokens[8]) – 2.0在协议层去掉所有签名和加密要求,而仅仅依赖于传输层的TLS[6]。这意味着2.0的token在本质上处于更低安全系数的情况。任何想提高token安全性的行为必然要求额外的规范,而从目前提案展示的情况来看,工作组仅仅着眼于企业应用范畴。
token失效(Expiring tokens) – 2.0 的token存在过期时效,并且必须在过期时进行刷新。这对从1.0过来的client开发者而言是最大的改变,现在他们需要自行实现token状态管 理。之所以有token过期一说,是因为要适应自编码token的实现——一种在服务器端无需进行数据库查找即可进行认证的加密token。正因为这种自 编码token的存在,他们不可能被回收,只能强制为短时效存在,以此减少遭受危险时带来的损失。无论怎样从(server端)去掉签名所带来的好处,都 要在(client端)实现token状态管理面前输了两回。
准许类型(Grant types[7]) – 在2.0中,授权准许(authorization grants)被用于交换获取access token。准许是一种抽象概念,代表最终用户已同意授权。它可以是用户在访问许可授权页中点击“Approve(同意)”后获取的一个code,也可以 是用户实际的用户名和密码。之所以有这个概念,是为了实现多重认证流程。1.0着眼于用1个认证流程适应于多种client类型,而2.0则是明显为不同 的client类型增加多个特殊化认证流程。
犹豫不决的决策
以上的那些改变,若在一个良好定义的协议上实施是可控管理的。然而由于工作组的组成性质,导致了问题(issue)要不陷在细节纠缠不清,要不就只能保持开放等待所有执行成员共同决定。以下仅是工作组无法达成共识的一小部分例子:
– 不强制要求token类型
– 不能对协定基于HMAC算法token类型目标统一意见
– 不要求实施token过期
– 没有关于token字段值长度的指导,其他值类似
– 没有严格要求注册登记流程
– 弱定义client类型
– 缺乏明晰的client安全属性
– 不强制要求准许类型
– 没有一个关于准许类型的适宜性或者适用性指导
– 没有一个实用的native application支持(倒是有许多空口说白话)
– 没有强制要求client认证机制
– 没有限制可扩展性
另一方面,OAuth 2.0为可扩展性定义4个新的登记值,以及通过URI增加额外扩展点,结果引发了一堆关于扩展性的提案。然而真正的问题在于,工作组还是不能为协议定义真 正的安全属性。这很清晰地表现在安全考虑环节上,大多处于扑朔迷离的情况。这导致安全专家几乎没有有效的聚焦点可供分析。实际上,工作组推出过70多页用 于描述2.0威胁模型的文档,它试图提供更多额外信息,但仍受困于一个相同的根本问题:没有一个实质的协议可供分析。
现实
在现实世界,Facebook仍在运行着一年半前的草案12,而且也完全没有理由要他们升级现有的实现形式。毕竟,一个升级过的、用于实现 Facebook对接的2.0 client也不太可能复用于其它Oauth服务提供方,反之亦然。Oauth 2.0一点也没有提供代码复用的潜力。
Oauth 2.0提供的是一个关于授权协议的蓝图(a blueprint for an authorization protocol)。正如上述定义所说,(独立使用)它基本上毫无用武之地,必须要迁并入一个具体的工作解决方案中——而这正是企业化的方式,WS-*的套路。2.0提供了一个全新的领域,用来推销咨询服务和整合方案。
然而互联网并不需要又一套安全框架。它需要的是一个简单、良好定义、和恰如其分合适的协议,以此提高安全性和增强互操作性。(可以说,)OAuth 2.0在寻求任何有意义的协议替代实现上失败了。
升级,还是停留
在最近几个月,许多人都问我,他们是否应该升级到Oauth 2.0,又或者应该推荐哪个协议版本给他们实现。我的答案是不能一概而论。
如果你现在用1.0用得很成功,忽略掉2.0吧。它并没有比1.0体现出更好的价值。(我猜测,用你们服务的client开发者现在已经很熟悉1.0的签名机制了。)
如果你在这个领域是个新来者,而且认为自己是个安全专家,务必要在仔细小心地审查Oauth 2.0的各种特性后再使用。如果你不是专家,要不就使用Oauth 1.0,要不就复制一个你信得过的Oauth 2.0服务方实现形式,来把事情做对(Facebook的API文档是一个很好的着手地方)。2.0对于大规模扩展(实施)相对较好,但是如果要运行大规 模改造,你很可能还需要一些安全专家现场估算各种情况和解决方案。
现在该咋办?
我现在希望有人接手2.0,然后创作10页左右、抛弃企业用途并更适用于绝大部分互联网服务提供方的文档。版本2.1应该更接近于版本1.5。但是在IETF,这根本不可能发生。在那个社区氛围中,全都是企业级用例。如果你看看他们的其他努力(比如OpenID Connect,本来超级简单的提案最终变成了一大打复杂的规范)就会知道,他们没能力让事情简化。
我认为OAuth牌子已经在衰退。这个框架还会存在一段时间,并且在当前缺乏替代品的情况下,它还会得到更广泛的接纳。然而我们更乐于看到接下来的几年里,Oauth 2.0会爆发各种重大的安全故障,还有其缓慢但稳步的品牌贬值。这将成为又一个你所厌恶却陷于其中泥潭的协议。
与此同时,我希望众多新兴社区们提出一些骨子里更接近1.0而非2.0的东西。Oauth 1.0是所有关于小型互联网创业团队寻找快速解决已明确定义问题的用户方案。老实点说,我都不知道Oauth 2.0究竟要解决什么样的用例。
写在最后
对于一个曾经有前途的社区,结论却是悲哀的。OAuth曾作为小型、快速且有用的标准模范,在标准机构之外无需繁琐过程和法律花销中产生。
(然而现在,)我们的标准制定过程已经破碎地无法修复。这个结局直接来源于IETF的本性,还有监督这份工作时的某些特定性格。更直白地说,这并非由于某 些坏人或者无能者导致的。恰恰相反,大家都非常有才华、聪明、和蔼可亲等等。然而大多数人表态只为自身企业领域服务,而剩下的我们已在事实上无法与之竞 争。
将OAuth带入IETF是个巨大的错误。另一种替代方案WRAP也不会有更好的结局,但至少不用花费3年时间才得知这个下场。只要能坚持住,我尽可能地留在里面,去为我自认为最适合互联网的模式而战。可是就自己而言,我并没有从所做的决策中得到什么。到了最后,一个反对派的声音只能将事情延缓,但不能改变什么。
我失败了。
我们都失败了。
http://hueniverse.com/2012/07/26/oauth-2-0-and-the-road-to-hell/