再谈SSH隧道技术(二)- 如何实现SSH隧道热备份

通过上一篇的介绍,我们会发现当SSH隧道建立好以后还需要很多配置工作。为了能让隧道在断开后自动恢复,就需要找到一种方法在建立SSH隧道的同时自动完成这些工作。接下来我们将用两个小章节来分别介绍在服务器端和客户端所使用的方法。

自动配置隧道的服务器端

众所周知,在Unix的世界里一项工作有不止一种方法可以完成。这里仅仅给出一种我自己比较喜欢的做法,使用SSH公私钥认证文件~/.ssh/authorized_key来帮助我们完成服务器端的配置工作。接下来的讨论需要你对SSH公私钥认证体系有基本的了解,如果你对这个概念还不清楚,可以参考我的 如何实现安全的免密码ssh登录

首先,我们来看一个配置好的~/.ssh/authorized_key:

no-port-forwarding,no-pty,command=”/root/.ssh/tap-setup” ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2389WXZZmIIArz6GGyNu/O3TLURtnMgYtsRwTB+VRyN0+RSPhGxIsEPcBI56Wt5DWWInFL711k1m3JCSIZbpagpPCsjWUKvBWHsWfi+JOJBk8aZKvK4rHMkxAVmyAZPSjhR93CiLLnqhIftog/Wb1P2AJSIkpRSKW1oe0CWpH7YiIOYA/9bloHPzOe1yUXp5bmqOOmOPopT26QpuhdAlFAvisEHKTBvpoiRsmhI2Aj7pP2kPQZhqZhGQ5ba/iUw2jMvSyS9FBkoZZbLdtch9wCghnRMPdiuZDvLJ9jwhZIjS+LGhzgGFIyIg4QAkeetHT1k7IxE2JCQDRPPIaZUCyQ== jianingy@nby

与普通的公钥串相比,上面的公钥串在ssh-rsa前面多出了一些参数。它们可以对使用这个公钥验证的用户做出一些限制,这里的几个参数含义如下:

  • no-port-forwarding 对于使用该公钥认证的用户,不允许做端口转发。
  • no-pty 对于使用该公钥认证的用户,不分配伪终端(PTY)。
  • command=”/root/.ssh/tap-setup” (最关键)对于使用该公钥登陆的用户,强制执行脚本/root/.ssh/tap-setup。而用户在登陆时给出的执行命令,将被保存在环境变量SSH_ORIGINAL_COMMAND中。

下面,我们来实现tap-setup脚本。这个脚本需要两类参数。第一,我们需要知道服务器端的tap设备的名字。第二,我们需要知道服务器端tap设备的IP信息。这两类参数都会通过SSH客户端,借助SSH_ORIGINAL_COMMAND环境变量传递给tap-setup脚本。

#!/bin/bash
# author: jianingy.yang (AT) gmail.com

set $SSH_ORIGINAL_COMMAND

device=$1
ipaddr=$2
netmask=${3:-255.255.255.0}

if [ -z "$device" -o -z "$ipaddr" ]; then
  echo "not enough arugments" 2>&1
  exit 255
fi

retries=3
while ! ifconfig $device $ipaddr netmask $netmask
do
  [ $retries -lt 0 ] && break
  ((--retries))
  sleep 5
done

有了tap-setup脚本之后,我们就可以通过如下命令发起SSH连接了。tap-setup会在连接建立好以后帮我们做好服务器端的设置

ssh -w 1:100 -o Tunnel=Ethernet root@server "tap100 192.168.1.250 255.255.255.0"

在客户端自动配置隧道

谈到客户端自动重连SSH的方法,我个人比较喜欢用djb的daemontools。这个工具简单、方便并且还很易于管理多个隧道连接。当然,如果需要一切从简,也可以将一个带有while循环的脚本放在后台去执行。但无论如何我们都要能够在隧道建立成功后进行本地虚拟设备的配置。这里,介绍一个使用SSH客户端LocalCommand参数来进行配置的方法。

LocalCommand用来指定一个在SSH连接建立好以后在本地执行的命令。我们可以将所需的配置包裹在一个脚本中,然后通过LocalCommand来适时地调用我们的脚本。例如,采用如下SSH连接命令可以在连接成功后调用tap-up脚本。

ssh -o PermitLocalCommand=yes -o LocalCommand="./tap-up" -o Tunnel=Ethernet -w 100:1 hostname 

tap-up则可以是类似下面的实现。

retries=3
while ! ifconfig tap1 192.168.1.10 netmask 255.255.255.0
do
  [ $retries -lt 0 ] && break
  ((--retires))
  sleep 5
done

最后,结合我在 SSH隧道技术简介 里面“检查隧道状态”的部分,我们可以让隧道在检测出异常状态时中断并重新连接。

通过bonding模块进行隧道热备份

虽然SSH隧道在意外中断后可以自动重连,但连接终究还是会中断。为了实现“不间断服务”,让我们来借力于Linux的Bonding模块吧。Bonding模块用来将多个二层设备绑定在一起协同工作。它支持很多种工作模式,其中active-backup模式用来在多个二层设备之间进行热备份。举例来说,如果我们将eth0和eth1的物理接口连接在同一个交换机上。然后通过bonding模块将eth0和eth1绑定在一个称作bond0的虚拟设备上。默认情况下,eth0会做为bond0的主设备(Primary)工作。而一旦eth0设备出现问题bonding模块可以在毫秒级别上检测到设备失败并切换到eth1上工作。在这期间已经建立好的TCP链接并不会断开,而只是承受少量的TCP重传。

另人庆幸的是bonding模块只要求被绑定的设备是一个二层设备。因此,SSH创建的二层隧道也可以通过Bonding模块进行绑定从而享受热备份带来的好处。

假设,我们已经创建了两个机器间的两个相同的隧道设备tap100和tap101。我们可以用如下命令在隧道两端制作Bonding虚拟设备。

在客户端:

sudo modprobe bonding mode=active-backup arp_interval=100 arp_ip_target=192.168.1.250
ifenslave bond0 tap100
ifenslave bond0 tap101
ifconfig bond0 192.168.1.10 netmask 0xffffff00

服务器端:

sudo modprobe bonding mode=active-backup arp_interval=100 arp_ip_target=192.168.1.10
ifenslave bond0 tap100
ifenslave bond0 tap101
ifconfig bond0 192.168.1.250 netmask 0xffffff00

modprobe执行的时候向bonding模块传递了3个参数,他们的含义如下:

  • mode bonding设备工作模式,这里使用active-backup也就是热备份模式
  • arp_ip_interval 通过ARP包检测设备联通状态的检测间隔,单位是毫秒。
  • arp_ip_target 通过ARP包检测设备联通状态时,用以发送ARP查询的地址。

模块加载好以后,便可以使用ifenslave命令(该命令一般需要单独安装)来将参与热备的设备加入到bond0中。最后,再为bond0设置好IP地址,整个配置过程就完成了。

模块加载的部分和bond设备IP地址的配置都可以被放到系统启动时完成。对于ifenslave操作,则可以被我们分别放到服务器端和客户端的重连脚本里。这样一来即使隧道处于断开重连状态中,只要还有可工作的隧道存在bond0设备就会一直有效,其上的TCP连接也都能继续保持。

到此为止?

当然不是:)。通过这两篇对SSH隧道的介绍,你应该已经掌握了建立稳定SSH隧道的方法。但仍有很多细节问题需要进一步考察。也许你已经发现了bonding设备的balance-rr模式可以提高SSH隧道的吞吐量,也许你在思考如何在一台服务起上建立多个bonding设备等等。有关SSH隧道及其相关的更多问题我会争取在以后的博文中再逐一解释。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值