openfire connection manager tls 配置

本文介绍了TLS配置的基础知识,包括公钥密码体制、对称加密算法、非对称加密算法以及RSA加密。通过一个加密通信过程的演化,解释了如何通过公钥和私钥确认服务器身份,并利用对称加密保证通信内容的安全。在实际应用中,数字证书解决了公钥的可信性问题,确保了证书的发布机构和公钥的对应关系。文章最后提到了自签名证书的生成步骤。

最近项目(基于openfire)里需要用tls,为了方便以后的工作,这里简单做一下记录,不罗嗦直接进入正题。

说到tls,我们就要问问为什么需要tls,原因无非是保证客户端和服务器交互的安全性。我们使用tls最初只是为了加密通信通道,后来又需要增加一个tls证书认证,让保证客户端收到的连接一定是我们的服务器发出的,也就是防止域名劫持,说到域名劫持那么我们就得了解一下DNS协议,以及域名劫持是如何发生的。下面我们就一步一步的进行一下简单的介绍。

DNS协议

参考:计算机网络 谢希仁 第5版

域名系统DNS(Domain Name System)是因特网使用的命名系统,用来把人们使用的机器名字转换为IP地址,为什么机器在处理IP数据报的时候要使用IP地址而不适用域名呢?这是因为IP地址的长度是固定的32位(IPV6是128位,也是定长的),而域名的长度是不固定的,机器使用起来比较困难。早在ARPANET时代,整个网络上都只有几百台计算机,那时候使用一个叫做hosts的文件保存域名和IP地址的映射就足够了,理论上讲,整个因特网可以只使用一个域名服务器来保存所有的域名和IP地址的映射关系就可以了,但是随着因特网的快速发展,网络上的机器数量已经大到单个服务器无法承载了,所以域名管理系统也就应运而生了。DNS系统是一个联机分布式数据库系统,采用客户服务器方式。DNS使大多数名字都在本地进行解析,仅仅只有少量的解析需要在因特网上通信,因此DNS系统的效率是很高的。而且由于这个系统是分布式的,即使系统中的某一个服务器出现了故障也不会影响系统的正常运行。


域名到IP的解析过程要点如下:当某个应用进程需要把主机名解析为IP地址时,该应用程序就调用解析程序,并成为一个DNS客户,把带解析的域名放到DNS报文中,以UDP用户数据报方式发给本地的域名服务器,本地域名服务器在查找域名之后把对应的IP地址放在应答报文中返回。详细的根域名,子域名,根域名服务器,代理授权域名服务器这些内容这里就不啰嗦详述了,我们直接来看看域名服务器的工作方式:

迭代查询


迭代查询过程:

1:主机m.xyz.com先向本地域名服务器dns.xyz.com进行查询

2:本地域名服务器采用迭代查询,它先向一个根域名服务器查询

3:根域名服务器告诉本地域名服务器,下一次应该查询顶级域名服务器dns.com的ip地址

4:本地域名服务器向顶级域名服务器dns.com进行查询

5:顶级域名服务器dns.com告诉本地域名服务器下一次应该查询的权限域名服务器dns.abc.com的ip地址

6:本地域名服务器向权限域名服务器dns.abc.com查询

7:权限域名服务器告诉本地域名服务器,所查询的主机的ip地址

8:本地域名服务器把查询结果返回给查询者


递归查询



递归查询时,本地域名服务器只需向根域名服务器查询一次,后面的几次查询都是在其他的域名服务器之间进行的,本地域名服务器从根域名服务器得到查询的ip地址。


为了提高DNS的查询效率,并减轻根域名服务器的压力和减少因特网上的DNS查询报文的数量,在域名服务器中广泛的使用了高速缓存,缓存用来存放最近查询过的域名以及从何处获得域名映射信息的记录。例如在上图迭代查询中,如果在不久前已经有用户查询过域名y.abc.com的ip地址,那么本地域名服务器就不需要向根域名服务器重新查询y.abc.com的ip地址,而是直接把缓存中上次查询的结果告诉用户。假如本地域名服务器中没有缓存y.abc.com的ip地址,而是存放着顶级域名服务器dns.com的ip地址,那么本地域名服务器也可以不向根域名服务器进行查询,而是直接向顶级域名服务器发生查询请求。这样不仅可以减轻根域名服务器的压力,而且还可以大大减少网络上的报文。由于缓存是有有效时间的,如果所有的有关的缓存信息都已经过期不存在了,那么就必须走完迭代查询的所有过程(如果使用迭代查询)。不但在本地域名服务器中需要缓存,在主机中也很需要。许多主机在启动时从本地域名服务器下载名字和地址的全部数据库,维护存放自己最近使用的域名的缓存,并且只在本地缓存中找不到记录是才使用域名服务器。

简单了解了DNS,我们再来看看DNS劫持是如何发生的(一下内容来自百度百科)
域名 劫持就是在劫持的网络范围内拦截 域名解析 的请求,分析请求的域名,把审查范围以外的请求放行,否则直接返回假的IP地址或者什么也不做使得请求失去响应,其效果就是对特定的网址不能访问或访问的是假网址。
域名解析 (DNS)的基本原理是把 网络地址 (域名,以一个字符串的形式,比如 www。google。com)对应到真实的计算机能够识别的 网络地址 (IP地址,比如216.239.53.99 这样的形式),以便计算机能够进一步通信,传递网址和内容等。
由于 域名 劫持往往只能在特定的被劫持的网络范围内进行,所以在此范围外的 域名服务器 (DNS)能够返回正常的IP地址,高级用户可以在网络设置把DNS指向这些正常的 域名服务器 以实现对网址的正常访问。所以 域名 劫持通常相伴的措施——封锁正常 DNS IP
如果知道该 域名 的真实IP地址,则可以直接用此IP代替域名后进行访问。比如访问http://www。google。com/ ,可以把访问改为http://216.239.53.99/ ,从而绕开 域名 劫持。
过程:
由于 域名 劫持只能在特定的网络范围内进行,所以范围外的域名服务器(DNS)能返回正常IP地址。攻击者正是利用此点在范围内封锁正常DNS的IP地址,使用 域名 劫持技术,通过冒充原域名以E-MAIL方式修改公司的注册域名记录,或将域名转让到其他组织,通过修改注册信息后在所指定的 DNS服务器 加进该域名记录,让原域名指向另一IP的服务器,让多数网民无法正确访问,从而使得某些用户直接访问到了恶意用户所指定的域名地址,其实施步骤如下:
一、获取劫持 域名 注册信息:首先攻击者会访问域名查询站点,通过MAKE CHANGES功能,输入要查询的域名以取得该域名注册信息。
二、控制该 域名 的E-MAIL帐号:此时攻击者会利用社会工程学或暴力破解学进行该E-MAIL密码破解,有能力的攻击者将直接对该E-MAIL进行入侵行为,以获取所需信息。
三、修改注册信息:当攻击者破获了E-MAIL后,会利用相关的MAKE CHANGES功能修改该 域名 的注册信息,包括拥有者信息,DNS服务器信息等。

四、使用E-MAIL收发确认函:此时的攻击者会在信件帐号的真正拥有者之前,截获网络公司回溃的网络确认注册信息更改件,并进行回件确认,随后网络公司将再次回溃成攻修改信件,此时攻击者成功劫持域名
(以前项目发生过域名劫持,不过是由于提供域名服务的运营商工作人员手动修改了我们的域名映射造成的)
tls协商过程简介
1、基础知识

    这部分内容主要解释一些概念和术语,最好是先理解这部分内容。

1.1、公钥密码体制(public-key cryptography)

    公钥密码体制分为三个部分,公钥私钥、加密解密算法,它的加密解密过程如下:

  • 加密:通过加密算法公钥对内容(或者说明文)进行加密,得到密文。加密过程需要用到公钥
  • 解密:通过解密算法私钥密文进行解密,得到明文。解密过程需要用到解密算法私钥。注意,公钥加密的内容,只能由私钥进行解密,也就是说,由公钥加密的内容,如果不知道私钥,是无法解密的。

    公钥密码体制公钥和算法都是公开的(这是为什么叫公钥密码体制的原因),私钥是保密的。大家都以使用公钥进行加密,但是只有私钥的持有者才能解密。在实际的使用中,有需要的人会生成一对公钥私钥,把公钥发布出去给别人使用,自己保留私钥

1.2、对称加密算法(symmetric key algorithms)

    对称加密算法中,加密使用的密钥和解密使用的密钥是相同的。也就是说,加密和解密都是使用的同一个密钥。因此对称加密算法要保证安全性的话,密钥要做好保密,只能让使用的人知道,不能对外公开。这个和上面的公钥密码体制有所不同,公钥密码体制中加密是用公钥,解密使用私钥,而对称加密算法中,加密和解密都是使用同一个密钥,不区分公钥私钥

    // 密钥,一般就是一个字符串或数字,在加密或者解密时传递给加密/解密算法。前面在公钥密码体制中说到的公钥私钥就是密钥公钥是加密使用的密钥私钥是解密使用的密钥

1.3、非对称加密算法(asymmetric key algorithms)

    非对称加密算法中,加密使用的密钥和解密使用的密钥是不相同的。前面所说的公钥密码体制就是一种非对称加密算法,他的公钥和是私钥是不能相同的,也就是说加密使用的密钥和解密使用的密钥不同,因此它是一个非对称加密算法

1.4、RSA简介

    RSA是一种公钥密码体制,现在使用得很广泛。如果对RSA本身有兴趣的,后面看我有没有时间写个RSA的具体介绍。

    RSA密码体制是一种公钥密码体制,公钥公开,私钥保密,它的加密解密算法是公开的。 由公钥加密的内容可以并且只能由私钥进行解密,并且由私钥加密的内容可以并且只能由公钥进行解密。也就是说,RSA的这一对公钥、私钥都可以用来加密和解密,并且一方加密的内容可以由并且只能由对方进行解密

1.5、签名和加密

    我们说加密,是指对某个内容加密加密后的内容还可以通过解密进行还原。 比如我们把一封邮件进行加密,加密后的内容在网络上进行传输,接收者在收到后,通过解密可以还原邮件的真实内容。

这里主要解释一下签名签名就是在信息的后面再加上一段内容,可以证明信息没有被修改过,怎么样可以达到这个效果呢?一般是对信息做一个hash计算得到一个hash值,注意,这个过程是不可逆的,也就是说无法通过hash值得出原来的信息内容。在把信息发送出去时,把这个hash值加密后做为一个签名信息一起发出去。 接收方在收到信息后,会重新计算信息的hash值,并和信息所附带的hash值(解密后)进行对比,如果一致,就说明信息的内容没有被修改过,因为这里hash计算可以保证不同的内容一定会得到不同的hash值,所以只要内容一被修改,根据信息内容计算的hash值就会变化。当然,不怀好意的人也可以修改信息内容的同时也修改hash值,从而让它们可以相匹配,为了防止这种情况,hash值一般都会加密后(也就是签名)再和信息一起发送,以保证这个hash值不被修改。至于如何让别人可以解密这个签名,这个过程涉及到数字证书等概念,我们后面在说到数字证书时再详细说明,这里您先只需先理解签名的这个概念。

2、一个加密通信过程的演化

    我们来看一个例子,现在假设“服务器”和“客户”要在网络上通信,并且他们打算使用RSA(参看前面的RSA简介)来对通信进行加密以保证谈话内容的安全。由于是使用RSA这种公钥密码体制,“服务器”需要对外发布公钥(算法不需要公布,RSA的算法大家都知道),自己留着私钥。“客户”通过某些途径拿到了“服务器”发布的公钥,客户并不知道私钥。“客户”具体是通过什么途径获取公钥的,我们后面再来说明,下面看一下双方如何进行保密的通信:

2.1 第一回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“服务器”:????

    因为消息是在网络上传输的,有人可以冒充自己是“服务器”来向客户发送信息。例如上面的消息可以被黑客截获如下:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“黑客”:你好        // 黑客在“客户”和“服务器”之间的某个路由器上截获“客户”发给服务器的信息,然后自己冒充“服务器”

“黑客”->“客户”:你好,我是服务器

    因此“客户”在接到消息后,并不能肯定这个消息就是由“服务器”发出的,某些“黑客”也可以冒充“服务器”发出这个消息。如何确定信息是由“服务器”发过来的呢?有一个解决方法,因为只有服务器有私钥,所以如果只要能够确认对方有私钥,那么对方就是“服务器”。因此通信过程可以改进为如下:

2.2 第二回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“服务器”:向我证明你就是服务器

“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

    // 意这里约定一下,{} 表示RSA加密后的内容,[ | ]表示用什么密钥和算法进行加密,后面的示例中都用这种表示方式,例如上面的{你好,我是服务器}[私钥|RSA]  就表示用私钥“你好,我是服务器”进行加密后的结果。

    为了向“客户”证明自己是“服务器”, “服务器”把一个字符串用自己的私钥加密,把明文和加密后的密文一起发给“客户”。对于这里的例子来说,就是把字符串 “你好,我是服务器”和这个字符串用私钥加密后的内容 {你好,我是男人}[私钥|RSA] 发给客户。

    “客户”收到信息后,她用自己持有的公钥解密密文,和明文进行对比,如果一致,说明信息的确是由男人发过来的。也就是说“客户”把 {你好,我是服务器}[私钥|RSA] 这个内容用公钥进行解密,然后和“你好,我是服务器”对比。因为用“服务器”用私钥加密后的内容,由并且只能由公钥进行解密,私钥只有“服务器”持有,所以如果解密出来的内容是能够对得上的,那说明信息一定是从“服务器”发过来的。

假设“黑客”想冒充“服务器”:

“黑客”->“客户”:你好,我是服务器

“客户”->“黑客”:向我证明你就是服务器

“黑客”->“客户”:你好,我是服务器 {你好,我是服务器}[???|RSA]    //这里黑客无法冒充,因为他不知道私钥,无法用私钥加密某个字符串后发送给客户去验证。

“客户”->“黑客”:????

    由于“黑客”没有“服务器”的私钥,因此它发送过去的内容,“客户”是无法通过服务器的公钥解密的,因此可以认定对方是个冒牌货!

    到这里为止,“客户”就可以确认“服务器”的身份了,可以放心和“服务器”进行通信,但是这里有一个问题,通信的内容在网络上还是无法保密。为什么无法保密呢?通信过程不是可以用公钥私钥加密吗?其实用RSA的私钥公钥是不行的,我们来具体分析下过程,看下面的演示:

2.3 第三回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“服务器”:向我证明你就是服务器

“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[公钥|RSA]

“服务器”->“客户”:{你的余额是100元}[私钥|RSA]

    注意上面的的信息 {你的余额是100元}[私钥],这个是“服务器”用私钥加密后的内容,但是我们之前说了,公钥是发布出去的,因此所有的人都知道公钥,所以除了“客户”,其它的人也可以用公钥{你的余额是100元}[私钥]进行解密。所以如果“服务器”用私钥加密发给“客户”,这个信息是无法保密的,因为只要有公钥就可以解密这内容。然而“服务器”也不能用公钥对发送的内容进行加密,因为“客户”没有私钥,发送个“客户”也解密不了。

    这样问题就又来了,那又如何解决呢?在实际的应用过程,一般是通过引入对称加密来解决这个问题,看下面的演示:

2.4 第四回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“服务器”:向我证明你就是服务器

“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

“客户”->“服务器”:{我们后面的通信过程,用对称加密来进行,这里是对称加密算法密钥}[公钥|RSA]      // 蓝色字体的部分是对称加密的算法和密钥的具体内容,客户把它们发送给服务器。

“服务器”->“客户”:{OK,收到!}[密钥|对称加密算法]

“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]

“服务器”->“客户”:{你的余额是100元}[密钥|对称加密算法]

    在上面的通信过程中,“客户”在确认了“服务器”的身份后,“客户”自己选择一个对称加密算法和一个密钥,把这个对称加密算法密钥一起用公钥加密后发送给“服务器”。注意,由于对称加密算法密钥是用公钥加密的,就算这个加密后的内容被“黑客”截获了,由于没有私钥,“黑客”也无从知道对称加密算法密钥的内容。

    由于是用公钥加密的,只有私钥能够解密,这样就可以保证只有服务器可以知道对称加密算法密钥,而其它人不可能知道(这个对称加密算法密钥是“客户”自己选择的,所以“客户”自己当然知道如何解密加密)。这样“服务器”和“客户”就可以用对称加密算法密钥来加密通信的内容了。


    总结一下,RSA加密算法在这个通信过程中所起到的作用主要有两个:

  • 因为私钥只有“服务器”拥有,因此“客户”可以通过判断对方是否有私钥来判断对方是否是“服务器”。
  • 客户端通过RSA的掩护,安全的和服务器商量好一个对称加密算法密钥来保证后面通信过程内容的安全。

    如果这里您理解了为什么不用RSA去加密通信过程,而是要再确定一个对称加密算法来保证通信过程的安全,那么就说明前面的内容您已经理解了。(如果不清楚,再看下2.3和2.4,如果还是不清楚,那应该是我们说清楚,您可以留言提问。)

    到这里,“客户”就可以确认“服务器”的身份,并且双方的通信内容可以进行加密,其他人就算截获了通信内容,也无法解密。的确,好像通信的过程是比较安全了。


    但是这里还留有一个问题,在最开始我们就说过,“服务器”要对外发布公钥,那“服务器”如何把公钥发送给“客户”呢?我们第一反应可能会想到以下的两个方法:

    a) 把公钥放到互联网的某个地方的一个下载地址,事先给“客户”去下载。

    b) 每次和“客户”开始通信时,“服务器”把公钥发给“客户”。

    但是这个两个方法都有一定的问题,

    对于a)方法,“客户”无法确定这个下载地址是不是“服务器”发布的,你凭什么就相信这个地址下载的东西就是“服务器”发布的而不是别人伪造的呢,万一下载到一个假的怎么办?另外要所有的“客户”都在通信前事先去下载公钥也很不现实。

    对于b)方法,也有问题,因为任何人都可以自己生成一对公钥私钥,他只要向“客户”发送他自己的私钥就可以冒充“服务器”了。示意如下:

“客户”->“黑客”:你好           //黑客截获“客户”发给“服务器”的消息

黑客”->“客户”:你好,我是服务器,这个是我的公钥    //黑客自己生成一对公钥私钥,把公钥发给“客户”,自己保留私钥

“客户”->“黑客”:向我证明你就是服务器

黑客”->“客户”:你好,我是服务器 {你好,我是服务器}[黑客自己的私钥|RSA]      //客户收到“黑客”用私钥加密的信息后,是可以用“黑客”发给自己的公钥解密的,从而会误认为“黑客”是“服务器”

    此,“黑客”只需要自己生成一对公钥私钥,然后把公钥发送给“客户”,自己保留私钥,这样由于“客户”可以用黑客的公钥解密黑客的私钥加密的内容,“客户”就会相信“黑客”是“服务器”,从而导致了安全问题。这里问题的根源就在于,大家都可以生成公钥私钥对,无法确认公钥对到底是谁的。 如果能够确定公钥到底是谁的,就不会有这个问题了。例如,如果收到“黑客”冒充“服务器”发过来的公钥,经过某种检查,如果能够发现这个公钥不是“服务器”的就好了。

    为了解决这个问题,数字证书出现了,它可以解决我们上面的问题。先大概看下什么是数字证书,一个证书包含下面的具体内容:

  • 证书的发布机构
  • 证书的有效期
  • 公钥
  • 证书所有者(Subject)
  • 签名所使用的算法
  • 指纹以及指纹算法

    证书的内容的详细解释会在后面详细解释,这里先只需要搞清楚一点,数字证书可以保证数字证书里的公钥确实是这个证书的所有者(Subject)的,或者证书可以用来确认对方的身份。也就是说,我们拿到一个数字证书,我们可以判断出这个数字证书到底是谁的。至于是如何判断的,后面会在详细讨论数字证书时详细解释。现在把前面的通信过程使用数字证书修改为如下:

2.5 第五回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器,这里是我的数字证书        //这里用证书代替了公钥

“客户”->“服务器”:向我证明你就是服务器

“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

    注意,上面第二次通信,“服务器”把自己的证书发给了“客户”,而不是发送公钥。“客户”可以根据证书校验这个证书到底是不是“服务器”的,也就是能校验这个证书的所有者是不是“服务器”,从而确认这个证书中的公钥的确是“服务器”的。后面的过程和以前是一样,“客户”让“服务器”证明自己的身份,“服务器”用私钥加密一段内容连同明文一起发给“客户”,“客户”把加密内容用数字证书中的公钥解密后和明文对比,如果一致,那么对方就确实是“服务器”,然后双方协商一个对称加密来保证通信过程的安全。到这里,整个过程就完整了,我们回顾一下:

2.6 完整过程:

    step1: “客户”向服务端发送一个通信请求

“客户”->“服务器”:你好

  

    step2: “服务器”向客户发送自己的数字证书。证书中有一个公钥用来加密信息,私钥由“服务器”持有

“服务器”->“客户”:你好,我是服务器,这里是我的数字证书 


    step3: “客户”收到“服务器”的证书后,它会去验证这个数字证书到底是不是“服务器”的,数字证书有没有什么问题,数字证书如果检查没有问题,就说明数字证书中的公钥确实是“服务器”的。检查数字证书后,“客户”会发送一个随机的字符串给“服务器”用私钥去加密,服务器把加密的结果返回给“客户”,“客户”用公钥解密这个返回结果,如果解密结果与之前生成的随机字符串一致,那说明对方确实是私钥的持有者,或者说对方确实是“服务器”。

“客户”->“服务器”:向我证明你就是服务器,这是一个随机字符串     //前面的例子中为了方便解释,用的是“你好”等内容,实际情况下一般是随机生成的一个字符串。

“服务器”->“客户”:{一个随机字符串}[私钥|RSA]


    step4: 验证“服务器”的身份后,“客户”生成一个对称加密算法密钥,用于后面的通信的加密和解密。这个对称加密算法密钥,“客户”会用公钥加密后发送给“服务器”,别人截获了也没用,因为只有“服务器”手中有可以解密的私钥。这样,后面“服务器”和“客户”就都可以用对称加密算法来加密和解密通信内容了。

“服务器”->“客户”:{OK,已经收到你发来的对称加密算法和密钥!有什么可以帮到你的?}[密钥|对称加密算法]

“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]

“服务器”->“客户”:{你好,你的余额是100元}[密钥|对称加密算法]

2.7 其它问题:

    上面的过程已经十分接近HTTPS的真实通信过程了,完全可以按照这个过程去理解HTTPS的工作原理。但是我为了方便解释,上面有些细节没有说到,有兴趣的人可以看下这部分的内容。可以跳过不看,无关紧要。


【问题1】上面的通信过程中说到,在检查完证书后,“客户”发送一个随机的字符串给“服务器”去用私钥加密,以便判断对方是否真的持有私钥。但是有一个问题,“黑客”也可以发送一个字符串给“服务器”去加密并且得到加密后的内容,这样对于“服务器”来说是不安全的,因为黑客可以发送一些简单的有规律的字符串给“服务器”加密,从而寻找加密的规律,有可能威胁到私钥的安全。所以说,“服务器”随随便便用私钥去加密一个来路不明的字符串并把结果发送给对方是不安全的。

〖解决方法〗每次收到“客户”发来的要加密的的字符串时,“服务器”并不是真正的加密这个字符串本身,而是把这个字符串进行一个hash计算,加密这个字符串的hash值(不加密原来的字符串)后发送给“客户”,“客户”收到后解密这个hash值并自己计算字符串的hash值然后进行对比是否一致。也就是说,“服务器”不直接加密收到的字符串,而是加密这个字符串的一个hash值,这样就避免了加密那些有规律的字符串,从而降低被破解的机率。“客户”自己发送的字符串,因此它自己可以计算字符串的hash值,然后再把“服务器”发送过来的加密的hash值和自己计算的进行对比,同样也能确定对方是否是“服务器”。


【问题2】在双方的通信过程中,“黑客”可以截获发送的加密了的内容,虽然他无法解密这个内容,但是他可以捣乱,例如把信息原封不动的发送多次,扰乱通信过程。

〖解决方法〗可以给通信的内容加上一个序号或者一个随机的值,如果“客户”或者“服务器”接收到的信息中有之前出现过的序号或者随机值,那么说明有人在通信过程中重发信息内容进行捣乱,双方会立刻停止通信。有人可能会问,如果有人一直这么捣乱怎么办?那不是无法通信了? 答案是的确是这样的,例如有人控制了你连接互联网的路由器,他的确可以针对你。但是一些重要的应用,例如军队或者政府的内部网络,它们都不使用我们平时使用的公网,因此一般人不会破坏到他们的通信。 


【问题3】在双方的通信过程中,“黑客”除了简单的重复发送截获的消息之外,还可以修改截获后的密文修改后再发送,因为修改的是密文,虽然不能完全控制消息解密后的内容,但是仍然会破坏解密后的密文。因此发送过程如果黑客对密文进行了修改,“客户”和“服务器”是无法判断密文是否被修改的。虽然不一定能达到目的,但是“黑客”可以一直这样碰碰运气。

〖解决方法〗在每次发送信息时,先对信息的内容进行一个hash计算得出一个hash值,将信息的内容和这个hash值一起加密后发送。接收方在收到后进行解密得到明文的内容和hash值,然后接收方再自己对收到信息内容做一次hash计算,与收到的hash值进行对比看是否匹配,如果匹配就说明信息在传输过程中没有被修改过。如果不匹配说明中途有人故意对加密数据进行了修改,立刻中断通话过程后做其它处理。


流程图:

现在还有一个问题就是如何保证证书的真实性,因为证书也是可以被伪造的,那么我们下面就来了解一下数字证书的相关内容。

证书的构成和原理

  ◆Issuer (证书的发布机构)

    指出是什么机构发布的这个证书,也就是指明这个证书是哪个公司创建的(只是创建证书,不是指证书的使用者)。对于上面的这个证书来说,就是指"SecureTrust CA"这个机构。


    ◆Valid from , Valid to (证书的有效期)

也就是证书的有效时间,或者说证书的使用期限。 过了有效期限,证书就会作废,不能使用了。


    ◆Public key (公钥)

    这个我们在前面介绍公钥密码体制时介绍过,公钥是用来对消息进行加密的,第2章的例子中经常用到的。这个数字证书的公钥是2048位的,它的值可以在图的中间的那个对话框中看得到,是很长的一串数字。


    ◆Subject (主题)

    这个证书是发布给谁的,或者说证书的所有者,一般是某个人或者某个公司名称、机构的名称、公司网站的网址等。 对于这里的证书来说,证书的所有者是Trustwave这个公司。


    ◆Signature algorithm (签名所使用的算法)

    就是指的这个数字证书的数字签名所使用的加密算法,这样就可以使用证书发布机构的证书里面的公钥,根据这个算法对指纹进行解密。指纹的加密结果就是数字签名(第1.5节中解释过数字签名)。


    ◆Thumbprint, Thumbprint algorithm (指纹以及指纹算法)

    这个是用来保证证书的完整性的,也就是说确保证书没有被修改过,这东西的作用和2.7中说到的第3个问题类似。 其原理就是在发布证书时,发布者根据指纹算法(一个hash算法)计算整个证书的hash值(指纹)并和证书放在一起,这个算法是不可逆的,也就是无法从hash值得出被加密的原始内容。使用者在打开证书时,自己也根据指纹算法计算一下证书的hash值(指纹),如果和刚开始的值对得上,就说明证书没有被修改过,因为证书的内容被修改后,根据证书的内容计算的出的hash值(指纹)是会变化的。 注意,这个指纹会使用"SecureTrust CA"这个证书机构的私钥用签名算法(Signature algorithm)加密后和证书放在一起。

 注意,为了保证安全,在证书的发布机构发布证书时,证书的指纹和指纹算法,都会加密后再和证书放到一起发布,以防有人修改指纹后伪造相应的数字证书。这里问题又来了,证书的指纹和指纹算法用什么加密呢?他们是用证书发布机构的私钥进行加密的。可以用证书发布机构的公钥对指纹和指纹算法解密,也就是说证书发布机构除了给别人发布证书外,他自己本身也有自己的证书。这里即使黑客截获了证书,和解密证书的公钥,他也无法对证书的内容进行修改,因为修改后的内容无法被公钥解密,如果黑客将修改的证书发送给客户端,客户端是无法用CA的公钥进行解密的,也就知道这个证书是伪造的了。证书发布机构的证书是哪里来的呢???这个证书发布机构的数字证书(一般由他自己生成)在我们的操作系统刚安装好时(例如windows xp等操作系统),这些证书发布机构的数字证书就已经被微软(或者其它操作系统的开发机构)安装在操作系统中了,微软等公司会根据一些权威安全机构的评估选取一些信誉很好并且通过一定的安全认证的证书发布机构,把这些证书发布机构的证书默认就安装在操作系统里面了,并且设置为操作系统信任的数字证书。这些证书发布机构自己持有与他自己的数字证书对应的私钥,他会用这个私钥加密所有他发布的证书的指纹作为数字签名。




举个例子方便大家理解,假设我们公司"ABC Company"花了1000块钱,向一个证书发布机构"SecureTrust CA"为我们自己的公司"ABC Company"申请了一张证书,注意,这个证书发布机构"SecureTrust CA"是一个大家公认并被一些权威机构接受的证书发布机构,我们的操作系统里面已经安装了"SecureTrust CA"的证书。"SecureTrust CA"在给我们发布证书时,把Issuer,Public key,Subject,Valid from,Valid to等信息以明文的形式写到证书里面,然后用一个指纹算法计算出这些数字证书内容的一个指纹,并把指纹和指纹算法用自己的私钥进行加密,然后和证书的内容一起发布,同时"SecureTrust CA"还会给一个我们公司"ABC Company"的私钥给到我们。我们花了1000块钱买的这个证书的内容如下:

×××××××××××××××证书内容开始×××××××××××××××××

Issuer : SecureTrust CA

Subject : ABC Company

Valid from : 某个日期

Valid to: 某个日期

Public Key : 一串很长的数字

…… 其它的一些证书内容……

{证书的指纹和计算指纹所使用的指纹算法}[SecureTrust CA的私钥|RSA]      //这个就是"SecureTrust CA"对这个证书的一个数字签名,表示这个证书确实是他发布的,有什么问题他会负责(收了我们1000块,出了问题肯定要负责任的)

×××××××××××××××证书内容结束×××××××××××××××××

               // 记不记得前面的约定?{} 表示RSA加密后的内容,[ | ]表示用什么密钥和算法进行加密

 

我们"ABC Company"申请到这个证书后,我们把证书投入使用,我们在通信过程开始时会把证书发给对方,对方如何检查这个证书的确是合法的并且是我们"ABC Company"公司的证书呢?首先应用程序(对方通信用的程序,例如IE、OUTLook等)读取证书中的Issuer(发布机构)为"SecureTrust CA" ,然后会在操作系统中受信任的发布机构的证书中去找"SecureTrust CA"的证书,如果找不到,那说明证书的发布机构是个水货发布机构,证书可能有问题,程序会给出一个错误信息。 如果在系统中找到了"SecureTrust CA"的证书,那么应用程序就会从证书中取出"SecureTrust CA"的公钥,然后对我们"ABC Company"公司的证书里面的指纹和指纹算法用这个公钥进行解密,然后使用这个指纹算法计算"ABC Company"证书的指纹,将这个计算的指纹与放在证书中的指纹对比,如果一致,说明"ABC Company"的证书肯定没有被修改过并且证书是"SecureTrust CA" 发布的,证书中的公钥肯定是"ABC Company"的。对方然后就可以放心的使用这个公钥和我们"ABC Company"进行通信了。

connection manager自签名证书生成

主要参考:http://svn.igniterealtime.org/svn/repos/connectionmanager/trunk/documentation/docs/ssl-guide.html

步骤:

1:决定所使用的服务器的域名,例如我们使用t.hotalk.com作为xmpp服务器的域名

2:进入cmd命令行,进入到connection manager的resource/security目录下,使用keytool工具,或者将此目录下的keystore文件拷贝到jdk的keytool目录(C:\Program File\java\jre6\bin)下使用

keytool -storepasswd -keystore keystore   作用修改keystore的默认密码(默认为changeit),根据提示输入新的密码,并确认

3:使用keytool生成公私密钥对和证书文件,注意这里是要对t.hotalk.com域名进行签名,所以alias的参数为t.hotalk.com,如果是其他域名直接替换就ok了。

keytool -genkey -keystore keystore -alias t.hotalk.com -validity 365 -keyalg rsa

这里要说的是,使用自签名的证书是证书会在上述命令执行的同时被生成。而如果使用CA的证书的话那么上述过程只是生成了加密证书使用的密钥对,这里validity指定证书的有效期,单位为天数,365也就是1年,keyalg指定加密算法,keytool支持rsa和dsa两种算法,还可以用keysize指定密码长度,默认为1024.

4:删除keystore中已存在的两个默认签名项

keytool -delete -keystore keystore -alias rsa

keytool -delete -keystore keystore -alias dsa

如果要删除t.hotalk.com签名项则使用keytool -delete -keystore keystore -alias t.hotalk.com

5:生成给android客户端使用中间证书文件server.cer,这个文件不会被android客户端使用,但是被android客户端使用的最终证书要由它来生成

keytool -export -alias t.hotalk.com -file server.cer -keystore keystore

6:将server.cer文件(jks格式证书)转换为BKS证书,因为android目前不支持jks格式证书,而只支持BKS格式证书,所以这里要对其进行转换。转换要依赖bcprov-jdk16-1.45.jar(jar包的版本可以去官网下载,版本自己根据所使用的jdk版本进行选择),下载该jar包后放入jdk安装目录jre6\lib\ext目录下,并将该文件的路径位置添加到系统环境变量的classpath变量中,然后使用如下命令进行转换

keytool -import -alias t.hotalk.com -file server.cer -keystore truststore -storetype BKS -providername "BC"

这里生成的BKS文件就是给android客户端使用的服务器证书文件,用来验证服务器身份。

7:配置connection manager

  • xmpp.socket.ssl.active -- set to 'true' to active SSL
  • xmpp.socket.ssl.port -- the port to use for SSL (default is 5223 for XMPP)
  • xmpp.socket.ssl.storeType -- the store type used ("JKS" is the Sun Java Keystore format used by the JDK keytool). If this property is not defined, Connection Manager will assume a value of "jks".
  • xmpp.socket.ssl.keystore -- the location of the keystore file relative to your Connection Manager installation root directory. You can leave this property blank to use the default keystore.
  • xmpp.socket.ssl.keypass -- the keystore/key password you changed in step 2.
  • xmpp.socket.ssl.truststore -- leave blank to not use a truststore, otherwise the location of the truststore file relative to your Connection Manager installation root directory.
  • xmpp.socket.ssl.trustpass -- the truststore/key password you changed in step 6. 

如果是直接使用openfire服务器的tls,参考:http://www.igniterealtime.org/builds/openfire/docs/latest/documentation/ssl-guide.html

http://community.igniterealtime.org/docs/DOC-1243



[root@yfw ~]# cd /opt/openfire [root@yfw openfire]# # 1. 编译源码 [root@yfw openfire]# mkdir -p /tmp/hello-plugin/{src,classes} [root@yfw openfire]# cp /root/openfire-plugin-build/src/main/java/com/example/restapi/RestApiPlugin.java /tmp/hello-plugin/src/ cp: cannot stat '/root/openfire-plugin-build/src/main/java/com/example/restapi/RestApiPlugin.java': No such file or directory [root@yfw openfire]# javac -d /tmp/hello-plugin/classes -cp "/opt/openfire/lib/*" /tmp/hello-plugin/src/RestApiPlugin.java javac: file not found: /tmp/hello-plugin/src/RestApiPlugin.java Usage: javac <options> <source files> use -help for a list of possible options [root@yfw openfire]# [root@yfw openfire]# # 2. 打包 [root@yfw openfire]# cd /tmp/hello-plugin/classes [root@yfw classes]# jar cvf /root/openfire-plugin-build/restapi.jar . added manifest [root@yfw classes]# [root@yfw classes]# # 3. 验证 [root@yfw classes]# jar tf /root/openfire-plugin-build/restapi.jar | grep RestApiPlugin [root@yfw classes]# # 应该输出:com/example/restapi/RestApiPlugin.class [root@yfw classes]# [root@yfw classes]# # 4. 部署 [root@yfw classes]# systemctl stop openfire [root@yfw classes]# rm -rf /opt/openfire/plugins/hello-plugin [root@yfw classes]# mkdir -p /opt/openfire/plugins/hello-plugin/{classes,lib,web} [root@yfw classes]# [root@yfw classes]# cat > /opt/openfire/plugins/hello-plugin/classes/plugin.xml << 'EOF' > <?xml version="1.0" encoding="UTF-8"?> > <plugin> > <className>com.example.restapi.RestApiPlugin</className> > <name>Hello Plugin</name> > <description>A minimal working plugin</description> > <version>1.0.0</version> > <author>Admin</author> > <minServerVersion>4.0.0</minServerVersion> > <maxServerVersion>5.0.0</maxServerVersion> > </plugin> > EOF [root@yfw classes]# [root@yfw classes]# cp /root/openfire-plugin-build/restapi.jar /opt/openfire/plugins/hello-plugin/lib/ [root@yfw classes]# chown -R openfire:openfire /opt/openfire/plugins/hello-plugin [root@yfw classes]# systemctl start openfire [root@yfw classes]# sleep 30 [root@yfw classes]# grep -i "hello-plugin\|pluginmonitor\|restapi\|loaded plugin\|found new plugin\|construct\|initialize" /opt/openfire/logs/openfire.log | tail -100 2025.05.17 22:06:19.090 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Finished processing all plugins. 2025.05.17 22:06:43.160 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.container.PluginManager - Successfully loaded plugin 'jabberbrowsing-1.0.1'. 2025.05.17 22:06:43.163 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Finished processing all plugins. 2025.05.17 22:07:28.588 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Plugin 'nodejs' was removed from the file system. 2025.05.17 22:07:28.601 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginManager - Removing all System Properties for the plugin 'NodeJs' 2025.05.17 22:07:28.602 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginClassLoader - Unloading plugin JAR file /opt/openfire/bin/../plugins/nodejs/lib/nodejs-0.1.1.jar 2025.05.17 22:07:30.696 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginManager - Successfully unloaded plugin 'nodejs'. 2025.05.17 22:11:14.780 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.container.PluginManager - Successfully loaded plugin 'presence-1.7.3'. 2025.05.17 22:11:14.783 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Finished processing all plugins. 2025.05.17 22:11:40.365 INFO [PluginMonitorExec-2]: uk.ifsoft.openfire.plugins.pade.PadePlugin - start pade server localhost:7443 2025.05.17 22:11:40.367 INFO [PluginMonitorExec-2]: org.jivesoftware.util.cache.CacheFactory - Created local-only cache [org.jivesoftware.util.cache.DefaultLocalCacheStrategy] for URL Source Content 2025.05.17 22:11:40.378 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.net.SASLAuthentication - Support added for the 'PADE' SASL mechanism. 2025.05.17 22:11:40.378 INFO [PluginMonitorExec-2]: uk.ifsoft.openfire.plugins.pade.PadePlugin - Create recordings folder 2025.05.17 22:11:40.379 INFO [PluginMonitorExec-2]: uk.ifsoft.openfire.plugins.pade.PadePlugin - Starting Openfire Meetings 2025.05.17 22:11:40.384 INFO [PluginMonitorExec-2]: org.jivesoftware.util.cache.CacheFactory - Created local-only cache [org.jivesoftware.util.cache.DefaultLocalCacheStrategy] for MUC Room Properties 2025.05.17 22:11:40.393 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.plugin.ofmeet.OfMeetPlugin - No pre-existing 'jvb' user detected. Generating one. 2025.05.17 22:11:40.495 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.plugin.ofmeet.JitsiJvbWrapper - Successfully initialized Jitsi Videobridge. 2025.05.17 22:11:40.510 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.plugin.ofmeet.OfMeetPlugin - No pre-existing 'focus' user detected. Generating one. 2025.05.17 22:11:40.566 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.plugin.ofmeet.OfMeetPlugin - Adding 'focus' user as a sysadmin to the 'conference' MUC service. 2025.05.17 22:11:40.572 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.plugin.ofmeet.JitsiJicofoWrapper - Initializing Jitsi Focus Component (jicofo)... 2025.05.17 22:11:40.673 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.plugin.ofmeet.JitsiJicofoWrapper - Successfully initialized Jitsi Focus Component (jicofo). 2025.05.17 22:11:40.680 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.plugin.ofmeet.OfMeetPlugin - Initialized public web socket for /colibri-ws web socket 2025.05.17 22:11:44.017 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.plugin.ofmeet.OfMeetPlugin - OfMeet Plugin - Initialize IQ handler 2025.05.17 22:11:46.516 INFO [PluginMonitorExec-2]: org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor 2025.05.17 22:11:46.518 INFO [PluginMonitorExec-2]: org.quartz.simpl.SimpleThreadPool - Job execution threads will use class loader of thread: PluginMonitorExec-2 2025.05.17 22:11:46.531 INFO [PluginMonitorExec-2]: org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl 2025.05.17 22:11:46.531 INFO [PluginMonitorExec-2]: org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.3.2 created. 2025.05.17 22:11:46.532 INFO [PluginMonitorExec-2]: org.quartz.simpl.RAMJobStore - RAMJobStore initialized. 2025.05.17 22:11:46.533 INFO [PluginMonitorExec-2]: org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.3.2) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED' 2025.05.17 22:11:46.533 INFO [PluginMonitorExec-2]: org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties' 2025.05.17 22:11:46.533 INFO [PluginMonitorExec-2]: org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.2 2025.05.17 22:11:46.533 INFO [PluginMonitorExec-2]: org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started. 2025.05.17 22:11:46.535 ERROR [PluginMonitorExec-2]: org.jivesoftware.openfire.muc.MultiUserChatManager - A database exception occurred while trying to load the ID for MUC service 'lobby' from the database. at org.jivesoftware.openfire.plugin.ofmeet.LobbyMuc.initialize(LobbyMuc.java:46) [pade-1.8.4.jar:?] at org.jivesoftware.openfire.plugin.ofmeet.OfMeetPlugin.initializePlugin(OfMeetPlugin.java:334) [pade-1.8.4.jar:?] at uk.ifsoft.openfire.plugins.pade.PadePlugin.initializePlugin(PadePlugin.java:118) [pade-1.8.4.jar:?] at org.jivesoftware.openfire.container.PluginMonitor$MonitorTask$4.call(PluginMonitor.java:380) [xmppserver-4.9.2.jar:4.9.2] at org.jivesoftware.openfire.container.PluginMonitor$MonitorTask$4.call(PluginMonitor.java:368) [xmppserver-4.9.2.jar:4.9.2] 2025.05.17 22:11:46.535 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.muc.MultiUserChatManager - Creating MUC service 'lobby' 2025.05.17 22:11:46.535 INFO [PluginMonitorExec-2]: org.jivesoftware.util.cache.CacheFactory - Created cache [org.jivesoftware.util.cache.DefaultLocalCacheStrategy] for MUC Service 'lobby' Rooms 2025.05.17 22:11:46.564 INFO [PluginMonitorExec-2]: org.jivesoftware.util.cache.CacheFactory - Created cache [org.jivesoftware.util.cache.DefaultLocalCacheStrategy] for MUC Service 'lobby' Room Statistics 2025.05.17 22:11:46.625 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.muc.spi.MultiUserChatServiceImpl - Rescheduling user idle task, recurring every PT15M 2025.05.17 22:11:46.625 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.muc.spi.MultiUserChatServiceImpl - 多用户聊天域:lobby.localhost 2025.05.17 22:11:46.637 INFO [PluginMonitorExec-2]: uk.ifsoft.openfire.plugins.pade.PadePlugin - Creating webauthn RelyingParty 2025.05.17 22:11:46.697 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.container.PluginManager - Successfully loaded plugin 'pade-1.8.4'. 2025.05.17 22:11:46.701 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Finished processing all plugins. 2025.05.17 22:30:01.079 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.container.PluginManager - Successfully loaded plugin 'clientcontrol-2.1.9'. 2025.05.17 22:30:01.081 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Finished processing all plugins. 2025.05.17 23:29:36.241 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.container.PluginManager - Successfully loaded plugin 'contentfilter-1.8.2'. 2025.05.17 23:29:36.242 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Finished processing all plugins. 2025.05.17 23:34:21.140 INFO [PluginMonitorExec-2]: org.jivesoftware.database.SchemaManager - 缺少 monitoring 的数据库架构。正在尝试安装… 2025.05.17 23:34:21.255 INFO [PluginMonitorExec-2]: org.jivesoftware.database.SchemaManager - 数据库更新成功。 2025.05.17 23:34:22.425 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.archive.ArchiveIndexer[CONVERSATION] - Unable to find a Lucene index in MMapDirectory@/opt/openfire/monitoring/search lockFactory=org.apache.lucene.store.NativeFSLockFactory@1c5950cc. rebuilding. 2025.05.17 23:34:22.471 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.archive.ArchiveIndexer[CONVERSATION] - Lucene index has never been modified. Removing and rebuilding. 2025.05.17 23:34:22.490 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.archive.ArchiveIndexer[MUCSEARCH] - Unable to find a Lucene index in MMapDirectory@/opt/openfire/monitoring/mucsearch lockFactory=org.apache.lucene.store.NativeFSLockFactory@1c5950cc. rebuilding. 2025.05.17 23:34:22.491 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.archive.ArchiveIndexer[MUCSEARCH] - Lucene index has never been modified. Removing and rebuilding. 2025.05.17 23:34:22.501 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.archive.ArchiveIndexer[MESSAGE] - Unable to find a Lucene index in MMapDirectory@/opt/openfire/monitoring/msgsearch lockFactory=org.apache.lucene.store.NativeFSLockFactory@1c5950cc. rebuilding. 2025.05.17 23:34:22.501 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.archive.ArchiveIndexer[MESSAGE] - Lucene index has never been modified. Removing and rebuilding. 2025.05.17 23:34:22.570 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.container.PluginManager - Successfully loaded plugin 'monitoring-2.6.1'. 2025.05.17 23:34:22.572 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Finished processing all plugins. 2025.05.17 23:39:17.737 WARN [socket_c2s-thread-6]: org.jivesoftware.openfire.net.StanzaHandler - TLS requested by initiator when TLS was never offered by server. Closing connection: NettyConnection{peer: /198.19.85.144:17098, state: CLOSED, session: LocalClientSession{address=localhost/a18ef20e-7b0c-4906-b013-6c37aa434626, streamID=4r1n9o4rrd, status=CLOSED, isEncrypted=false, isDetached=false, serverName='localhost', isInitialized=false, hasAuthToken=false, peer address='198.19.85.144', presence=' 2025.05.17 23:58:24.333 WARN [socket_c2s-thread-4]: org.jivesoftware.openfire.nio.NettyXMPPDecoder - Error occurred while decoding XMPP stanza, closing connection: NettyConnection{peer: /116.30.131.71:3545, state: OPEN, session: LocalClientSession{address=admin@localhost/Spark, streamID=9zv3etldkk, status=AUTHENTICATED, isEncrypted=false, isDetached=false, serverName='localhost', isInitialized=true, hasAuthToken=true, peer address='116.30.131.71', presence=' 2025.05.18 02:11:21.455 WARN [socket_c2s-thread-8]: org.jivesoftware.openfire.net.StanzaHandler - TLS requested by initiator when TLS was never offered by server. Closing connection: NettyConnection{peer: /64.62.156.152:23954, state: CLOSED, session: LocalClientSession{address=localhost/6a875700-1bec-4059-90ca-bfd52a7f7069, streamID=9cwwog9iyw, status=CLOSED, isEncrypted=false, isDetached=false, serverName='localhost', isInitialized=false, hasAuthToken=false, peer address='64.62.156.152', presence=' 2025.05.18 04:40:46.695 WARN [socket_c2s-thread-9]: org.jivesoftware.openfire.nio.NettyXMPPDecoder - Error occurred while decoding XMPP stanza, closing connection: NettyConnection{peer: /206.168.34.95:37108, state: OPEN, session: LocalClientSession{address=localhost/5cc2629c-6b02-4c6d-99f8-29382e47998b, streamID=80z5qip1vo, status=CONNECTED, isEncrypted=false, isDetached=false, serverName='localhost', isInitialized=false, hasAuthToken=false, peer address='206.168.34.95', presence=' 2025.05.18 06:26:35.467 WARN [socket_c2s-thread-11]: org.jivesoftware.openfire.nio.NettyXMPPDecoder - Error occurred while decoding XMPP stanza, closing connection: NettyConnection{peer: /167.94.146.61:40624, state: OPEN, session: LocalClientSession{address=localhost/01b9c3c1-172a-4139-9288-9f04327a7bef, streamID=3offa8wn3a, status=CONNECTED, isEncrypted=false, isDetached=false, serverName='localhost', isInitialized=false, hasAuthToken=false, peer address='167.94.146.61', presence=' 2025.05.18 09:42:55.040 WARN [socket_c2s-thread-2]: org.jivesoftware.openfire.nio.NettyXMPPDecoder - Error occurred while decoding XMPP stanza, closing connection: NettyConnection{peer: /198.235.24.215:53794, state: OPEN, session: LocalClientSession{address=localhost/49b2957d-33e8-47a8-998e-88f64d45d268, streamID=1sfyowwbg0, status=CONNECTED, isEncrypted=false, isDetached=false, serverName='localhost', isInitialized=false, hasAuthToken=false, peer address='198.235.24.215', presence=' 2025.05.18 09:49:00.440 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Plugin 'xmppweb' was removed from the file system. 2025.05.18 09:49:00.471 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginManager - Removing all System Properties for the plugin 'xmppweb' 2025.05.18 09:49:00.472 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginClassLoader - Unloading plugin JAR file /opt/openfire/bin/../plugins/xmppweb/lib/json-20231013.jar 2025.05.18 09:49:00.473 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginClassLoader - Unloading plugin JAR file /opt/openfire/bin/../plugins/xmppweb/lib/xmppweb-0.10.3.1.jar 2025.05.18 09:49:02.612 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginManager - Successfully unloaded plugin 'xmppweb'. 2025.05.18 09:49:25.325 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.container.PluginManager - Successfully loaded plugin 'xmppweb-0.10.3 Release 1'. 2025.05.18 09:49:25.327 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Finished processing all plugins. 2025.05.18 11:31:26.703 WARN [socket_c2s-thread-4]: org.jivesoftware.openfire.nio.NettyXMPPDecoder - Error occurred while decoding XMPP stanza, closing connection: NettyConnection{peer: /162.142.125.120:33946, state: OPEN, session: LocalClientSession{address=localhost/848fe979-91fa-43ef-9690-5bb99e2421db, streamID=ehz2xj8lv, status=CONNECTED, isEncrypted=false, isDetached=false, serverName='localhost', isInitialized=false, hasAuthToken=false, peer address='162.142.125.120', presence=' at org.apache.jasper.runtime.PageContextImpl.initialize(PageContextImpl.java:130) ~[apache-jsp-9.0.52.jar:9.0.52] 2025.05.18 19:27:55.823 WARN [socket_c2s-thread-8]: org.jivesoftware.openfire.nio.NettyXMPPDecoder - Error occurred while decoding XMPP stanza, closing connection: NettyConnection{peer: /206.168.34.37:52832, state: OPEN, session: LocalClientSession{address=localhost/2c0ba85c-47b1-442d-9cdd-df02772f77b8, streamID=apaqifrw93, status=CONNECTED, isEncrypted=false, isDetached=false, serverName='localhost', isInitialized=false, hasAuthToken=false, peer address='206.168.34.37', presence=' 2025.05.18 20:26:42.223 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.container.PluginManager - Successfully loaded plugin 'candy-0.0.0'. 2025.05.18 20:26:42.228 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Finished processing all plugins. 2025.05.18 20:39:20.427 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Plugin 'xmppweb' was removed from the file system. 2025.05.18 20:39:20.480 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginManager - Removing all System Properties for the plugin 'xmppweb' 2025.05.18 20:39:20.480 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginClassLoader - Unloading plugin JAR file /opt/openfire/bin/../plugins/xmppweb/lib/json-20231013.jar 2025.05.18 20:39:20.481 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginClassLoader - Unloading plugin JAR file /opt/openfire/bin/../plugins/xmppweb/lib/xmppweb-0.10.3.1.jar 2025.05.18 20:39:22.613 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginManager - Successfully unloaded plugin 'xmppweb'. 2025.05.18 20:39:27.493 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Plugin 'candy' was removed from the file system. 2025.05.18 20:39:27.505 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginManager - Removing all System Properties for the plugin 'Candy' 2025.05.18 20:39:27.505 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginClassLoader - Unloading plugin JAR file /opt/openfire/bin/../plugins/candy/lib/json-20231013.jar 2025.05.18 20:39:27.505 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginClassLoader - Unloading plugin JAR file /opt/openfire/bin/../plugins/candy/lib/candy-2.2.0-release-5.jar 2025.05.18 20:39:29.656 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginManager - Successfully unloaded plugin 'candy'. 2025.05.18 20:41:12.712 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Plugin 'websocket' was removed from the file system. 2025.05.18 20:41:12.713 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginManager - Removing all System Properties for the plugin 'Openfire WebSocket' 2025.05.18 20:41:12.714 WARN [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginManager - No plugin loader found for 'websocket'. 2025.05.18 20:41:47.652 WARN [PluginMonitorExec-2]: org.jivesoftware.openfire.container.PluginManager - Ignoring plugin 'websocket': compatible with server versions up to but excluding 4.2.0. Current server version is 4.9.2. 2025.05.18 20:52:43.808 INFO [PluginMonitorExec-2]: org.jivesoftware.openfire.container.PluginManager - Successfully loaded plugin 'xmppweb-0.10.3 Release 1'. 2025.05.18 20:52:43.810 INFO [PluginMonitorTask-2]: org.jivesoftware.openfire.container.PluginMonitor - Finished processing all plugins. 2025.05.18 22:22:35.615 WARN [socket_c2s-thread-3]: org.jivesoftware.openfire.nio.NettyXMPPDecoder - Error occurred while decoding XMPP stanza, closing connection: NettyConnection{peer: /119.123.129.17:8032, state: OPEN, session: LocalClientSession{address=admin@localhost/Spark, streamID=6qn9egdg8p, status=AUTHENTICATED, isEncrypted=false, isDetached=false, serverName='localhost', isInitialized=true, hasAuthToken=true, peer address='119.123.129.17', presence=' 2025.05.18 23:26:17.312 WARN [socket_c2s-thread-11]: org.jivesoftware.openfire.net.StanzaHandler - TLS requested by initiator when TLS was never offered by server. Closing connection: NettyConnection{peer: /198.19.91.156:17515, state: CLOSED, session: LocalClientSession{address=localhost/50e82849-70a1-4123-865c-908c4ce26966, streamID=3xhrg241ma, status=CLOSED, isEncrypted=false, isDetached=false, serverName='localhost', isInitialized=false, hasAuthToken=false, peer address='198.19.91.156', presence=' 2025.05.18 23:44:40.257 WARN [socket_c2s-thread-13]: org.jivesoftware.openfire.net.StanzaHandler - TLS requested by initiator when TLS was never offered by server. Closing connection: NettyConnection{peer: /65.49.20.67:27622, state: CLOSED, session: LocalClientSession{address=localhost/d886b72b-1ca4-45d9-8784-e3f2fae7fb8c, streamID=7z5651o759, status=CLOSED, isEncrypted=false, isDetached=false, serverName='localhost', isInitialized=false, hasAuthToken=false, peer address='65.49.20.67', presence=' 2025.05.19 01:12:41.159 WARN [socket_c2s-thread-15]: org.jivesoftware.openfire.net.StanzaHandler - TLS requested by initiator when TLS was never offered by server. Closing connection: NettyConnection{peer: /198.19.83.27:19319, state: CLOSED, session: LocalClientSession{address=localhost/73e0a9db-0c41-4189-9662-59afd7f80f30, streamID=amdtgcxs0g, status=CLOSED, isEncrypted=false, isDetached=false, serverName='localhost', isInitialized=false, hasAuthToken=false, peer address='198.19.83.27', presence=' 2025.05.19 05:07:10.196 WARN [socket_c2s-thread-16]: org.jivesoftware.openfire.net.StanzaHandler - TLS requested by initiator when TLS was never offered by server. Closing connection: NettyConnection{peer: /185.247.137.7:33277, state: CLOSED, session: LocalClientSession{address=localhost/9cacc3df-b485-4a54-bfb7-d114733ab1d4, streamID=81aj48psvq, status=CLOSED, isEncrypted=false, isDetached=false, serverName='localhost', isInitialized=false, hasAuthToken=false, peer address='185.247.137.7', presence=' Binary file /opt/openfire/logs/openfire.log matches [root@yfw classes]#
最新发布
10-04
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值