使用 rsync 或 unison 备份或同步支持 ssh 的 web 主机

2010/01/07 | 15:11 | 分类:Web与移动平台 | 标签: | 577次阅读

  使用 web 主机而非 VPS 的站长,站点的备份或同步常常是一个问题。很多站点只能使用 ftp 做单向备份,基于较弱的元信息来判定文件是否需要重新下载,缺乏校验、压缩、增量传输等高级特性。有的服务商在 web 控制面板中提供备份功能,或允许上传简单的 cron 脚本,但这些途径通常只适合备份整站或指定目录,而不方便以增量方式传输更新过的内容。Linux 下成熟的镜像同步工具是 rsync,如果你的 web 主机允许 ssh 登录,则可以考虑使用 rsync 或其它类似工具。
  网上有很多说法认为 web 主机不允许跑 daemon、不允许开自定义端口,故而无法使用 rsync。其实不然,rsync 可以仅通过 ssh 连接而不需要开放额外的端口,服务端也可以借助 sshd 来启动而不需要作为 daemon 运行。我们需要的只是 ssh 登录以及运行自己上传的程序的权限。我使用的 Godaddy Economy Plan Hosting (Linux) 即属于这种情况。
  Godaddy 的 web 主机不提供 rsync 程序,我们可以从本地上传一个。需要注意上传的 rsync 二进制文件应该与你的 web 主机的平台一致,连接 libc、libpopt 等库的版本一致。对于使用 x86 版 CentOS 5.2 的 Godaddy 主机,我也直接在相同版本的 CentOS 中提取了一个 rsync 上传。这时,在客户端使用“-e”参数指定连接方式为 ssh,用“--rsync-path”参数指定服务端 rsync 所在的位置,即可借助 ssh 连接传输数据了。

  1. rsync -vzrtopgl --progress --delete -e ssh --rsync-path=/[remote_home_dir]/bin/rsync [username]@[hostname]:/[remote_home_dir]/html/ /[local_home_dir]/

  如果客户端为 Windows,则可以使用 Win32 下移植的 cwRsync,这个工具基于 cygwin 库但不需要安装整个 cygwin 环境,它同时包含了 Win32 版的 OpenSSH 客户端。上述命令无须修改即可在 Windows 下运行。
  rsync 解决了文件的单向的备份或镜像功能,但如果需要双向同步,更适合的工具是 unison。unison 使用 OCaml 语言开发,基于 rsync 算法对两端文件进行比较,将它们更新到一致的状态(最新的、不冲突的版本)。unison 可借助 socket、ssh 等连接方式,并支持多种操作系统。与 rsync 类似,我们需要向 web 主机上传一个 unison 二进制文件。官方只提供了最新版的源代码,需要自行下载到本地编译(事先安装 OCaml 编译器及 etags 工具)。服务端部署之后,客户端配置文件([config_name].prf)为:

  1. root = /[local_home_dir]/html/
  2. root = ssh://[username]@[hostname]//[remote_home_dir]/html/
  3. servercmd = /[remote_home_dir]/bin/unison

  在客户端执行 ./unison [config_name] 即可完成双向同步。注意 unison 要求服务端和客户端的主次版本号一致。
  如果客户端为 Windows,同样可以使用来自 cwRsync 的 ssh 命令。如果嫌这个 ssh 外加 cygwin 库的体积太大(~5M),另一种替代的方案是使用 Putty 提供的 Plink 工具。这是一个小巧的 Win32 ssh 客户端(276K),由于运行参数与 OpenSSH 不同,因此需要写一个批处理文件(ssh.bat)来封装:

  1. @Plink.exe [hostname] -l [username] -pw [password] "/[remote_home_dir]/bin/unison -server"

  并在 unicon 配置文件中指定 ssh 命令:

  1. sshcmd = ssh.bat

  此时运行 unicon,即可使用 Plink 进行 ssh 连接。
  无论使用 OpenSSH 的 ssh 还是 Putty 的 Plink,都可以借助公钥认证方式避免密码的输入。这样有利于定时备份和同步的自动化执行。具体方法不再赘述。

让 Dropbear 更好地支持 PAM

2009/10/22 | 14:45 | 分类:Linux与开源 | 标签: | 707次阅读

  Dropbear 是一套来自澳大利亚的 *nix SSH 工具集,以体积微小著称,因此在嵌入式环境被广泛中使用。Dropbear 支持 Linux PAM,但直到目前最新的 0.52 版本,它对 PAM 的支持仍极其有限,只能做基本的身份认证(auth、account),不支持会话与密码管理(session、password)。在使用时,我发现即使是 Dropbear 已实现的 PAM 特性也存在一些不大不小的问题,需要自己动手解决。不过作者在 configure 的帮助中已经说明了现在只是“Try to include PAM support”,并且在与 PAM 相关的源代码注释中多次告知用户可以在什么地方 add、edit、hack 一些代码来满足自己特定的需求。我在编译部署 Dropbear 时,为了正常使用 PAM 认证,做了如下工作(基于 0.52 版本):
  1.开启 PAM 支持
  不要以为 configure 时加入 --enable-pam 参数就开启了 PAM 支持,仔细看 configure 输出的最后一句:Now edit options.h to choose features。我们需要自行修改 options.h,定义 ENABLE_SVR_PAM_AUTH 宏,同时将与其冲突的 ENABLE_SVR_PASSWORD_AUTH 宏注释掉,这样 PAM 相关的代码才会被启用。
  2.修正每次 PAM 会话(conversation)之后立即销毁密码的 bug
  svr-authpam.c 中的 pamConvFunc 函数实现了将客户端消息传递给服务端 PAM 的会话。为安全起见,第 119 行使用 m_burn 函数将用完的消息中的密码销毁(使用 0x66 字符覆盖)。但我们知道,在一次 pam_authenticate 调用中有可能配置了多个 PAM(pam_unix.so、pam_ldap.so……)陆续调用应用程序提供的会话函数来取用户名、密码,如果在第一次会话之后立即销毁密码,后续的会话就无法正常工作了。因此,需要等待所有 PAM 会话结束之后再销毁密码。我们可以注释掉 119 行;而 pam_authenticate 之后销毁密码的工作在 svr_auth_pam 函数中已经实现,不用新增。
  3.去除 PAM 会话函数只识别“password:”提示符为密码消息的限制
  svr-authpam.c 的第 101 行限制了密码消息的提示符为“password:”,但一些 PAM 有可能使用其它自定义的提示符,这使得 Dropbear 拒绝传送密码。事实上像 OpenSSH 等软件只是通过消息的类型为 PAM_PROMPT_ECHO_OFF 来认定其内容为密码,而不在意提示符是什么。因此,我们可以去除此处对提示符的判断,让使用自定义提示符的 PAM 也能与之兼容。
  4.解决 PAM 和基于 NSS 的用户映射无法同时工作的问题
  有的应用系统结合使用 PAM 以及 GNU C Library 提供的 NSS 特性实现应用级的用户到本地系统用户的映射。在这类系统中,用户提供给 PAM 的应用级用户名在 NSS 中被映射为本地系统级用户名,用户只持有应用级的密码而不用知道本地系统级的密码。login、OpenSSH、vsftp 等程序对此种需求的支持良好,但 Dropbear 的实现却是首先调用 getpwnam 获得本地系统级用户名(已经由 NSS 映射过的),再用这个用户名去调用 PAM 认证,这就使得 PAM 得到的是“本地系统级用户名+应用级密码”的组件,自然验证失败。我们可以修改 Dropbear 的实现,在 svr-authpam.c 的 recv_msg_userauth_request 函数中保存客户端输入的用户名,在 svr-authpam.c 的 svr_auth_pam 函数中读取前面保存的用户名,而不要使用 NSS 输出在 ses.authstate.pw_name 的本地用户名。
  所有修改如下,如果你也需要在 Dropbear 中支持 PAM 认证,可以直接打上这些 patch。我有空向 Dropbear 的作者反馈一下吧。

  1. dropbear-0.52$ cat options.h.diff
  2. 152c152
  3. < #define ENABLE_SVR_PASSWORD_AUTH
  4. ---
  5. > /*#define ENABLE_SVR_PASSWORD_AUTH*/
  6. 154c154
  7. < /*#define ENABLE_SVR_PAM_AUTH*/
  8. ---
  9. > #define ENABLE_SVR_PAM_AUTH
  1. dropbear-0.52$ cat svr-auth.c.diff
  2. 36a37,38
  3. > char client_login_username[256];
  4. >
  5. 142a145,146
  6. >     strncpy(client_login_username, username, 256);
  7. >
  1. dropbear-0.52$ cat svr-authpam.c.diff
  2. 41a42,43
  3. > extern char client_login_username[256];
  4. >
  5. 101c103
  6. <             if (!(strcmp(compare_message, "password:") == 0)) {
  7. ---
  8. >             if (/*!(strcmp(compare_message, "password:") == 0)*/ 0) {
  9. 119c121
  10. <             m_burn(userDatap->passwd, strlen(userDatap->passwd));
  11. ---
  12. >             /*m_burn(userDatap->passwd, strlen(userDatap->passwd));*/
  13. 198c200
  14. <     userData.user = ses.authstate.pw_name;
  15. ---
  16. >     userData.user = m_strdup(client_login_username);
  17. 247a250,252
  18. >     if (userData.user != NULL) {
  19. >         m_free(userData.user);
  20. >     }

Godaddy Economy Plan Hosting SSH 体验

2009/04/18 | 12:11 | 分类:Web与移动平台 | 标签: | 1,922次阅读

  我使用的是 Godaddy 的 Economy Plan Hosting (Linux) + Dedicated IP。它以前是不支持 SSH 登录管理的,不久前听说 SSH 服务已经可用,我随即开通。简单说一下试用情况。
  开通 SSH 的方法很简单。首先备份数据库,因为开通 SSH 需要将文件和数据库迁移到另一台服务器上。可以使用 Godaddy 提供的数据库备份服务(Hosting - My Hosting Account - Manage Account - Databases - MySQL,点击数据库名右边的小铅笔图标,在之后的界面就有 Backup 和 Restore 的选项),这样可以突破 phpMyAdmin 的导入/导出文件大小限制。至于主机上的文件,Godaddy 会自动迁移,不过为了保险起见建议使用 FTP 自行备份到本地,因为数据库的备份也保存在 html 目录中。备份完成之后即可在 Hosting - My Hosting Account - Manage Account - Settings - SSH 中开通 SSH 服务。开通的过程需要电话验证:填写电话号码,很快会收到一个美国长途,播出一串数字,将它们填写在网页上即可验证通过。之后需要等待若干时间,待文件迁移到新的服务器上,然后手工重建数据库并恢复原备份数据。Godaddy 会自动修改 DNS 记录以指向新的服务器 IP(但二级域名的 A 记录它没有自动帮我修改)。这时便可以使用 SSH 客户端登录了,IP、用户名、密码同 Hosting 设置。
  Economy Plan Hosting 的 SSH 自由度当然没有 Virtual Dedicated Server 的大了。首先,没有 root 权限,想开个 IPv6 隧道都不行。其次,实用程序缺一些,我的这个服务器上什么 locate、man、gcc、dig、telnet、ftp、w3m 都没有,ping 和 ssh 也没有执行权限;然而一些不怎么常用(或许在 web 开发中有用)的程序倒有一些,比如 tiff2rgba、icctrans;自己上传程序是可以的,不过要搞定动态链接库等系统依赖可能会费些周折。再次,防火墙屏蔽了 HTTP、FTP 等常规服务之外的端口,不能跑一些非 web 接口的程序或服务;我试验运行一些自己上传的二进制或 python 网络工具,却被告知 socket error: Operation not permitted。最后,sshd 的设置也比较保守,不允许 TCP 端口转发等。
  那么用户可以拿 SSH 做什么呢?我想至少可以做以下工作:1.文件管理:把私有文件转移到 html 之外的目录,通过 sftp/scp 将 10G 空间用做网盘;可以方便地压缩、解压文件,弥补 web 文件管理器和 FTP 的不足。2.数据库管理:mysql 命令行比 phpMyAdmin 灵活很多,至少没有导入/导出文件大小限制。3.使用 bash、php、python、ruby、perl 脚本做一些事:由于上述诸多限制,我们只能使用 web 接口。好在有 wget 和 curl 可用,让 bash 脚本也能有 web 输入;输出就是 html 目录,可以对用户直接呈现 web 或提供 REST API。可以使用 nohup 方式在后台跑自己的脚本,同时能够在 Hosting - My Hosting Account - Manage Account - Content - Processes 界面管理进程。当然,用脚本实时监控火车票转让信息之类的私事也可以干,不过推送信息恐怕只能用 twitter 之类提供 REST API 了。4.cron 计划任务:可以直接编辑自己的 crontab,也可以在 Hosting - My Hosting Account - Manage Account - Content - Cron Manager 界面增删 cron 作业,跑一些周期性任务,比如数据备份。这里支持 E-mail 发送作业输出文本,但执行周期最短是一个小时,恐怕用它是抢不到火车票的 :) 。上述两种后台服务方式可以结合使用,各取所长。
  总之可以看出,这个 SSH 只是用来辅助管理和维护 web 的,Godaddy 不允许用户把 web 服务器当作其它服务器使用,不希望它的主机成为用户学习 Linux 和网络配置的平台,也不能容忍它的服务器作为用户进行其它活动的代理或跳板。但只要有脚本语言的存在,我们就可以尽可能发挥想象,榨取 Godaddy Economy Plan Hosting 的每一滴油水。