存档在 2011年7月

OpenSSH密钥管理

2011年7月24日

作者

Daniel Robbins, 总裁/首席执行官, Gentoo Technologies,Inc. 2001 年 9 月 01 日

Daniel Robbins 居住在美国新墨西哥州的阿尔布开克。他主创了 Gentoo Linux,这是一种用于 PC 的高级 Linux,以及 Portage 系统,是用于 Linux 的下一代移植系统。他还是几本 Macmillan 出版的书籍 Caldera OpenLinux Unleashed、SuSE Linux Unleashed 和 Samba Unleashed 的投稿人。Daniel 自二年级起就与计算机结下了不解之缘,那时他最先接触的是 Logo 程序语言,并沉溺于 Pac Man 游戏中。这也许就是他至今仍担任 SONY Electronic Publishing/Psygnosis 首席图形设计师的原因所在。Daniel 喜欢与妻子 Mary 和新出生的女儿 Hadassah 一起共度时光。

原文镜像

第 1 部分 理解 RSA/DSA 认证

在本系列文章中,您将学习 RSA 和 DSA 认证的工作原理,以及了解如何正确设置无密码认证。在本系列的第一篇文章里,Daniel Robbins 主要介绍 RSA 和 DSA 认证协议并向您展示如何在网络上应用这些协议。在本系列文章中,您将学习 RSA 和 DSA 认证的工作原理,以及了解如何正确设置无密码认证。在本系列的第一篇文章里,Daniel Robbins 主要介绍 RSA 和 DSA 认证协议并向您展示如何在网络上应用这些协议。

我们中有许多人把优秀的 OpenSSH(参见本文后面的参考资料)用作古老的 telnet 和 rsh 命令的替代品,OpenSSH 不仅是安全的而且是加密的。OpenSSH 更加吸引人的特性之一是它能够使用基于一对互补的数字式密钥的 RSA 和 DSA 认证协议来认证用户。RSA 和 DSA 认证承诺不必提供密码就能够同远程系统建立连接,这是它的主要魅力之一。虽然这非常吸引人,但是 OpenSSH 的新用户们常常以一种快速却不完善的方式配置 RSA/DSA,结果虽然实现了无密码登录,却也在此过程中开了一个很大的安全漏洞。

什么是 RSA/DSA 认证?

SSH,特别是 OpenSSH(完全免费的 SSH 的实现),是一个不可思议的工具。类似于 telnet 或 rsh,ssh 客户程序也可以用于登录到远程机器。所要求的只是该远程机器正在运行 sshd,即 ssh 服务器进程。但是,与 telnet 不同的是,ssh 协议非常安全。加密数据流,确保数据流的完整性,甚至安全可靠的进行认证它都使用了专门的算法。

然而,虽然 ssh 的确很棒,但还是有一个 ssh 功能组件常常被忽略、被危险的误用或者简直就是被误解。这个组件就是 OpenSSH 的 RSA/DSA 密钥认证系统,它可以代替 OpenSSH 缺省使用的标准安全密码认证系统。

OpenSSH 的 RSA 和 DSA 认证协议的基础是一对专门生成的密钥,分别叫做专用密钥和公用密钥。使用这些基于密钥的认证系统的优势在于:在许多情况下,有可能不必手工输入密码就能建立起安全的连接。

尽管基于密钥的认证协议相当安全,但是当用户并不完全了解这些简化操作对安全性的影响,为了方便而使用某些简化操作时,就会出现问题。本文中,我们将详细讨论如何正确使用 RSA 和 DSA 认证协议,使我们不会冒任何不必要的安全性风险。在我的下一篇文章里,我将向您展示如何使用 ssh-agent 隐藏已经解密的专用密钥,还将介绍 keychain,它是 ssh-agent 的前端,可以在不牺牲安全性的前提下提供许多便利。如果您一直想要掌握 OpenSSH 更高级的认证功能的话,那么就请您继续往下读吧。

RSA/DSA 密钥的工作原理

下面从整体上粗略的介绍了 RSA/DSA 密钥的工作原理。让我们从一种假想的情形开始,假定我们想用 RSA 认证允许一台本地的 Linux 工作站(称作 localbox)打开 remotebox 上的一个远程 shell,remotebox 是我们的 ISP 的一台机器。此刻,当我们试图用 ssh 客户程序连接到 remotebox 时,我们会得到如下提示:

% ssh drobbins@remotebox
drobbins@remotebox's password:

此处我们看到的是 ssh 处理认证的缺省方式的一个示例。换句话说,它要求我们输入 remotebox 上的 drobbins 这个帐户的密码。如果我们输入我们在 remotebox 上的密码,ssh 就会用安全密码认证协议,把我们的密码传送给 remotebox 进行验证。但是,和 telnet 的情况不同,这里我们的密码是加密的,因此它不会被偷看到我们的数据连接的人截取。一旦 remotebox 把我们提供的密码同它的密码数据库相对照进行认证,成功的话,我们就会被允许登录,还会有一个 remotebox 的 shell 提示欢迎我们。虽然 ssh 缺省的认证方法相当安全,RSA 和 DSA 认证却为我们开创了一些新的潜在的机会。

但是,与 ssh 安全密码认证不同的是,RSA 认证需要一些初始配置。我们只需要执行这些初始配置步骤一次。之后,localbox 和 remotebox 之间的 RSA 认证就毫不费力了。要设置 RSA 认证,我们首先得生成一对密钥,一把专用密钥和一把公用密钥。这两把密钥有一些非常有趣的性质。公用密钥用于对消息进行加密,只有拥有专用密钥的人才能对该消息进行解密。公用密钥只能用于 加密,而专用密钥只能用于对由匹配的公用密钥编码的消息进行解密。RSA(和 DSA)认证协议利用密钥对的这些特殊性质进行安全认证,并且不需要在网上传输任何保密的信息。

要应用 RSA 或者 DSA 认证,我们要执行一步一次性的配置步骤。我们把公用密钥拷贝到 remotebox。公用密钥之所以被称作是“公用的”有一个原因。因为它只能用于对那些给我们的消息进行 加密,所以我们不需要太担心它会落入其它人手中。一旦我们的公用密钥已经被拷贝到 remotebox 并且为了 remotebox 的 sshd 能够定位它而把它放在一个专门的文件(~/.ssh/authorized_keys)里,我们就为使用 RSA 认证登录到 remotebox 上做好了准备。

要用 RSA 登录的时候,我们只要在 localbox 的控制台键入 ssh drobbins@remotebox,就象我们常做的一样。可这一次,ssh 告诉 remotebox 的 sshd 它想使用 RSA 认证协议。接下来发生的事情非常有趣。Remotebox 的 sshd 会生成一个随机数,并用我们先前拷贝过去的公用密钥对这个随机数进行加密。然后, sshd 把加密了的随机数发回给正在 localbox 上运行的 ssh。接下来,轮到我们的 ssh 用专用密钥对这个随机数进行解密后,再把它发回给 remotebox,实际上等于在说:“瞧,我确实有匹配的专用密钥;我能成功的对您的消息进行解密!”最后, sshd 得出结论,既然我们持有匹配的专用密钥,就应当允许我们登录。因此,我们有匹配的专用密钥这一事实授权我们访问 remotebox。

两项注意事项

关于 RSA 和 DSA 认证有两项重要的注意事项。第一项是我们的确只需要生成一对密钥。然后我们可以把我们的公用密钥拷贝到想要访问的那些远程机器上,它们都会根据我们的那把专用密钥进行恰当的认证。换句话说,我们并不需要为想要访问的 每个系统都准备一对密钥。只要一对就足够了。

另一项注意事项是专用密钥不应落入其它人手中。正是专用密钥授权我们访问远程系统,任何拥有我们的专用密钥的人都会被授予和我们完全相同的特权。如同我们不想让陌生人有我们的住处的钥匙一样,我们应该保护我们的专用密钥以防未授权的使用。在比特和字节的世界里,这意味着没有人是本来就应该能读取或是拷贝我们的专用密钥的。

ssh 的开发者们当然知道专用密钥的重要性,而且他们已经在 ssh 和 ssh-keygen 里加入了一些防范措施,以防止我们的专用密钥被滥用。首先,ssh 被设置成了如果我们的密钥的文件权限允许除我们之外的任何人读取密钥,就打印出一条大大的警告消息。其次,在我们用 ssh-keygen 创建公用/专用密钥对的时候,ssh-keygen 会要求我们输入一个密码短语。如果我们输入了密码短语,ssh-keygen 就会用该密码短语加密我们的专用密钥,这样,即使专用密钥被盗,对于那些碰巧不知道密码短语的人而言,这把专用密钥是毫无用处的。具备了这一知识后,让我们看一下如何设置 ssh 以应用 RSA 和 DSA 认证协议。

ssh-keygen 细探

设置 RSA 认证的第一步从生成一对公用/专用密钥对开始。RSA 认证是 ssh 密钥认证的最初形式,因此 RSA 应该可以用于 OpenSSH 的所有版本,尽管这样,我还是推荐您安装可用的最近版本,在我写这篇文章的时候是 openssh-2.9_p2。生成一对 RSA 密钥的方法如下:

% ssh-keygen
Generating public/private rsa1 key pair.
Enter file in which to save the key (/home/drobbins/.ssh/identity): (hit enter)
Enter passphrase (empty for no passphrase): (enter a passphrase)
Enter same passphrase again: (enter it again)
Your identification has been saved in /home/drobbins/.ssh/identity.
Your public key has been saved in /home/drobbins/.ssh/identity.pub.
The key fingerprint is:
a4:e7:f2:39:a7:eb:fd:f8:39:f1:f1:7b:fe:48:a1:09 drobbins@localbox

当 ssh-keygen 要求输入存放密钥的缺省位置时,我们敲回车键接受缺省的 /home/drobbins/.ssh/identity。ssh-keygen 将把专用密钥保存在此路径中,公用密钥就存在紧临它的一个叫做 identity.pub 的文件里。

还要请您注意一下 ssh-keygen 还提示过我们输入密码短语。当时我们输入了一个好的密码短语(七位或者更多位难以预测的字符)。然后 ssh-keygen 用这个密码短语加密了我们的专用密钥(~/.ssh/identity),以使我们的专用密钥对于那些不知道这个密码短语的人将变得毫无用处。

追求快速的折衷方案

当我们指定密码短语时,虽然这使得 ssh-keygen 保护我们的专用密钥以防误用,但是也带来了一点小小的不便。现在,每当我们试图用 ssh 连接到 drobbins@remotebox 帐户时,ssh 都会提示我们输入该密码短语以便它能对我们的专用密钥进行解密,并使用我们的专用密钥进行 RSA 认证。此外,我们输入的不是 remotebox 上 drobbins 帐户的密码,而是在本地机器上对专用密钥进行解密所需要的密码短语。一旦我们的专用密钥被解密,我们的 ssh 客户程序就会处理其余的事情。虽然使用我们的远程密码和使用 RSA 密码短语的机制完全不同,但实际上还是会提示我们输入一个“保密的短语”给 ssh。

# ssh drobbins@remotebox
Enter passphrase for key '/home/drobbins/.ssh/identity': (enter passphrase)
Last login: Thu Jun 28 20:28:47 2001 from localbox.gentoo.org 

Welcome to remotebox!

%

这里就是人们经常会被误导而导致追求快速的折衷方案的地方。有很多时候,仅仅是为了不必输入密码,人们就会创建不加密的专用密钥。那样的话,他们只要输入 ssh命令,立刻就会通过 RSA(或是 DSA)认证并登录。

# ssh drobbins@remotebox
Last login: Thu Jun 28 20:28:47 2001 from localbox.gentoo.org 

Welcome to remotebox!

%

然而,尽管这样很方便,但是在还没有完全理解这种方法对安全性的影响时,您不应该使用。如果有人在某一时刻闯入了 localbox,一把不加密的专用密钥使得他们也自动有权访问 remotebox 以及其它所有用这把公用密钥配置过的系统。

我知道您在想些什么。无密码认证,虽然有点冒险,可看起来的确很诱人。我完全同意。但是, 还有更好的办法!请相信我,我将向您展示如何既可以享受到无密码认证的好处,又不必牺牲专用密钥的安全性。在我的下一篇文章里,我还将向您展示如何熟练的使用 ssh-agent(正是它最先使得安全无密码认证成为可能)。现在,让我们通过设置 RSA 和 DSA 认证为使用 ssh-agent 做好准备。下面是逐步的指导。

RSA 密钥对的生成

要设置 RSA 认证,我们需要执行生成公用/专用密钥对的一次性步骤。我们的输入如下:

% ssh-keygen

出现提示时,请接受缺省的密钥位置(典型的情况下是 ~/.ssh/identity 和存储公用密钥的 ~/.ssh/identity.pub),并提供给 ssh-keygen 一个安全的密码短语。一旦 ssh-keygen 完成,您将会得到一把公用密钥和一把用密码短语加密的专用密钥。

RSA 公用密钥的安装

接下来,我们需要把正在运行 sshd 的远程系统设置成使用我们的公用 RSA 密钥进行认证。典型情况下,我们通过象下面这样把公用密钥拷贝到远程系统完成这一步:

% scp ~/.ssh/identity.pub drobbins@remotebox:

由于 RSA 认证还没有完全设置好,所以会提示我们输入 remotebox 上的密码。请您照做。然后,登录到 remotebox 并把公用密钥附加到文件 ~/.ssh/authorized_keys 上,如下所示:

% ssh drobbins@remotebox
drobbins@remotebox's password: (enter password)
Last login: Thu Jun 28 20:28:47 2001 from localbox.gentoo.org 

Welcome to remotebox!

% cat identity.pub >> ~/.ssh/authorized_keys
% exit

现在,配置过 RSA 认证以后,当我们试图使用 ssh 连接到 remotebox 时,应该会提示我们输入 RSA 密码短语(而不是我们的密码)。

% ssh drobbins@remotebox
Enter passphrase for key '/home/drobbins/.ssh/identity':

好哇,RSA 认证的配置完成了!如果刚才没有提示您输入密码短语,您可以试验一下以下几种情况。第一,尝试通过输入 ssh -1 drobbins@remotebox 登录。它会让 ssh 只应用 ssh 协议版本 1,如果出于某种原因远程系统缺省设置的是 DSA 认证的话,可能会要求这么做。如果不奏效的话,请确认您的 /etc/ssh/ssh_config 里没有写着这么一行 RSAAuthentication no。如果有的话,请您在前面加上一个“#”把这行注释掉。另外,还可以试着同 remotebox 的系统管理员联络,核实一下在他们那一端已经启用了 RSA 认证,并且 /etc/ssh/sshd_config 里的设置是正确的。

DSA 密钥的生成

ssh 协议的版本 1 使用的是 RSA 密钥,而 DSA 密钥却用于协议级 2,这是 ssh 协议的最新版本。目前所有的 OpenSSH 版本都应该既能使用 RSA 密钥又能使用 DSA 密钥。DSA 密钥以如下类似于 RSA 密钥的方式使用 OpenSSH 的 ssh-keygen 生成:

% ssh-keygen -t dsa

又会提示我们输入密码短语。输入一个安全的密码短语。还会提示我们输入保存 DSA 密钥的位置。正常情况下,缺省的 ~/.ssh/id_dsa 和 ~/.ssh/id_dsa.pub 就可以了。在我们一次性生成 DSA 密钥完成后,就该把我们的 DSA 公用密钥安装到远程系统上去了。

DSA 公用密钥的安装

DSA 公用密钥的安装又是几乎和 RSA 安装完全一样。对于 DSA,我们将要把 ~/.ssh/id_dsa.pub 文件拷贝到 remotebox,然后把它附加到 remotebox 上的 ~/.ssh/authorized_keys2 文件。请注意这个文件的名字和 RSA 的 authorized_keys 文件名不同。一旦配置完毕,输入我们的 DSA 专用密钥的密码短语就应该能登录到 remotebox,而不需要我们输入在 remotebox 上真正的密码。

下一篇

此刻,您应该已经可以使用 RSA 或者 DSA 认证了,但是在每一次新连接时,您仍需输入您的密码短语。在我的下一篇文章里,我们将会了解到如何使用 ssh-agent,它确实是一个很不错的系统,不仅允许我们不提供密码就建立连接,而且还使我们的专用密钥可以在磁盘上保持加密状态。我还将介绍 keychain,它是一个非常方便的 ssh-agent 前端,可以使 ssh-agent 比以前更可靠、更方便而且使用起来更具趣味性。在此之前,请就近查阅下面列出的参考资料以使您能跟上进度。

参考资料

第 2 部分 介绍 ssh-agent 和 keychain

许多开发人员把优秀的 OpenSSH 用作古老的 telnet 和 rsh 命令的替代品,OpenSSH 不仅是安全的而且是加密的。OpenSSH 更加吸引人的特性之一是它能够使用基于一对互补的数字式“密钥”的 RSA 和 DSA 认证协议来认证用户。RSA 和 DSA 认证承诺 不必提供密码就能够同远程系统建立连接,这是其主要魅力之一。在第二篇文章里,Daniel 介绍 ssh-agent (专用密钥高速缓存)及 keychain ,这个特殊的 bash 脚本的设计使基于密钥的认证极为方便和灵活。

介绍 ssh-agent

ssh-agent 是专为既令人愉快又安全的处理 RSA 和 DSA 密钥而设计的特殊程序,它包括在 OpenSSH分发内(请参阅 本系列文章的第 1 部分以得到关于 RSA 和 DSA 认证的介绍)。不同于 ssh , ssh-agent 是个长时间持续运行的守护进程(daemon),设计它的唯一目的就是对解密的专用密钥进行高速缓存。

ssh 包含的内建支持允许它同 ssh-agent 通信,允许 ssh 不必每次新连接时都提示您要密码才能获取解密的专用密钥。对于 ssh-agent ,您只要使用 ssh-add 把专用密钥添加到 ssh-agent 的高速缓存中。这是个一次性过程;用过 ssh-add 之后, ssh 将从 ssh-agent 获取您的专用密钥,而不会提示要密码短语来烦您了。

使用 ssh-agent

让我们看一下整个 ssh-agent 密钥高速缓存系统的工作过程。 ssh-agent 启动时,在脱离 shell(外壳程序)并继续在后台运行之前它会输出一些重要的环境变量。以下是 ssh-agent 开始时生成的输出的一些示例:

% ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-XX4LkMJS/agent.26916; export SSH_AUTH_SOCK;
SSH_AGENT_PID=26917; export SSH_AGENT_PID;
echo Agent pid 26917;

正如您所看到的,事实上 ssh-agent 的输出是一系列 bash 命令;如果这些命令被执行,则将设置两个环境变量:SSH_AUTH_SOCK 和 SSH_AGENT_PID。内含的 export 命令使这些环境变量对之后运行的任何附加命令都可用。唔, 如果 shell 真对这些行进行计算,这一切才会发生,但是此时它们只是被打印到标准输出(stdout)而已。要使之确定,我们可以象下面这样调用 ssh-agent :

eval `ssh-agent`

这个命令先让 bash 运行 ssh-agent 后对 ssh-agent 的输出进行计算。shell 以这种调用方式(使用反引号,而不是普通的单引号)设置并导出 SSH_AGENT_PID 及 SSH_AUTH_SOCK 变量,使这些变量对于您在登录会话期间启动的所有新进程都可用。

启动 ssh-agent 的最佳方式就是把上面这行添加到您的 ~/.bash_profile 中;这样,在您的登录 shell 中启动的所有程序都将看到环境变量,而且能够定位 ssh-agent ,并在需要的时候向其查询密钥。尤其重要的环境变量是 SSH_AUTH_SOCK;SSH_AUTH_SOCK 包含有 ssh 和 scp 可以用来同 ssh-agent 建立对话的 UNIX 域套接字的路径。

使用 ssh-add

但是 ssh-agent 启动时高速缓存当然是空的,里面不会有解密的专用密钥。在我们真能使用 ssh-agent 之前,首先还需要使用 ssh-add 命令把我们的专用密钥添加到 ssh-agent 的高速缓存中。下面的示例中,我使用 ssh-add 把我的 ~/.ssh/identity 专用 RSA 密钥添加到 ssh-agent 的高速缓存中:

# ssh-add ~/.ssh/identity
Need passphrase for /home/drobbins/.ssh/identity
Enter passphrase for /home/drobbins/.ssh/identity
(enter passphrase)

正如您所看到的, ssh-add 要我的密码短语来对专用密钥进行解密并存储在 ssh-agent 的高速缓存中以备使用。一旦您已经用 ssh-add 把专用密钥(或多个密钥)添加到 ssh-agent 的高速缓存中, 并在当前的 shell 中(如果您在 ~/.bash_profile 中启动 ssh-agent ,情况应当是这样)定义 SSH_AUTH_SOCK,那么您可以使用 scp 和 ssh 同远程系统建立连接而不必提供密码短语。

ssh-agent 的不足之处

ssh-agent 确实棒,但是其缺省配置还是会留给我们一些小小的不便。让我们来看一下这些不足吧。

首先,~/.bash_profile 中的 eval `ssh-agent` 使每次登录会话都会启动一个新的 ssh-agent 副本;这不仅仅是有一丁点儿浪费,而且还意味着您得使用 ssh-add 向每个新的 ssh-agent 副本添加专用密钥。如果您只想打开系统上的一个终端或控制台,这没什么大不了的,但是我们中大多数人打开相当多的终端,每次新打开控制台都需要键入密码短语。从技术角度讲,既然一个 ssh-agent 进程的确应当足够了,要是我们还需这样做,这毫无道理。

有关 ssh-agent 的缺省设置的另外一个问题是它同 cron 作业不兼容。由于 cron 作业是 cron 进程启动的,这些作业无法从它们的环境中继承 SSH_AUTH_SOCK 变量,因而也无从知道 ssh-agent 进程正在运行以及如何同它联系。事实证明这个问题也是可以修补的。

开始用到 keychain

为了解决这些问题,我编写了一个有用的 ssh-agent 前端,它基于 bash,叫做 keychain 。 keychain 的特别之处在于它允许 每个系统使用一个 ssh-agent 进程,而非每次登录会话。这意味着您只需对每个专用密钥执行一次 ssh-add ,就一次。正如我们稍后将要看到的一样, keychain 甚至有助于优化 ssh-add ,而这只要它试图向那些正在运行的 ssh-agent 添加其高速缓存中没有的专用密钥。

以下对 keychain 如何工作从头到尾浏览一遍。从 ~/.bash_profile 中启动时, keychain 将首先查看 ssh-agent 是否已经在运行了。如果没有,它就启动 ssh-agent 并把重要的 SSH_AUTH_SOCK 和 SSH_AGENT_PID 变量记录在 ~/.ssh-agent 文件中,一方面为了安全而保存,另一方面也是为了以后的使用。这是启动 keychain 的最佳途径;同使用平淡无奇的老式 ssh-agent 一样,我们在 ~/.bash_profile 内部执行必要的配置:

#!/bin/bash
#example ~/.bash_profile file
/usr/bin/keychain ~/.ssh/id_rsa
#redirect ~/.ssh-agent output to /dev/null to zap the annoying
#"Agent PID" message
source ~/.ssh-agent > /dev/null

正如您所看到的,对于 keychain 我们用 source 命令读入并执行 ~/.ssh-agent 文件,而不是象我们直接使用 ssh-agent 时所做的对输出进行计算。但是,结果是一样的:定义了非常重要的 SSH_AUTH_SOCK,而且正运行 ssh-agent 以备使用。同时,因为 SSH_AUTH_SOCK 被记录在 ~/.ssh-agent 里,只要用 source 命令读入并执行 ~/.ssh-agent 文件,就可以轻易的把我们的 shell 脚本及 cron 作业同 ssh-agent 连接起来。 keychain 本身也利用了这个文件;您应该记住 keychain 启动时,它会查看现有的 ssh-agent 是否正在运行。如果是,则它使用 ~/.ssh-agent 文件来获得适当的 SSH_AUTH_SOCK 设置,这样就使 keychain 能使用现有的代理程序而不必新启动一个。只有在 ~/.ssh-agent 文件无效(指向一个不存在的 ssh-agent )或 ~/.ssh-agent 文件本身不存在时, keychain 才会启动新的 ssh-agent 进程。

安装 keychain

安装 keychain 很容易。首先,直接到 keychain 工程主页下载可用的 keychain 源压缩文档的最新版本。然后,安装如下:

# tar xzvf keychain-1.0.tar.gz
# cd keychain-1.0
# install -m0755 keychain /usr/bin

既然 keychain 在 /usr/bin/ 目录下,就请把它添加到您的 ~/.bash_profile 中,并把您的专用密钥路径作为参数。下面是一个既标准又好的启用 keychain 的 ~/.bash_profile:

启用 keychain 的 ~/.bash_profile 示例

#!/bin/bash
#on this next line, we start keychain and point it to the private keys that
#we'd like it to cache
/usr/bin/keychain ~/.ssh/id_rsa ~/.ssh/id_dsa
source ~/.ssh-agent > /dev/null
#sourcing ~/.bashrc is a good thing
source ~/.bashrc

Keychain 生效

您一为每次登录时调用 keychain 配置好了 ~/.bash_profile,就请先退出再登录回来。在您再次登录时, keychain 将启动 ssh-agent ,并记录下 ~/.ssh-agent 中的代理程序环境变量设置,然后提示您输入在 ~/.bash_profile 中的 keychain 命令行指定的所有专用密钥的密码短语:

Keychain 首次启动

您一输入密码短语,您的专用密钥就会被高速缓存,同时 keychain 将退出。接着,用 source 命令读入并执行 ~/.ssh-agent,初始化您的登录会话以便同 ssh-agent 一起使用。现在,如果您退出,然后再登录回来,将发现 keychain 会找到现有的 ssh-agent 进程;在您退出时,它并没有终止。此外, keychain 将验证您指定的专用密钥是否已经在 ssh-agent 的高速缓存中了。如果没有,那么将会提示您输入正确的密码短语,但如果一切进展顺利,则现有 ssh-agent 仍包含有您以前添加的专用密钥;这意味着不会提示您输入密码:

Keychain 找到现有的 ssh-agent

祝贺您!您刚才已经登录了,应该能够用 ssh 和 scp 连到远程系统;您不必一登录就使用 ssh-add ,而且 ssh 和 scp 也不会提示您输入密码短语。事实上,只要初始的 ssh-agent 进程一直在运行,您就能不提供密码登录并建立 ssh 连接。 ssh-agent 进程持续运行直到机器重新启动也是很有可能的;由于您最可能在 Linux 系统上这样设置,所以也许一连几个月您都不必输入密码短语!欢迎来到安全的、使用 RSA 和 DSA 认证无密码连接的世界。

继续创建几个新的登录会话,您会发现每次 keychain 都会准确无误的“钩住”到同一 ssh-agent 进程。不要忘记您也可以使 cron 作业和脚本“钩住”正在运行的 ssh-agent 进程。要在 shell 脚本和 cron 作业中使用 ssh 或 scp 命令,只要确保先用 source 命令读入并执行 ~/.ssh-agent:

source ~/.ssh-agent

然后,随后所有的 ssh 或 scp 命令就能够找到当前正在运行的 ssh-agent ,并且象您在 shell 中一样能建立安全的无密码连接。

Keychain 选项

您启动并运行 keychain 后,一定要键入 keychain –help 以熟悉 keychain 所有的命令行选项。我们要特别看一下这个选项: -clear 选项。

还记得我在 第 1 部分里阐释了使用不加密专用密钥是一种危险的做法,因为这种做法允许其它人盗用您的专用密钥不提供密码就可以从所有系统登录到您的远程帐户。唔,尽管 keychain 不易遭到这种滥用(只要您使用加密的专用密钥就行),但仍存在有可能可以利用的弱点,同 keychain 使得“钩住”长时间持续运行的 ssh-agent 进程如此容易这一事实直接相关。我想,如果闯入者以某种方式能想出我的密码或密码短语,还能登录进入我的本地系统,会发生什么事情呢?如果出于某种原因他们能以我的用户名登录,那么 keychain 就会立刻授权他们访问我的解密的专用密钥,使他们可以轻而易举的访问我的其它帐户。

现在,在继续下面的内容之前,让我们先客观的表述一下安全威胁。如果由于某种原因一些恶意的用户能以我的身份登录, keychain 确实会允许他们访问我的远程帐户。但,尽管如此,这位闯入者要偷到我的加密的专用密钥非常困难,因为它们仍旧在磁盘上保持着加密状态。而且,得到我的专用密钥访问权要求用户真的以我的身份 登录,不单单是阅读我的目录中的文件而已。因此,滥用 ssh-agent 是比只偷到一个不加密的专用密钥困难得多的一项任务,后者只需要闯入者通过某种手段获得我在 ~/.ssh 里的文件的访问权,而不管是否是以我的身份登录。不过,如果闯入者能够成功的以我的身份登录,通过使用我的加密专用密钥他们造成相当多的额外损害。所以,如果您刚好在您不频繁登录或没有对安全缺口进行密切监视的一台服务器上使用 keychain ,那么请您考虑使用 –clear 选项以提供附加的安全层。

–clear 选项允许您让 keychain 假定把每次以您的帐户的新登录都当作是可能的安全缺口,直到能证明并非如此。当您启动 keychain 时使用了 –clear 选项时,您登录的时候 keychain 会立即刷新 ssh-agent 的高速缓存里的所有专用密钥,此后才执行它的常规职责。这样,如果您是一位闯入者,则 keychain 会提示您输入密码短语而不会让您访问现有的高速缓存中的密钥集合。但是,虽然这样增强了安全性,却使情况有点更不方便,尤其好象完全是 ssh-agent 在运行,而 keychain 并没有运行。此处,情况常常是这样,一个人可以选择或者安全性更高,或更方便,但不能两者兼得。

尽管如此,使用带有 –clear 的 keychain 仍然比只用 ssh-agent 要好;请记住,当您使用 keychain –clear 时,您的 cron 作业和脚本仍然能建立无密码连接;这是因为专用密钥是在 登录时刷新,而不是在 退出时。由于从系统退出不会构成潜在的安全缺口,因而没有理由要 keychain 来刷新 ssh-agent 的密钥作为响应。因此,对于不频繁访问又需要偶而执行安全拷贝任务的服务器而言,比如,备份服务器、防火墙及路由器, –clear 选项是一个理想的选择。

结束了!

既然 OpenSSH 密钥管理系列文章结束了,您就应当对 RSA 和 DSA 密钥非常熟悉,而且应当知道如何以一种方便又安全的方式使用。还务必请看看下面的参考资料:

参考资料

第 3 部分 代理程序转发和 keychain 改进

在这一系列的第三篇文章中,Daniel Robbins 向您显示了如何利用 OpenSSH 代理程序连接转发来增强安全性。他还共享 keychain shell 脚本近期的改进。

我们中的许多人都使用非常优秀的 OpenSSH 作为古老的 telnet 和 rsh 命令的替代品,OpenSSH 不仅安全而且是加密的。OpenSSH 更吸引人的特性之一是它能够使用以一对互补的数字式“密钥”为基础的 RSA 和 DSA 认证协议来认证用户。RSA 和 DSA 认证承诺不必提供密码就能够与远程系统建立连接,这是其主要魅力之一。有关更多背景资料,请参阅关于 OpenSSH 密钥管理的本系列文章中以前的几篇,分别包括 RSA/DSA 认证(第 1 部分)和 ssh-agent 和 keychain(第 2 部分)。

由于第 2 部分发表在 2001 年 9 月的 developerWorks上,并且稍后在 Slashdot 和 Freshmeat(请参阅本文后面的 参考资料,获取到这些站点的链接)上引用了此文,因此,许多人已经开始使用 keychain ,而且它已经做了许多更改。我收到了世界各地开发人员编写的约 20 个高质量的补丁程序。我已将其中许多补丁代码合并入 keychain 源码中,它目前的版本是 1.8(请参阅 参考资料)。我真诚地感谢所有提交补丁程序、错误报告、功能请求及感谢信的那些人。

加强 ssh 安全性

在 上篇文章中,我花了一些时间来讨论运行 ssh-agent 在安全性方面的利弊。第二篇文章发表在 developerWorks的几天后,我收到来自 Sarnoff Corporation 的 Charles Karney 的一封电子邮件,他非常礼貌地通知了我 OpenSSH 新的认证代理程序转发的能力,我们将会简要地讨论这一能力。另外,Charles 强调:在 不可信机器上运行 ssh-agent 是十分危险的:如果有人成功地获取系统上的 root 访问权,那么就 能从 ssh-agent 中抽取您解密的密钥。即使抽取密钥有一定的困难,但是它还是在专业的解密高手的能力范围之内。而且,基本事实就是偷窃私钥是 可能的,这意味着我们应首先采取措施来防止这种情况的发生。

为了简单描述保护私钥的策略,首先必须把我们访问的机器归为两种类型中的一类。如果特定主机是安全性良好或是孤立的 ― 要成功获取主机的 root 访问权几乎不可能 ― 那么,那台机器应被认为是 可信主机。不过,如果许多其他人使用这台机器或者您怀疑系统的安全性,那么这台机器应被认为是 不可信主机。为防止您的私钥被他人抽取,绝对不应在不可信主机上运行 ssh-agent (和由此启动的 keychain )。 那样的话,即使系统安全性受到威胁,由于 ssh-agent 没有运行,闯入者在第一时间内也不能抽取密钥。

但是,这产生了一个问题。如果不能在不可信主机上运行 ssh-agent ,那么如何从这些系统上建立安全的、无密码的 ssh 连接呢?答案是:只在 可信主机上使用 ssh-agent 和 keychain ,并利用 OpenSSH 新的 认证转发能力将无密码的认证扩展到任何不可信主机上。简略地说,就是通过允许远程 ssh 会话来联系运行在可信系统上的 ssh-agent ,使认证转发工作。

认证代理程序转发

要了解认证转发工作的原理,让我们首先看一下一个假设情况,其中用户 drobbins 有一个称为 lappy 的可信的便携式电脑、一个称为 trustbox 的可信服务器和另外两个他必须访问的不可信系统,分别称为 notrust1 和 notrust2 。当前,他在所有这四台机器上都使用 ssh-agent 以及 keychain ,如下所示:

图 1. 运行在可信和不可信机器上的 ssh-agent

ssh-agent running on trusted and untrusted machines

这种方法所带来的问题是如果有人获取 notrust1 或 notrust2 的 root 访问权,那么这个人当然可以从现在易受攻击的 ssh-agent 进程中抽取密钥。为了解决这个问题, drobbins 停止运行不可信主机 notrust1 和 notrust2 上的 ssh-agent 和 keychain 。事实上,为了更为小心, drobbins 决定只在 lappy 上使用 ssh-agent 和 keychain 。这样限制了他解密的私钥的泄露,同时防止他的私钥被偷窃:

图 2. ssh-agent 只运行在 lappy 上;一个更安全的配置

ssh-agent running only on lappy; a more secure configuration

当然,这种方法带来的问题是 drobbins 现在只能从 lappy 建立无密码的连接。让我们看一下如何启用认证转发并解决这个问题。

假设所有机器都运行 OpenSSH 的最近版本,通过使用认证转发,我们能解决这个问题。认证转发允许远程 ssh 进程联系您正在本地可信机器上运行的 ssh-agent ― 而不要求在您正运行 ssh 的同一台机器上运行 ssh-agent 的一个版本。这通常允许您在单个机器上运行 ssh-agent (和 keychain ),并且这意味着源于这台机器的所有 ssh 连接(直接或间接)都将使用本地 ssh-agent 。

为了启用认证转发,我们在 lappy 和 trustbox 的 /etc/ssh/ssh_config 中添加了下面行。请注意:这是 ssh 的配置文件( ssh_config),而不是 ssh 守护进程 sshd 的配置文件( sshd_config):

清单 1. 将这行添加到 /etc/ssh/ssh_config 中

ForwardAgent Yes

现在,为了利用认证转发, drobbins 可以从 lappy 连接到 trustbox ,然后在不提供任何连接的密码的情况下,从 trustbox 连接到 notrust1 。这两个 ssh 进程都“进入”运行在 lappy 上的 ssh-agent :

清单 2. 进入 lappy

$ 
        
        ssh drobbins@trustbox
Last login: Wed Sep 26 13:42:08 2001 from lappy

Welcome to trustbox!
$ 
        
        ssh drobbins@notrust1
Last login: Tue Sep 25 12:03:40 2001 from trustbox

Welcome to notrust1!
$

如果您尝试使用类似的配置,并发现代理程序转发不起作用,请尝试使用 ssh -A 替代原来单纯的 ssh 来明确启用认证转发。这里是当我们使用上面提到的认证转发而登录到 trustbox 和 notrust1 时,实现此操作的内部运行图:

图 3. 正在运作的代理程序转发

Agent forwarding in action

正如您看到的,当 ssh 连接到 trustbox 时,它维持与运行在 lappy 上的 ssh-agent 的连接。当产生从 trustbox 到 notrust1 的 ssh 连接时,这个新的 ssh 进程维持与以前 ssh 的认证连接,这样有效地延伸了链。这个认证链是否能延伸到 notrust1 以外的其它主机取决于 notrust1 的 /etc/ssh/ssh_config 是如何配置的。 只要启用了代理程序转发,通过使用在可信 lappy 上运行的 ssh-agent ,这个链上的所有部分都能认证。

代理程序连接转发的优点

认证转发提供了许多在此没有提到的安全性优点。为了让我相信代理程序连接转发的重要性,Charles Karney 与我分享了以下三个安全性优点:

私钥只存储在可信机器上。这样防止怀有恶意的用户从磁盘获取加密的密钥并防止他们试图解加密。
ssh-agent 只运行在可信机器上。这样防止闯入者进行远程 ssh-agent 进程的内存转储并从转储中抽取出您的解密私钥。
由于您只需要在可信机器上输入密码,所以防止了任何击键记录器在您输入密码时悄悄地截取密码。

使用认证代理程序连接转发的一个缺点是:它不能解决允许 cron 作业利用 RSA/DSA 认证这个问题。解决这个问题的一个方案是设置所有需要 RSA/DSA 认证的 cron 作业,这样它们就可以从局域网中的一台可信机器上执行。如果需要的话,这些 cron 作业能使用 ssh 连接到远程系统来实现自动备份、使文件同步等操作。

既然我们已经了解了认证代理程序连接转发,那么让我们转到近期对 keychain 脚本本身所做的改进上。

keychain 功能改进

感谢用户发来补丁程序,许多重要的改进已添加到 keychain 源码中。 用户提交的 keychain 补丁程序中有几个与功能有关。例如,您应记得 keychain 创建了一个 ~/.ssh-agent 文件;这个文件的名字现在已经改为 ~/.ssh-agent-[hostname],这样 keychain 可以使用从几个不同物理主机上能访问已挂装 NFS 的主目录。除了 ~/.ssh-agent-[hostname] 文件外,现在还有一个 ~/.ssh-agent-csh-[hostname] 文件,兼容 csh 的 shell 利用 source 命令读入并执行该文件。最后,添加了一个新的 –nocolor 选项,这样,如果您碰巧在使用不兼容 vt100 的终端时,就能禁用彩色化功能部件。

Shell 兼容性修正

当完成了许多重要的功能改进时,对 shell 兼容性问题也做了大量的修正。您看,keychain 1.0 需要 bash ,而以后的版本则改为可以使用任何 sh 兼容的 shell。这一更改使得 keychain 跳出固有的框架,可以在包括 Linux、BSD、Solaris、IRIX 和 AIX 以及其它 UNIX 平台的几乎所有 UNIX 系统上运行。转至 sh 并与常规 UNIX 兼容,这已经是困难重重了,而同时它也经过了大量的学习经验。创建运行在所有这些平台上的单个脚本事实上是非常棘手的,主要因为我根本无权访问这些操作系统中的大多数系统!要感谢的是,全球范围内的 keychain 用户这样做了,并且许多人在识别兼容性问题以及提交补丁程序来解决它们等方面提供了非常大的帮助。

事实上,有两类兼容性问题必须解决。首先,我需要确信 keychain 只使用所有 sh 实现下完全支持的内置件、表达式和操作符,包括所有流行的免费和商业 UNIX sh shell、 zsh (以 sh 兼容的模式)和 bash 版本 1 和 2。这里是用户提交的应用到 keychain 源码中的一些 shell 兼容的修正:

由于较早的 sh shell 不支持 ~ 约定来引用用户的主目录,因此将使用 ~ 的行更改为使用 $HOME 来代替:

清单 3. 使之成为 $HOME

hostname=`uname -n`
pidf=${HOME}/.ssh-agent-${hostname}
cshpidf=${HOME}/.ssh-agent-csh-${hostname}

接着,所有对 source 的引用都更改成 . ,以确保与纯 NetBSD 的 /bin/sh 兼容,因为它根本不支持 source 命令:

清单 4. 迎合 NetBSD

if [ -f $pidf ]
then
    . $pidf
else
SSH_AGENT_PID="NULL"
fi

按照这个方法,我还应用了一些与性能相关的好的修正。一位聪明的 shell 脚本编写者告诉我不要通过输入 touch foo 来“更新”文件的修改日期,您可以这样做:

清单 5. 更新文件的修改日期

> foo 

通过使用内置的 shell 语法,而不是使用外部二进制文件,这样避免了使用 fork() ,而脚本却变得更加有效。 > foo 应使用任何兼容 sh 的 shell;但是,好象 ash 并不支持它。对大多数人来说这不应是个问题,因为 ash 更象是急救磁盘类型的 shell,而不是人们每天都要使用的程序。

平台可执行问题

获取在多个 UNIX 操作系统下运行的脚本不单单需要坚持纯粹的 sh 语法。请记住,大多数脚本还要调用诸如 grep 、 awk 、 ps 和其它命令的外部命令,而且必须尽可能以与标准相符的方法来调用这些命令。例如,包含在大多数 UNIX 版本中的 echo 能识别 -e 选项,而 Solaris 中的 echo 却不能识别 ― 当使用它时,它只把 -e 打印到标准输出(stdout)。因此为了处理 Solaris, keychain 现在自动检测 echo -e 是否起作用:

清单 6. 寻找 Solaris

if [ -z "`echo -e`" ]
then
    E="-e"
fi

上面的代码中,如果支持 -e ,那么将 E 设置为 -e 。然后,可以按如下所示调用 echo:

清单 7. 更好的 echo

echo $E Usage: ${CYAN}${0}${OFF} [ ${GREEN}options${OFF} ] ${CYAN}sshkey${OFF} ...

通过使用 echo $E ,而不是 echo -e ,可以根据需要动态地启用或禁用 -e 选项。

pidof,ps

可能最重要的兼容性修正涉及到更改 keychain 如何检测当前正在运行的 ssh-agent 的进程的方法。以前,我使用 pidof 命令来这样做,但是由于有几个系统没有 pidof ,所以不得不抛弃这个方案。实际上, pidof 无论如何都不是最佳的解决方案,因为它列出系统上运行的 所有 ssh-agent 进程,而不管用户是谁,但我们实际上感兴趣的是当前有效的 UID 所拥有的所有 ssh-agent 进程。

所以,为抽取所需的进程标识,我们不使用 pidof ,而是转向将 ps 输出通过管道输送到 grep 和 awk 上。 这是一个用户提交的修正:

清单 8. 管道比 pidof 好

mypids=`ps uxw | grep ssh-agent | grep -v grep | awk '{print $2}'`

上面的管线将 mypids 变量设置为当前用户拥有的所有 ssh-agent 进程的值。 grep -v grep 命令是管线的一部分,这样确保 grep ssh-agent 进程不会成为我们的 PID 列表中的一部分。

这种方法从概念上来说非常好,但是因为 ps 选项未在各类 BSD 和 System V 的 UNIX 派生系统上标准化,所以使用 ps 开启了一个全新的尚未解决的难题。这里是一个示例:虽然 ps uxw 在 Linux 下起作用,而在 IRIX 下不起作用。 ps -u username -f 在 Linux、IRIX 和 Solaris 下起作用,而在只理解 BSD 样式的 ps 选项的 BSD 下不起作用。为了解决这个问题,在执行 ps 管线之前, keychain 会自动检测当前系统的 ps 是使用 BSD 语法或还是 System V 语法:

清单 9. 检测 BSD 还是 System V

psopts="FAIL"
ps uxw >/dev/null 2>&1
if [ $? -eq 0 ]
then
psopts="uxw"
else
ps -u `whoami` -f >/dev/null 2>&1
if [ $? -eq 0 ]
then
psopts="-u `whoami` -f"
fi
fi
if [ "$psopts" = "FAIL" ]
then
echo $0: unable to use \"ps\" to scan for ssh-agent processes.  
Report KeyChain version and echo system configuration to drobbins@gentoo.org.
exit 1
fi

mypids=`ps $psopts 2>/dev/null | grep "[s]sh-agent" | awk '{print $2}'` > /dev/null 2>&1

为了确保我们能同时使用 System V 和 BSD 样式的 ps 命令,脚本试着运行 ps uxw ,而丢弃任何输出。如果这个命令的错误码为零,那么我们知道 ps uxw 正常工作,并且我们正确地设置了 psopts 值。但是,如果 ps uxw 返回一个非零的错误码(指出我们需要使用 BSD 样式的选项),那么我们试着运行 ps -u `whoami` -f ,并再次丢弃了任何输出。此时,我们有希望发现可以使用的 ps 是 BSD 的变体还是 System V 的变体。如果我们不知道答案,那么打印出错误并退出。但是很有可能这两个 ps 命令中的一个工作正常,在这样的情况下,执行上面代码段的最后一行,即 ps 管线。通过紧跟在 ps 后面使用 $psopts 变量扩展,我们能将正确的选项传送给 ps 命令。

ps 管线还包含一个 grep ,它的确是一个宝物,是 Hans Peter Verne 好心发给我的。 请注意 grep -v grep 不再是管线的一部分;实际上它已经被除去并且 grep “ssh-agent” 已经改为 grep “[s]sh-agent” 。这样一个 grep 命令最后执行与 grep ssh-agent | grep -v grep 相同的操作;您知道为什么吗?

清单 10. 简洁的 grep 诀窍

mypids=`ps $psopts 2>/dev/null | grep "[s]sh-agent" | awk '{print $2}'` > /dev/null 2>&1

是不是有点困惑?如果您确定 grep “ssh-agent” 和 grep “[s]sh-agent” 应匹配完全相同的文本行的话,那么您是正确的。所以当 ps 的输出通过管道输送给它们时,为什么它们生成不同的结果呢?这里是它的工作原理:当使用 grep “[s]sh-agent” 时,您更改了 grep 命令在 ps 进程列表中显示的方式。通过这样做,防止 grep 与它本身相匹配,因为 [s]sh-agent 字符串与 [s]sh-agent 正则表达式不匹配。那样不是很完美吗?如果您仍不太明白,请用一下 grep ,您很快就会明白了。

结束语

本专栏文章对讨论的 OpenSSH 作出了结论。希望您已经学到了有关 OpenSSH 的很多知识,足以开始使用 OpenSSH 来保护您系统的安全。

参考资料

其他参考资料

如何配置iPhone使用SSH登录

2011年7月20日

使用iPhone的各种应用时常常需要穿越。

配置iPhone在WiFi下使用VPS账号SSH登录方法。

1、确定你的iPhone已经越狱,且安装了OpenSSH和MobileTerminal。

2、下载此PAC文件,上传到iPhone的/var/mobile文件夹中。

3、在“设置”》“Wi-Fi”中设置无线网络,“HTTP代理”处选择“自动”,“URL”填“file://localhost/var/mobile/iphone.pac”。

» 阅读更多: 如何配置iPhone使用SSH登录

怎样注册.TT域名

2011年7月20日

.TT域名作为特立尼达和多巴哥国家的顶级域名,它能火起来并不是偶然的!

  • 在上千种域名后缀中,.TT域名是仅有的6个稀有双胞胎域名之一;
  • TT具有多种含义,在中文上可以理解为“天天”、“太太”、“淘淘”、“套套”等。

TT域名案例:

  • Ma.tt:WordPress的创始人Matt Mullenweg的个人独立域名博客是http://ma.tt/。正好是其名字的domain hack。
  • T.TT:罗永浩收购t.tt域名后,锤子科技启用http://t.tt域名跳转至官网。因为T的形状正象一柄锤子。
  • Mi.tt:曾被2012年的美国总统候选人Mitt Romney的参选团队用于互联网宣传的专属短网址使用。正好是其名字的domain hack。
  • Ge.tt: 实时文件分享的免费网盘。
  • G.tt:Go To Track,一个支持多个物流公司的快递查询工具网站。
  • DB.TT:为DropBox.com所持有,目前跳转至其官网。

各注册商价格:

WHOIS查询:

.TT域名注册规则:

  • .TT域名是少数开放1字符域名注册域名后缀,域名长度最短为1字符,最长为63字符,1字符.TT域名价格要稍微高一些。
  • .TT域名注册年限是至少3年,最长10年。
  • 个人和企业均可注册。

目前尚未注册的.TT域名推荐:

纯2数字tt域名:

37.tt
32.tt
82.tt
94.tt
93.tt
92.tt
84.tt
83.tt
81.tt
80.tt
75.tt
74.tt
73.tt
72.tt
71.tt
70.tt
65.tt
64.tt
63.tt
62.tt
61.tt
60.tt
57.tt
54.tt
53.tt
52.tt
51.tt
50.tt
49.tt
47.tt
46.tt
43.tt
42.tt
41.tt
40.tt
39.tt
35.tt
31.tt
30.tt
29.tt
27.tt
26.tt
24.tt
21.tt
20.tt
17.tt
16.tt
15.tt
14.tt
13.tt
10.tt
09.tt
07.tt
06.tt
05.tt
04.tt
02.tt

纯2字母tt域名:

ab.tt
gq.tt
te.tt
zx.tt
zw.tt
zv.tt
zu.tt
zt.tt
zs.tt
zr.tt
zq.tt
zo.tt
zn.tt
zm.tt
zl.tt
zk.tt
zj.tt
zi.tt
zf.tt
zd.tt
zc.tt
zb.tt
za.tt
yz.tt
yx.tt
yw.tt
yv.tt
yu.tt
yt.tt
yr.tt
yq.tt
yp.tt
yo.tt
ym.tt
yl.tt
yk.tt
yj.tt
yi.tt
yg.tt
yf.tt
ye.tt
yb.tt
ya.tt
xz.tt
xw.tt
xv.tt
xu.tt
xt.tt
xs.tt
xr.tt
xq.tt
xp.tt
xo.tt
xn.tt
xl.tt
xk.tt
xj.tt
xi.tt
xh.tt
xg.tt
xf.tt
xe.tt
xd.tt
xb.tt
xa.tt
wz.tt
wv.tt
wu.tt
wt.tt
ws.tt
wr.tt
wq.tt
wp.tt
wn.tt
wm.tt
wl.tt
wk.tt
wh.tt
wg.tt
we.tt
wd.tt
wc.tt
vz.tt
vy.tt
vx.tt
vu.tt
vt.tt
vq.tt
vp.tt
vn.tt
vm.tt
vl.tt
vk.tt
vj.tt
vi.tt
vh.tt
vg.tt
vf.tt
vd.tt
vc.tt
vb.tt
va.tt
uz.tt
uy.tt
uw.tt
uv.tt
ut.tt
us.tt
ur.tt
uq.tt
uo.tt
un.tt
um.tt
ul.tt
uk.tt
uj.tt
ui.tt
uh.tt
ug.tt
uf.tt
ue.tt
ud.tt
ub.tt
ua.tt
ty.tt
tr.tt
tq.tt
tp.tt
tl.tt
tk.tt
tj.tt
ti.tt
th.tt
tg.tt
tf.tt
td.tt
tc.tt
sz.tt
sy.tt
sx.tt
sw.tt
sv.tt
su.tt
st.tt
sr.tt
sq.tt
sp.tt
sm.tt
sl.tt
sk.tt
sg.tt
sc.tt
sb.tt
sa.tt
rz.tt
ry.tt
rx.tt
rw.tt
rv.tt
ru.tt
rt.tt
rs.tt
rq.tt
rp.tt
ro.tt
rn.tt
rm.tt
rl.tt
rk.tt
rj.tt
ri.tt
rg.tt
rf.tt
rd.tt
rc.tt
rb.tt
ra.tt
qz.tt
qy.tt
qw.tt
qv.tt
qu.tt
qt.tt
qs.tt
qr.tt
qp.tt
qo.tt
qn.tt
qm.tt
ql.tt
qk.tt
qj.tt
qi.tt
qg.tt
qf.tt
qe.tt
qd.tt
qb.tt
qa.tt
py.tt
px.tt
pw.tt
pv.tt
pu.tt
pt.tt
ps.tt
pq.tt
po.tt
pn.tt
pm.tt
pl.tt
pk.tt
pj.tt
ph.tt
pg.tt
pf.tt
pe.tt
pd.tt
pc.tt
pb.tt
pa.tt
oz.tt
oy.tt
ox.tt
ow.tt
ov.tt
ot.tt
os.tt
or.tt
oq.tt
op.tt
om.tt
ol.tt
oj.tt
oi.tt
oh.tt
og.tt
of.tt
oe.tt
od.tt
ob.tt
nz.tt
ny.tt
nw.tt
nv.tt
nu.tt
nt.tt
ns.tt
nr.tt
nq.tt
np.tt
no.tt
nm.tt
nl.tt
nk.tt
nj.tt
ni.tt
nh.tt
nf.tt
nd.tt
nc.tt
nb.tt
na.tt
mz.tt
mw.tt
mv.tt
mu.tt
mn.tt
ml.tt
mk.tt
mj.tt
mh.tt
mg.tt
md.tt
lz.tt
lw.tt
lu.tt
ls.tt
lr.tt
lq.tt
lp.tt
ln.tt
lm.tt
lk.tt
lj.tt
lh.tt
lg.tt
lf.tt
ld.tt
lc.tt
lb.tt
la.tt
kz.tt
ky.tt
kx.tt
kw.tt
kv.tt
ku.tt
kt.tt
ks.tt
kr.tt
kq.tt
kp.tt
ko.tt
kn.tt
km.tt
kl.tt
kj.tt
kh.tt
kg.tt
kf.tt
ke.tt
kc.tt
kb.tt
jz.tt
jw.tt
jv.tt
zp.tt
ed.tt
eb.tt
dy.tt
dw.tt
dv.tt
du.tt
dt.tt
ds.tt
dn.tt
dm.tt
dl.tt
dk.tt
di.tt
dh.tt
dg.tt
df.tt
de.tt
cz.tt
cy.tt
cx.tt
cv.tt
ct.tt
cr.tt
cq.tt
cp.tt
cm.tt
cl.tt
ck.tt
cj.tt
ci.tt
ch.tt
cg.tt
ce.tt
cb.tt
ca.tt
bz.tt
bx.tt
bw.tt
bv.tt
bs.tt
br.tt
bq.tt
bn.tt
bl.tt
bk.tt
bh.tt
bg.tt
bf.tt
be.tt
bc.tt
ba.tt
az.tt
ay.tt
ax.tt
aw.tt
au.tt
as.tt
ar.tt
aq.tt
ap.tt
ao.tt
an.tt
am.tt
al.tt
ak.tt
aj.tt
ah.tt
ag.tt
af.tt
ac.tt

品牌相关或优质推荐:

haosou.tt
tudou.tt
1314.tt
abc.tt
handu.tt
148365.tt
woxiu.tt
yooli.tt
daoxila.tt
haodai.tt
cnmo.tt
lenovo.tt
asus.tt
pchome.tt
yingjiesheng.tt
zhaopin.tt
ellechina.tt
self.tt
vogue.tt
mogujie.tt
onlylady.tt
pclady.tt
lvmama.tt
focus.tt
meilishuo.tt
meituan.tt
liepin.tt
elong.tt
moonbasa.tt
zhenai.tt
cntv.tt
nuomi.tt
lefeng.tt
baihe.tt
pcauto.tt
bitauto.tt
autohome.tt
zol.tt
jiayuan.tt
pconline.tt
people.tt
eastmoney.tt
360kan.tt
renren.tt
haosou.tt
1234.tt
456.tt
abcd.tt
mmm.tt
nnn.tt
bbb.tt
vvv.tt
ccc.tt
xxx.tt
zzz.tt
lll.tt
kkk.tt
jjj.tt
hhh.tt
ggg.tt
fff.tt
ddd.tt
sss.tt
ppp.tt
ooo.tt
iii.tt
uuu.tt
yyy.tt
rrr.tt
eee.tt
qqq.tt

参考资料:

T.TT
2014-05-24

又是一段传奇的故事。来自兽兽的t.tt——T.TT 卖给罗永浩锤子科技的经历

老罗的手机终于问世,在条件允许下,我就 T.TT 域名卖给罗永浩的经过写一个文章吧,就当作是对过去两年的回忆和总结。

首先,请不要再来询问这个域名的价格,我只能透露的是老罗不差钱,并且我也可以用这笔钱做很多有意义的事情,比如帮助贫困山区的孩子们,比如赚更多的钱,做更有意思的事儿。别说我俗,经营人生就是如此。

T.TT 这个域名是我在 2012 年 4 月底,去云南昆明看望前女友时,顺手拿下的。起初这个域名在一个日本人手里,根据 whois 来看,该域名在 3 月底就到期了,但由于种种原因,一直无法注册。无奈之下,我给 nic.tt (TTNIC,.tt 域名管理机构)发送了邮件并询问该域名的注册事宜,很快他们就回复我可以注册并且顺利付款。

然后我就去了昆明,那是最后一次在前女友的同意下去昆明这座城市。也许以后再也无法体会到这种青春年少时期,能为了某件事某个人如飞蛾扑火般不顾一切千里迢迢地飞奔过去的这种心情了吧哎。

好了,不提伤心事了,总之就是按照正常的程序,按照官方的标价我注册来了 T.TT (价格是 3000 美元三年,单个字符的 .tt 都是这个价格)。

之后,六月毕业,回家创业,启用 T.TT 作为通天塔博客的新域名。原本故事应该在这里结束,但是偶尔的一天,一个朋友的一封邮件,似乎预示着今后的人生就会发生一些改变。

某天,某个朋友给我发了个邮件,说是他的朋友的公司对 T.TT 这个域名感兴趣,想作为短网址,并且愿意花 10 万人民币购买。我当时就毫不犹豫地拒绝了,毕竟在我心里,T.TT 是无价的,在第一篇文章里就提到过,全世界三个叠字母的域名总共就七个,而目前开通的类似的域名就三个:c.cc g.gg t.tt

和这个朋友一直有邮件来往,并且这个公司对这个域名的报价也一直在涨,但是并没有达到我心里的价位,我也不愿意多浪费口舌在十几二十万就卖掉这个极品域名上。

一晃就是两个夏天,时间就静悄悄地过去了一年半。今年年初,该公司的副总直接联系我,约在北京见面详谈购买 T.TT 的事,在经过几轮谈判、交流、互相学习之后,我和锤子科技达成了共识,以一个不错的价格卖给了他们,时间是 2014 年 5 月初。

促使我卖掉这个域名的另外一个重要原因就是我注册到了 TTT.TT,并且觉得这个域名也很适合通天塔博客。既然锤子科技有意能把 T.TT 宣传的更广泛,那我就顺水推舟,何乐而不为呢?

是的,T.TT 这个域名我只拥有过两年,讽刺的是我和前女友也就好了两年。曾经拥有的,只是现在只剩下了回忆了吧。

一直以来,我的观念就是域名的最终目的是用来做网站,而非炒作买卖的商品,一旦一个域名找到终端客户并启用,这便是它的最好归宿。

感谢锤子科技,毕竟我一个人的能力范围有限,无法把 T.TT 传达给更广大的读者,但是锤子科技和老罗的影响力不同。我也希望有更多的朋友能知道并了解 ccTLDs (国别域名),而在所有的国别域名里,无疑类似 T.TT 这样能拿得出手的极品才是最好的宣传武器。

借着锤子科技发布会的东风,我也决定开始重新写博客,写写这些年的创业经历,分享自己的经验,以及认识更多的朋友。

域名案例:Citrix收购Cloud.com

2011年7月20日

7月13日消息,思杰系统公司(Citrix Systems)将以2亿美元至2.5亿美元的价格收购云计算产品网站Cloud.com。Cloud.com目前仅有70名员工、开发云基础设施软件,尤为重要的是他们拥有了当今最令人垂涎的云计算域名cloud.com。

著名域名投资人Frank Schilling,这个拥有诸如Antarctica.com等域名的世界最成功的通用域名投资人表示:如果cloud.com的新所有者想出售该域名的话,售价应该在300万到700万美元之间。Schilling在邮件中写到:“任何低于此售价的交易都将是对购买者的极大让利。”Schilling说:“云计算领域是一个极具竞争性的和重要的领域。在此领域运营的所有公司都想在客户心目中留下深刻印象。而Citrix正是这样一家非常懂得利用域名价值来赚钱的公司。”

尽管cloud.con可能卖到700万美元,但它仍不及去年sex.com 域名1300万美元的售价。域名日志将sex.com列为2010年全球最贵域名。就在本月,social.com以260万的价格售出。在域名日志列表中,这是今年以来域名售价的最高记录。另外,今年早些时候,曾有报道称苹果公司以450万美元购得域名icould.com。此后不久,苹果公司就开放了新的icloud存储服务。 » 阅读更多: 域名案例:Citrix收购Cloud.com

怎样在CentOS上命令行安装zip模块

2011年7月20日

A. 使用PECL安装zip

pecl install zip

参考资料:https://answers.launchpad.net/ubuntu/+question/125672

输出:

...
Build process completed successfully
Installing '/usr/local/php/lib/php/extensions/no-debug-zts-20121212/zip.so'
install ok: channel://pecl.php.net/zip-1.13.2
configuration option "php_ini" is not set to php.ini location
You should add "extension=zip.so" to php.ini

B. 使用源码编译安装zip

官网:http://pecl.php.net/package/zip

wget http://pecl.php.net/get/zip-1.13.2.tgz
tar zxvf zip-1.13.2.tgz && cd zip-1.13.2
/usr/local/php/bin/phpize   #对应的phpize路径#
./configure --with-php-config=/usr/local/php/bin/php-config #对应的php-config路径#
make
make install

生成的模块路径:

/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/zip.so   #对应的extensions路径#

在php.ini添加

[zip]
extension_dir="/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/"
extension = "zip.so"