Apache Qpid Broker的安全机制
一、 Apache Qpid的安全机制简介
Apache Qpid提供多种安全机制,包括用户认证、规则定制的授权、消息加密和数字签名等。Apache Qpid使用SASL框架实现对用户身份的认证,使用访问控制列表(ACL)对角色用户的权限进行管理控制,消息加密和数字签名则是使用SSL安全套接字层来实现。
二、 用户认证
AMQP使用SASL(Simple Authentication and Security Layer)对连接到Broker的每一个客户端进行身份认证。SASL是一个安全认证框架,提供多种身份认证方法。在一些对安全性有要求的应用程序中,CRAM-MD5,DIGEST-MD5,GSSAPI这三种属于安全性较高的推荐认证方法。ANONYMOUS匿名方法一般情况都不推荐,因为这是不安全的。PLAIN明文认证只有结合SSL使用,才能得到安全保证。
Apache Qpid Broker和Client是基于Cyrus SASL library。在安全要求较高的场合,要么配置SASL使用CRAM-MD5,DIGEST-MD5或GSSAPI(Kerberos 认证),要么配置SASL PLAIN + SSL。因为如果只用SASL PLAIN的话,系统会很容易遭受中间人攻击的威胁。因此,如果没有使用SSL的话,一般建议禁用PLAIN方法。
Apache Qpid Broker要启用用户认证,需要在配置文件中,把认证的开关打开。
# /usr/local/etc/qpidd/qpidd.conf
#
# Set auth to 'yes' or 'no'
auth=yes
配置SASL
SASL只在Linux系统下使用,windows下是没有的。在CentOS安装Qpid后,SASL配置文件的位置一般是/usr/local/etc/sasl2/qpidd.conf。
SASL数据库包括有用户名和密码,用于SASL认证。每一个用户名都必须要与个域(realm)关联。Apache Qpid默认使用QPID作为域。
Broker的配置文件应该增加域的配置项:
# /usr/local/etc/qpidd/qpidd.conf
#
# Set the SASL realm using 'realm='
auth=yes
realm=QPID
SASL数据库文件一般安装在位置/var/lib/qpidd/qpidd.sasldb。最初数据库文件里配置有初始用户名guest@QPID和密码guest。
为了安全,SASL数据库文件应该只能被系统用户qpidd可读。因为Qpid Broker以驻守进程执行时,一般只使用qpidd用户执行,而且SASL数据库文件保存用户和密码是明文的。因此如果用其他系统用户执行Qpid Broker,SASL数据库文件应该小心配置可见权限,或分开配置。
添加新用户到SASL数据库:
# saslpasswd2 -f /var/lib/qpidd/qpidd.sasldb -u realm new_user_name
列举所有SASL数据库里的用户:
# sasldblistusers2 -f /var/lib/qpidd/qpidd.sasldb
如果使用PLAIN认证方法,则客户端使用对应的用户和密码,即可以成功连接到Broker。如果需要使用更高安全性的认证形式,参考SASL相关文档来配置。
Kerberos
Qpid Broker和Client都是Kerberos server主体,即都是属于Kerberos服务的客户端角色。为了使用Kerberos,Broker 和Client都必须要向Kerberos服务认证。
三、 用户授权
Qpid里使用ACL即访问控制列表,对已认证通过的用户执行一些权限行为控制操作。使用—acl-file使命令加载ACL文件。ACL文件系以.acl为后缀名。
$ qpidd --acl-file ./aclfilename.acl
ACL文件的每一行显示指定授予或拒绝某些用户的行为操作权。如果最后一行是acl deny all all,那说明ACL使用的拒绝模式,只允许明确的用户被授予操作权。
acl allow rajith@QPID all all
acl deny all all
上面例子,用户rajith@QPID可以执行任务操作,其他用户则拒绝。因为ACL默认是拒绝模式的,所以上面的例子可以简化为:
acl allow rajith@QPID all all
另一种配置则是允许模式:
acl allow all all
允许模式跟拒绝模式是相反的,即拒绝该一行以上所指定的用户。允许或拒绝模式必须是ACL文件中的最后一行。
通过ACL的语法可以细化访问控制权限。如:
acl allow carlt@QPID create exchange name=carl.*
acl allow fred@QPID create all
acl allow all consume queue
acl allow all bind exchange
acl deny all all
ACL文件同样可以定义一个用户组,对一个用户组指定权限:
group admin ted@QPID martin@QPID
acl allow admin create all
acl deny all all
ACL也能定义每一个用户的连接数和队列使用配额:
group admin ted@QPID martin@QPID
group blacklist usera@qpid userb@qpid
quota connections 10 admin
quota connections 5 all
quota connections 0 blacklist
quota queues 50 admin
quota queues 5 all
quota queues 1 test@qpid
性能提示:大多数ACL查询并不是经常执行的。在创建队列时,执行的ACL规则决定是否允许或拒绝权限的负载,相对于创建和使用队列是可以忽略不计的。唯一一个比较明显的特殊情况就是发布交换器的查询操作。一个ACL文件如果没有定义发布交换器的规则,那么Broker会就近处理消息发布交换器的ACL查询。然而,如果有发布交换器规则的ACL文件,则Broker就会在每发布任意一条消息时,都会去查询ACL规则。在性能要求苛刻的环境下,一般都组织好exchanges/queue和bindings,提高性能。因此,发布交换器的ACL规则是没有必要的。
ACL语法
(略)
四、 用户连接数和队列配额
连接数限制
对于连接数限制这些设置,ACL里并没有明确指定,而是在Broker启动配置文件里。
--max-connections N
--connection-limit-per-user N
--connection-limit-per-ip N
五、 使用SSL实现加密
加密和证书授权管理,是通过Mozilla's Network Security Services Library (NSS)提供实现。
启用Qpid Broker的SSL
下列选项将在启动SSL Broker时用到
--ssl-cert-db PATH NSS证书库的地址PATH
--ssl-cert-password-file PATH NSS证书库的密码文件PATH
--ssl-cert-name NAME 将使用的证书名
--ssl-port NUMBER 将监听的SSL端口NUMBER,默认为5671
--require-encryption 强制要求Broker只接受加密连接
--listen-disable tcp 关闭对非加密TCP连接的监听
用例:
qpidd --ssl-port 41993 --ssl-cert-db ~/cert/ --ssl-cert-password-file ~/cert/password --ssl-cert-name gxxtest --listen-disable tcp --require-encryption
上述语句启动了一个:
以41993端口作为SSL端口的,
使用~/cert/目录下的NSS证书库的,
使用~/cert/password密码文件打开NSS证书库的,
使用gxxtest作为加密证书的,
不监听TCP连接的,
只接受加密连接的Qpid Broker。
注意,以上语句没有开启任何客户认证的方法。
在Qpid Client上使用SSL连接服务器
下列环境变量需要在启动Linux SSL Client前设置好
QPID_SSL_CERT_PASSWORD_FILE PATH NSS证书库的密码文件PATH
QPID_SSL_CERT_DB PATH NSS证书库的地址PATH
而Windows的Client由于代码实现和Linux的不一样,所以不需要使用NSS,而是使用系统内置的证书管理系统。所以在Windows下使用SSL连接,Broker的证书需要被系统信任。
证书设置好后,只需要在Client程序中,使用Qpid API中Connection类,初始化时将connectionOptions设置为{transport:ssl},连接端口改为服务器SSL端口即可。
以C++ API为例:
std::string connectionOptions = "{transport:ssl}";
Connection connection(broker, connectionOptions);
也可以通过在连接地址前加上“ssl:”前缀,API将会自动识别,如:
std::string broker = "ssl:localhost:5672";
Connection connection(broker, connectionOptions);
服务器CA或其签发机构应被客户端的证书管理系统信任,且连接服务器域名与证书上的认可域名一致,否则不能成功连接。
如果由于调试限制,链接地址无法与证书认可的域名一致,可以在connectionOptions中,增加ssl_ignore_hostname_verification_failure:ture,如:
std::string connectionOptions = "{transport:ssl, ssl_ignore_hostname_verification_failure:ture}";
Connection connection(broker, connectionOptions);
以上步骤都只是进行了对Broker的SSL认证,而没有对客户端进行认证。接下来的步骤将启动针对客户端的SSL认证(SSL client authentication)。
在Broker上启动SSL Client认证
下列选项将在启动Broker时用到
--ssl-require-client-authentication
用例:
qpidd --ssl-port 41993 --ssl-cert-db ~/cert/ --ssl-cert-password-file ~/cert/password --ssl-cert-name gxxtest --listen-disable tcp --require-encryption --ssl-require-client-authentication
以上语句启动了一个比“启用Qpid Broker的SSL”一节中的Broker额外多了要求进行用户SSL认证的Broker。
在Client上启动SSL Client认证
下列环境变量需要在启动Linux Client前设置好
QPID_SSL_CERT_PASSWORD_FILE PATH NSS证书库的密码文件PATH
QPID_SSL_CERT_DB PATH NSS证书库的地址PATH
而在Windows下,用户需要先将自己的证书(拥有私钥)导入到系统内置的证书管理系统中。
为了启用SSL客户端验证,应在Client程序初始化Connection类对象时,在connectionOptions中设置transport:ssl和ssl_cert_name。
用例:
std::string connectionOptions = "{transport:ssl, ssl_cert_name:client2}";
Connection connection(broker, connectionOptions);
上述语句初始化了一个
使用SSL协议传输的,
使用名为client2证书作为客户端验证证书的connection
客户端所使用的证书,应该被Broker所信任。
在Qpid Federation中启动SSL
在Broker间建立连接,需要双方都禁用TCP连接(--listen-disable tcp)才能以SSL端口进行通信。否则会形成一条源Broker:SSL端口=>目的Broker:非SSL端口的连接。
1、使用qpid-route建立Broker间的SSL链接:
qpid-route --transport=ssl link add <dest-broker> <src-broker>
用例:
qpid-route --transport=ssl link add amqps://broker1:41993 amqps://broker2:5671
上述语句建立了一条从broker2:5671到broker1:41993的SSL链接。
注意,因为qpid-route在调用qmf.console 中的BrokerURL类取得Broker的完整地址时,不会将SSL选项传递过去,所以“amqps://”不可省略。否则qpid-route将以非加密协议连接加密端口,出现连接超时失败的情况。
注意,路由是有向的。
2、使用qpid-route建立Broker间的SSL消息路由:
Queue Routes:
qpid-route --transport=ssl queue add <dest-broker> <src-broker> <dest-exchange> <src-queue>
Exchange Routes:
qpid-route --transport=ssl route add <dest-broker> <src-broker> <exchange> <routing-key>
Dynamic Exchange Routes:
qpid-route --transport=ssl dynamic add <dest-broker> <src-broker> <exchange>
用例:
qpid-route --transport=ssl dynamic add amqps://broker1:41993 amqps://broker2:5671 amq.topic
上述语句创建了一条由broker2:5671到broker1:41993的Dynamic Exchange Routes。qpid-route在创建消息路由时,会连带检查并创建链接,所以和创建链接时一样,“amqps://”不可省略。
如果broker采用SSL连接的默认端口号5671,那么端口号可以省略。
3、使用qpid-config/qpid-tool/qpid-route对启动了SSL的Broker进行管理:
用例:
qpid-tool -b amqps://localhost
qpid-config -b amqps://localhost
qpid-route route map amqps://localhost
“amqps://”不可省略。
4、对开启了SSL Client认证的Broker进行管理:
由于qpid-config/qpid-tool/qpid-route是作为Client向Broker发起连接的,所以要配置证书供Broker验证身份。下面给出例子。
qpid-config:
qpid-config --ssl-certificate=/home/chl/ca/client1.crt --ssl-key=/home/chl/ca/client1.key -b amqps://broker3:5673
qpid-route:
qpid-route --transport=ssl --ssl-certificate=/home/chl/ca/client3.crt --ssl-key=/home/chl/ca/client3.key route map amqps://broker1:5671
qpid:tool:
qpid-tool --ssl-certificate=/home/chl/ca/client3.crt --ssl-key=/home/chl/ca/client3.key -b amqps://broker2:5672
“amqps://”不可省略。--ssl-certificate所指定的证书应是被Broker信任的。