MSNP8协议解析以及对客户端的模拟实现

      由于现所在的公司的应用需要,因而有机会自己接触到了MSN 通信协议。前2周左右的时间里,自己完成了部分的功能,算是对协议的一次验证吧。在此贴出本文,希望能有抛砖引玉之效,言归正传吧。

 

      与客户端交互的MSN的服务器种类有三种:分派服务器(Dispatch Server, DS),通知服务器(Notification Server, NS),以及接线服务器(Switchboard Server, SS)。相关定义介绍可以看这里http://ericzhi-room.spaces.live.com/blog/cns!A1EE72D8F7FD1!217.entry?sa=842045214 。

 

  MSN 客户端登陆过程如下(以MSNP8为例)

MSN 客户端登陆步骤
1. 以TCP连接到(DS)messenger.hotmail.com:1863,发送指令:
   C>> VER 1 MSNP11 CVR0(\r\n)
   DS<< VER 1 MSNP11
   
2. 客户端发送CVR指令说明当前使用的环境
   C>> CVR 2 0x0804 win 5.1.2600 i386 MSNMSGR 7.0.0813 MSMSGS [email protected]
   DS<< CVR 2 1.0.0000 1.0.0000 1.0.0000 
        http://msgr.dlservice.microsoft.com http://download.live.com/?sku=messenger
3. 客户端发送USR说明身份
   C>> USR 3 TWN I [email protected]
   DS>> XFR 3 NS 207.46.124.105:1863 0 64.4.9.254:1863
   //第三个参数为NS服务器的通讯地址,第五个是当前连接的服务器IP与端口
4. 客户端关闭与以上DS的连接
   C>> OUT
5. 客户端与NS服务器建立连接,发送之前的指令消息:
   C>> VER 1 MSNP11 CVR0(\r\n)
   NS<< VER 1 MSNP11
   
   C>> CVR 2 0x0804 win 5.1.2600 i386 MSNMSGR 7.0.0813 MSMSGS [email protected]
   NS<< CVR 2 1.0.0000 1.0.0000 1.0.0000 
        http://msgr.dlservice.microsoft.com http://download.live.com/?sku=messenger
   
   C>> USR 3 TWN I [email protected]
   NS<< USR 3 TWN S ct = 127137673, rver=5.5.4182.0, wp=
        FS_40SEC_0_COMPACT,lc=1033,id=507,ru=http:%2F%2messenger.msn.com,
        tw=0,kpp=1,kv=4,ver=2.1.6000.1,rn=1lgjbfIL,tpf=b073adghiuhwg142614
   
   //响应的 S 表示后面的身份验证过程开始。
   
6. 使用SSL协议进行验证
   (1)以SSL连接到[https://]nexus.passport.com:443端口,发送指令:
      GET /rdr/pprdr.asp HTTP/1.0\r\n
      \r\n
   (2)从服务器返回的信息中取得PassportURLs字段中的DALogin部分,
      取得需要连接的服务器(如login.passport.com/login2.srf)
   (3)客户端以SSL连接(2)中得到的服务器的443端口,进行如下请求:
      GET /login2.srf HTTP/1.1\r\n
      Authorization:
      OrgVerb=GET,OrgURL=%2F%2messenger.msn.com(与先前DS返回的地址保持一致),
      [email protected],pwd=*********,
      tw=0,kpp=1,kv=4,ver=2.1.6000.1,rn=1lgjbfIL,tpf=b073adghiuhwg142614
      User-Agent: MSMSGS\r\n
      Host: login.passport.com\r\n
      Connection: Keep-Alive\r\n
      Cache-Control: no-cache\r\n
      //接下来,还是有可能失败,需要重定向到另外的服务器进行验证。
      //如果成功,服务器返回的信息中会包含ticket信息
      //在from-PP='t=*********'中,保存取得的单引号中的信息即为
      //所需ticket
   (4)关闭SSL连接,回到NS服务器上,发送包含ticket的指令:
      C>> USR 4 TWN S t=*********
      //如果认证成功NS可收到返回信息:
      DS<< USR 4 OK [email protected] 1 0
7. 同步本地联系人,客户端发送指令:
   C>> SYN 5 0 0\r\n
   NS<< SYN 5 2010-04-15T03:52:46.047-07:00 2010-04-15T03:52:45.833-07:00 6 1
        GTC A
        BLP BL
         
8. 发上线的通知
   //在收到DS的同步相应消息后,客户端可向服务器发送指令:
   C>> CHG 6 NLN
   DS<< CHS 6 NLN 0
   // DS发送回相关的联系人的信息
   // 返回指令包含 FLN,NLN,UBX...
   (发送QRY 7 fsgjhihg 指令,Ping 当前的服务器NS<< QRY 7\r\n)
   
9. 接收外部客户的查询交互信息(建立语言识别资源库

     1. 以TCP连接(DS)messenger.hotmail.com:1863,发送指令:  

        C>> VER 1 MSNP8 CVR0(\r\n)   

        DS<< VER 1 MSNP8

 

     2. 客户端发送CVR指令说明当前使用的环境   

    C>> CVR 2 0x0804 win 5.1.2600 i386 MSNMSGR 7.0.0813 MSMSGS [email protected]  

        DS<< CVR 2 1.0.0000 1.0.0000 1.0.0000   http://msgr.dlservice.microsoft.com http://download.live.com/?sku=messenger

 

   3. 客户端发送USR说明身份   

    C>> USR 3 TWN I [email protected]  

    DS>> XFR 3 NS 207.46.124.105:1863 0 64.4.9.254:1863   

       // XFR 命令指出客户端可以与NS 服务器进行通讯连接了。其中第三个参数为NS服务器的通讯地址,第五个是当前连接的实际服务器IP与端口。


     4. 客户端关闭与以上DS的连接  

        C>> OUT

 

     5. 客户端与NS服务器建立连接,发送之前的指令消息:   

    C>> VER 1 MSNP8 CVR0(\r\n)   

     NS<< VER 1 MSNP8

 

       C>> CVR 2 0x0804 win 5.1.2600 i386 MSNMSGR 7.0.0813 MSMSGS [email protected]  

       NS<< CVR 2 1.0.0000 1.0.0000 1.0.0000   http://msgr.dlservice.microsoft.com http://download.live.com/?sku=messenger  

 

       C>> USR 3 TWN I [email protected]   

       NS<< USR 3 TWN S ct = 127137673, rver=5.5.4182.0,                      wp=FS_40SEC_0_COMPACT,lc=1033,id=507,ru=http:%2F%2messenger.msn.com,          tw=0,kpp=1,kv=4,ver=2.1.6000.1,rn=1lgjbfIL,tpf=b073adghiuhwg142614      

       // 注意到TWN命令S 表示后面的身份验证过程开始,它之后的字符串被称为Challenge String,用于后面的SSL 身份验证 .

 

  6. 使用SSL协议进行身份验证的一般过程

  (1)以SSL连接到[https://]nexus.passport.com:443端口,发送指令:     

  GET /rdr/pprdr.asp HTTP/1.0\r\n \r\n   

  (2)从服务器返回的信息中取得PassportURLs字段中的DALogin部分,取得需要连接的服务器(如login.passport.com/login2.srf)   

  (3)客户端以SSL连接(2)中得到的服务器的443端口,进行如下请求:      

  GET /login2.srf HTTP/1.1\r\n      

  Authorization:  OrgVerb=GET,OrgURL=%2F%2messenger.msn.com(与先前DS返回的ChallengeString保持一致),sign-    [email protected],pwd=******, tw=0,kpp=1,kv=4,ver=2.1.6000.1,rn=1lgjbfIL,tpf=b073adghiuhwg142614      

  User-Agent: MSMSGS\r\n      

  Host: login.passport.com\r\n     

  Connection: Keep-Alive\r\n      

  Cache-Control: no-cache\r\n     

  //接下来,还是有可能失败,需要重定向到另外的服务器进行验证。如果成功,服务器返回的信息中会包含ticket信息 在from-PP='t=*********'中,保存取得的单引号中的信息即为所需ticket。

  (4)关闭SSL连接,回到NS服务器上,发送包含ticket的指令:      

  C>> USR 4 TWN S t=*********      

  // 认证成功NS可收到如下返回信息,认为登陆成功。      

  DS<< USR 4 OK [email protected] nickname 1 0

  7. 客户端发送指令同步本地联系人 

  C>> SYN 5 0 0\r\n   

  NS<< SYN 5 2010-04-15T03:52:46.047-07:00 2010-04-15T03:52:45.833-07:00 6 1        

  GTC A

  BLP BL   

      // DS发送回相关的联系人的信息,联系人所在列表,群的信息等 

 

  8. 发上线的通知   

  //在收到DS的同步相应消息后,客户端可向服务器发送指令:   

  C>> CHG 6 NLN   

  DS<< CHS 6 NLN 0   

     通知在联系人列表中的contact当前用户已经上线。

 

     MSN 连接状态的保持

     1. 在上线后的一段时间内,会收到NS发送的验证信息:

  DS<< CHL 0 23535 7436571354157672341575625

     该命令的最后参数为随机的数字字符串(a challenge),你需要在50s 内发回QRY的应答消息,不回答或是答错都将会被NS断开连接,并且没有任何出错提示。

Client ID string Client ID code
[email protected] Q1P7W2E4J9R8U3S5
PROD0038W!61ZTF9 VT6PX?UQTM4WM%YR
PROD0058#7IL2{QD QHDCY@7R1TB6W?5B
PROD0061VRRZH@4F JXQ6J@TUOGYV@N0M

   可以从以上的组合中选出一组,在响应的QRY命令中要求Client ID String, 而对应的ID Code 将与服务器发送过来的challenge组成 challenge + Client ID Code组合字符串。随后利用MD5加密算法计算这个字符串 32位的digest。发回响应的命令:

  C>> QRY trID Client_ID_String 32\r\n digest

      验证成功会收到NS的返回信息

     NS<< QRY trID \r\n


     2. 为防止端口被关闭,客户端可以定时向NS发送心跳包, 以测试当前TCP的连接状态

  C>> PNG\r\n 

      NS<< QNG\r\n

 

总结:

1> 在实现协议交互的过程中,以上登陆的阶段是近乎同步的通信过程,单独得响应过程应该不会有太大的难点。着重说明的还有发送的消息格式要严格遵循,每条消息后一般都会有\r\n结尾,另外实际利用socket发送出去的数据的实际大小也要一致。否则,你的连接会被服务器悄无声息地断掉 ;)

2> 另外在利用MD5算法时,可以利用现有的开源代码。这个在协议MSNP11中验证的计算方式发生了变化,有兴趣的园友可以研究下。

3> 在以SSL方式验证时可以调用WinINet中的相关的函数(InternetOpen,InternetOpenUrl,HttpQueryInfo),获取验证服务器返回的ticket。然而这在C#中利用 WebService 却可以得到更快的实现。

4> 最重要的会是网络通信模型的选择以及多线程的应用,因为与NS的连接要一直保存下去;而对于建立/发起外部的会话,这就要关联到与不同的SS交互的过程。最后与MSN Activity 展开交互的部分,仍然成为了现阶段需要解决的难点。

 

Ref URL:

MSN协议分析的最佳网站

1. http://www.hypothetic.org/docs/msn/index.php

2. http://msnpiki.msnfanatic.com/index.php/MSN_Protocol_Version_8

支持MSN Messenger Client 的开源作品

3. http://www.miranda-im.org/

4. http://code.google.com/p/msnp-sharp/

转载于:https://www.cnblogs.com/raywalker/archive/2010/05/03/MSN_Protocol.html

你可能感兴趣的:(MSNP8协议解析以及对客户端的模拟实现)