Glacier2 关于部分网友咨询的穿墙问题

常见的防火墙穿墙问题

我们假设一个客户端和服务器需要在不受信任的网络通信,并且客户端和服务器主机驻留在专用网络防火墙后面:

 

场景1:在一个典型的网络中的客户端请求。

尽管上图看起来相当简单但是存在以下问题

1、 服务器上的防火墙上必须打开专用的端口并配置为向服务器转发消息。

2、 如果服务器使用多个端点(例如,支持TCPSSL),然后防火墙端口必须为每个端点转发消息。

3、 客户端的代理必须为了使用服务器的“公共”端点而配置防火墙的主机名和专用端口。

4、 如果服务器返回一个请求的代理服务器,代理服务器不能包含服务器的专用端点,因为该端点无法访问客户端

更为复杂的情况下下面的说明在从服务器添加到客户端的回调回调意味着客户端也是一个服务器因此所有与之前的插图相关的问题在客户端同样适用

 

场景2:在一个典型网络中的回调。

如果这个场景还不够复杂下面说明添加多个客户端和服务器每个额外的服务端(包括客户端需要回调)为防火墙管理员增加为了传递请求而另开端口的工作。

 

 

场景三:多个客户端和多个服务端在典型网络中采用回调

显然,这些场景如果没有预先衡量好的话会非常复杂。幸运的是,ICE提供了Glacier2的解决方案


关于Glacier2

Glacier2ICE应用的路由防火墙最小化影响客户端和服务端(防火墙管理员)的防火墙穿越方案在下面的例子中Glacier2成为ICE应用的服务端防火墙Glacier2如何消除多个防火墙穿越的复杂性下图中描述的不是很明显

 

复杂的网络环境是一个不可争议的事实。不幸的是,确保一个企业网络的安全性而增加应用了应用程序的复杂性和管理开销。Glacier2帮助企业降低这些成本,提供高效安全的ICE应用路由。

Glacier2具有以下优点和局限性

优点

1、 使用Glacier2时,客户端程序只需要小的变化

2、 只需要一个前端端口就可以支持任意数量的服务端,Glacier2路由器很容易从一个端口转发防火墙接收连接

3、 后端服务器起的连接数减少了Glacier2扮演着连接集中器的角色为每个后端服务器建立一个单独连接传递来自客户端任何端口的请求同样来自后端服务器发送回调Glacier2为目的的连接也集中起来了。

4、 服务器不知道Glacier2的存在所以使用Glacier2的时候不需要做任何修改从服务器角度来看Glacier2只是另一个本地的客户端,因此服务器不在需要发布他们创建的代理端点。此外,后端服务例如Icegrid能继续透明的使用Glacier2的路由

5、 通过Glacier2回调不需要从客户端到服务器端建立新连接换而言之一个从客户端到服务器端的回调是基于现有的连接从而消除了在客户端防火墙支持回调的相关管理要求

6、 Glacier2不需要了解应用层定义因此是非常有效的他的路由请求和应答消息没有解析消息内容

7、 除了其转发ICE请求的基础功能,glacier2提供用户自定义Session管理和认证支持限制超时和请求缓存以及批量请求。

局限性

数据报协议不支持,如UDP

客户端回调对象的标识必须使用Glacier2提供的类型


Glacier2是如何工作的?

Ice核心支持一个通用的路由设置,由Ice::Router 接口解析这个接口允许第三方服务器拦截一个正确配置的代理请求,并将其提供给预期的服务器。Glacier2是一个该服务的实现,其他实现也是可以的。

Glacier2通常运行在一个主机的专用网络防火墙后面的的端口转发但他也可以访问公共和专用网络主机操作这种配置如下,Glacier2必须对每个网络都有端点

 

在客户端,为使用Glacier2作为路由器代理必须做配置。这种配置可以通过communicator创建的所有代理静态完成,或者以编程的方式为特定的代理。配置为使用路由的代理被称为路由代理。

当一个客户端调用一个路由代理上的操作,客户端连接到一个Glacier2的客户端点,把Glacier2当做就是服务端来发送请求。Glacier2在私有网络上建立客户端-服务器发送连接,转发到服务器的请求并返回结果(如果有)到客户端。Glacier2本质上是作为远程客户端在本地的代理。

如果服务器返回一个代理作为操作结果,该代理包含在私有网络中服务器的端点。(记住,服务器不知道Glacier2的存在因此客户端假定代理是可用的)。

在路由的情况下,客户将要尝试使用这种代理会接收到一个异常。

然而,当配置一个路由器时,客户端忽略代理的端点,而总请求发送到路由器的客户端点。

在私有网络中的Glacier2的服务器端点,仅当服务器回调客户端的时候使用。


开始使用Glacier2

使用glacier2

在使用glacier2最小配置包括下列任务

为路由器写一个配置文件

为路由器写一个密码文件glacier2还支持其他的方式对用户进行身份验证

决定是否使用路由器的内部会话管理器,或者提供自己的会话管理器。

一个主机上启动路由器访问公共和私有网络

修改客户端配置使用上路由器

修改客户端创建路由会话

确保路由器会话保持活跃只要客户端需要他

 

配置路由器

下面的路由器配置属性建立必要的端点,并定义当一个会话到期的时间:

Glacier2.Client.Endpoints=tcp -h 5.6.7.8 -p 4063

Glacier2.SessionTimeout=60

Glacier2.Client.Endpoints定义的端点被Ice运行环境用来客户端直接与路由器进行交会他也是从路由器代理发送请求的端点这个端点必须在公用网络接口上定义因为它必须能被客户端访问此外端点使用一个固定的端口因为客户端可能会被静态地配置为这个端点代理端口号4063Tcp)和4064SSL)是互联网数字分配结构分配给glacier2专用的。

为了使用Glacier2的路由器客户端必须创建会话我们配置Glacier2.SessionTimeout属性是使路由器销毁已经闲置了60s的会话。它不是强制性定义的一个超时,但他是建议,否则会话状态可能会在路由器中积累。

请注意此配置使路由器能够将客户端的请求转发给服务器其他配置以支持从服务器到客户端的回调

你还必须决定使用哪一种身份验证方案一个基于文件的机制是可用的也可以用其他更复杂的策略如果客户端通过路由器访问一个位置服务额外的路由器配置通常也是必须的

 

创建一个密码文件

路由器最简单的身份验证机制就是建立一个用户名和密码对组成的访问控制列表文件。密码是使用模块化的加密编码方式(MCF)。

一个MCF的一般结构编码的密码散列标识符$标识$内容,这里的标识符标识用哈希方案,

内容是指他的内容。Glacier2支持两种类型的MCF编码的密码哈希值:

windowsos x下:

PBKDF2 使用SHA-1, SHA-256, 或者SHA-512摘要算法

· $pbkdf2-digest$rounds$salt$ for SHA-256 and SHA-512.

· $pbkdf2$rounds$salt$ for SHA-1.

linux下:

 SHA-256SHA-512摘要算法

Glacier2.CryptPasswords属性指定密码文件。

Glacier2.CryptPasswords=passwords

密码文件的格式相当简单。每个用户名密码对为一行,用空格分隔。例如,下面密码文件包含一个用户名密码测试条目:

test $5$rounds=110000$5rM9XIDChkgEu.S3$ov7yip4NOi1wymAZmamEv1uKPQRB0WzasoJsWMpRT19

ICE散列密码帮助脚本

你可以使用ice散列密码帮助脚本生成这些用户名密码对。这个脚本需要pythonpip的支持。要安装此脚本运行:

pip install zeroc-icehashpassword

现在你可以使用命令icehashpassword

> icehashpassword

Password:

$5$rounds=110000$5rM9XIDChkgEu.S3$ov7yip4NOi1wymAZmamEv1uKPQRB0WzasoJsWMpRT19

您还可以指定几个可选参数:

-d MESSAGE_DIGEST_ALGORITHM, --digest=MESSAGE_DIGEST_ALGORITHM

-s SALT_SIZE, --salt=SALT_SIZE

-r ROUNDS, --rounds=ROUNDS

例如:

> python icehashpassword.py -r 25000 -s 32 -d sha256

Password:

$pbkdf2-sha256$25000$pJSSEuKcs9aaE.J8711LyRlD6H0P4Tyn9J7znpNyLsU$Yx7NNLDfwwLeMbZV84X2rBYBnvrXvK/TDIQiIGabQIM

注意icehashpasswordwindows或者OS X上生成PBKDF2哈希与在linux上。

 

启动路由器

路由器支持以下命令行选项:

$ glacier2router -h

Usage: glacier2router [options]

Options:

-h, --help     Show this message.

-v, --version  Display the Ice version.

--nowarn       Suppress warnings.

当启动时路由器无法连接到权限验证对象或会话管理器时候,--nowarn选项能隐藏路由器启动时的警告信息。

其他命令行选项的支持,包括那些允许路由器作为windows的服务运行或者Unix的守护进程,ice有使用程序帮助你将路由器作为Windows的服务来安装。

假使我们配置属性存储在一个config的文件中,你可以通过如下指令启动路由器:

$ glacier2router --Ice.Config=config

 

配置Glacier2客户端

以下属性配置一个使用Glacier2路由器的客户端:

Ice.Default.Router=Glacier2/router:tcp -h 5.6.7.8 -p 4063

Ice.RetryIntervals=-1

 

Ice.Default.Router属性定义路由器代理,它的端点必须与Glacier2.Client.Endpoints相匹配。

设定Ice.RetryIntervals属性为-1,不允许自动重试。

 

Glacier2对象标识

一个Glacier2路由器主机有两个公共对象。这两个对象的默认身份标识为Glacier2/routerGlacier2/admin,Glacier2::Router Glacier2::Admin接口一一对应。如果一个应用程序想使用多个不同路由器,指定唯一的标识这些对象属性的不通知的glacier2.instancename配置路由器是一个好办法,举例:

Glacier2.InstanceName=PublicRouter

这个属性改变对象标识的范畴,成为PublicRouter/routerPublicRouter/admin。客户端的配置也必须要改变,以适应新的标识:

Ice.Default.Router=PublicRouter/router:tcp -h 5.6.7.8 -p 4063:tcp -h 6.10.7.8 -p 4063

 

创建一个Glacier2的会话

会话管理是由Glacier2::Router接口提供:

Slice

module Glacier2 {

    exception PermissionDeniedException {

        string reason;

    };

    interface Router extends Ice::Router {

        Session* createSession(string userId, string password)

            throws PermissionDeniedException,

                   CannotCreateSessionException;

        Session* createSessionFromSecureConnection()

            throws PermissionDeniedException,

                   CannotCreateSessionException;

        idempotent string getCategoryForClient();

        void refreshSession()

            throws SessionNotExistException;

        void destroySession()

            throws SessionNotExistException;

        idempotent long getSessionTimeout();

        idempotent int getACMTimeout();

    };

};

这个接口定义了两个创建会话的操作:createSessioncreateSessionFromSecureConnection路由器要求每个客户端使用其中一个操作创建会话,只有当会话已经创建路由器才能代表客户端转发请求。

createSession操作需要一个用户名和密码,根据路由器的配置,返回其中一个session的代理或者空。当使用默认的身份验证方案时,给定的用户名和密码必须与路由器的密码文件中的条目相匹配才能创建会话。

createSessionFromSecureConnection方法不需要用户名和密码,因为他的客户端认证是基于SSL的证书。

创建一个会话,客户端通常从communicator获得路由器代理,强制将代理转型为Glacier2::Router接口类型,并调用其中一个创建方法。下面的实例代码演示C++中是如何操作的,在其他语言中代码写法也相似。

C++

Ice::RouterPrx defaultRouter = communicator->getDefaultRouter();

Glacier2::RouterPrx router = Glacier2::RouterPrx::checkedCast(defaultRouter);

string username = ...;

string password = ...;

Glacier2::SessionPrx session;

try

{

    session = router->createSession(username, password);

}

catch(const Glacier2::PermissionDeniedException& ex)

{

    cout << "permission denied:\n" << ex.reason << endl;

}

catch(const Glacier2::CannotCreateSessionException& ex)

{

    cout << "cannot create session:\n" << ex.reason << endl;

}

如果路由器配置了会话管理器,createSessioncreateSessionFromSecureConnection操作可能返回一个实现了Glacier2::Session接口的代理对象(或者一个应用程序特定的派生接口)。如果没有配置会话管理器,则客户端接收一个空代理。

由创建操作返回的非空会话代理对象必须与创建它的路由器进行配置,因为会话对象仅通过路由器访问。如果路由器被配置为客户端默认路由器的时候,createSessioncreateSessionFromSecureConnection被调用,如上面的例子中,会话代理已经正确配置所以客户端不需要别的配置。否则,客户端必须使用ice_router代理方法显示配置会话代理和路由器。

如果客户端想主动结束会话,它必须在路由器代理上调用destroySession方法。如果一个客户端没有结束会话,路由器会在session过期时自动销毁它。客户端可以通过调用getSessionTimeout方法获得session不活动的时间,如果有必要可以通过定期调用refreshSession来保持会话。一个更简单的解决方法来保持会话是调用getACMTimeout并且使用这个值来配置客户端连接路由器的活动连接管理行为:

int acmTimeout = router->getACMTimeout();

if (acmTimeout > 0) {

    Ice::ConnectionPtr conn = router->ice_getCachedConnection();

    conn->setACM(acmTimeout, IceUtil::None, Ice::HeartbeatAlways);

}

客户端调用getACMTimeout(Ice3.6新特性)获取路由器服务器端的ACM超时时间,并将这个值传递给这个路由器的连接的setACM方法。从而保证了客户端和路由器都使用一致的值设置。客户端也能自动保持心跳连接,所以能保持活动的连接,不会被路由器的ACM从服务器端关闭连接。

或者,你可以配置客户端的ACM利用Ice.ACM.TimeoutIce.ACM.Heartbeat属性。请注意,这些属性影响所有客户端的连接。一般来说,我们建议直接配置连接,就像上面那样。

getCategoryForClient方法被用于在双向连接中实现回调函数。

 

Glacier2会话过期

一个glacier2的路由器可能被配置为在一段时间不活动后就销毁。这个特性允许路由器以及一个自定义会话管理器来回收会话中的资源,但是它要求路由器和它的客户端之间的协调。

理想的情况下,你会选择一个足够长的时间来适应你的客户端使用。例如,一个每5秒调用服务器端操作的客户端选择会话超时时间为30秒是合理的选择。然而,超时可能造成一个不同客户端的长时间不活动,如调用的时候需要进行人机交互。

如果你不能肯定你的客户端使用模式,我们建议配置超时时间长一点,以免会话过期。最简单的解决方案是启用活动连接管理的心跳功能,其中Ice运行会定期自动发送心跳消息。Glacier2的路由器将心跳消息理解为客户端仍旧是活跃的,并且希望继续保持会话。ACM的设置可以配置所有的被通信器创建的连接,或单独为一个特定的连接。小心确保客户端的ACM超时时间和路由器的会话超时时间兼容。

注意:如果一个会话超时,下一个客户端调用会造成ConnectionLostException要重新建立会话,客户端必须显示地重建它。如果客户端使用回调函数,它也需要重新创建毁掉是配置并且重新注册他的回调服务。

 

Glacier2会话销毁

一个路由器会话过期或者客户端主动销毁的时候,会话会被销毁。如果在试图连接时报错路由器也会销毁一个会话。这些错误以Run-time exception,SocketException,TimeoutExceptionProtocolException的方式展现。换而言之,如果当glacier2试图建立到后端服务器连接时候发生这些异常,或者传递请求到目的服务端的时候产生异常,路由器都会自动销毁这些会话。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值