本帖最后由 江威 于 2017-3-31 17:19 编辑  
 
1、背景介绍 
    Lotus Notes可以集成很多应用,在很多企业都作为办公OA系统,具有一定的普遍性,对于大型企业来说,办公OA系统会直接影响到职员的办公效率,可以部署多台Lotus Notes系统通过负载均衡的方式对外提供服务,一方面提高服务器的响应速度,另一方面可以提高扩展性,而对终端用户来说不需要修改服务器地址。  
 2、协议分析     Lotus Notes是IBM开发的一套办公软件,在访问其服务器时,数据包中会携带要访问的服务器IP地址,同时在数据包的头两个字节中表明此数据包的长度,服务器在收到客户端的数据包时会校验此数据包的合法性,具体可以见下图(第一张图中标记了服务器地址;第二张图中标记了数据包的长度,此图为7c):  
 
3、解决方案 通过AD对Lotus Notes进行负载,需要对外修改为统一的VIP地址,那么必然导致服务器检查服务器IP地址这一部分不通过,因此,需要通过iPro脚本将其VIP地址修改为当前调度的节点IP地址,修改数据包之后可能造成数据包长度变化,需要一并修改,源码如下: - --[[
 
 -         Lotus Notes 应用负载,首个连接有协商,共2个数据包需要替换VIP
 
 - --]]
 
  
- local rs = nil
 
 - local packet = 1
 
  
- --调试
 
 - function dbg(str)
 
 -         LOG.log(LOG.DEBUG, str)
 
 - end
 
  
- event CLIENT_ACCEPT 
 
 - {
 
 -         dbg("CLIENT_ACCEPT")
 
 -                 
 
 -         rs = pool("srv")
 
 -         
 
 -         if rs 
 
 -         then
 
 -             dbg("sched ok, rs "..rs.ip..":"..rs.port)
 
 -         else
 
 -             dbg("ERROR: sched failed")
 
 -             TCP.close()
 
 -         end
 
 -         
 
 -         TCP.collect()
 
 - }
 
  
- --处理第一个带VIP的包
 
 - function deal_with_packet_1(data, st, ed)
 
 -         dbg("deal with packet 1")
 
 -         
 
 -         --首个字节为包总长度
 
 -         local total_len = string.byte(data, 1)
 
 -         local packet_len = total_len + 2
 
 -         --总长度差额
 
 -         local total_len_diff = 0;
 
 -         
 
 -         --新旧IP字符串长度
 
 -         local old_ip_len = ed - st + 1
 
 -         local new_ip_len = string.len(rs.ip)
 
 -         local len_diff = 0
 
 -         
 
 -         dbg("total_len: "..total_len)
 
 -         dbg("new ip len: "..new_ip_len..", old_ip_len: "..old_ip_len)
 
 -         
 
 -         len_diff = new_ip_len - old_ip_len
 
 -         total_len_diff = len_diff
 
  
-         --若差额是奇数,考虑补位和总长度
 
 -         if total_len_diff % 2 ~= 0
 
 -         then
 
 -                 --若最后一位是0
 
 -                 if string.byte(data, packet_len) == 0
 
 -                 then
 
 -                         dbg("last byte == 0")
 
 -                         --长度-1,去掉最后的0
 
 -                         total_len_diff = total_len_diff - 1
 
 -                         TCP.replace(packet_len, packet_len + 1, "")
 
 -                         
 
 -                 --若最后一位非0
 
 -                 else
 
 -                         dbg("last byte != 0")
 
 -                         --长度+1,同时需要补位
 
 -                         total_len_diff = total_len_diff + 1
 
 -                         TCP.append(0)
 
 -                 end
 
 -         end
 
 -         
 
 -         dbg("len_dif: "..len_diff..", data[5]: "..string.byte(data, 5)..", data[st - 2]: "..string.byte(data, st - 2))
 
 -         dbg("total_len_diff: "..total_len_diff)
 
 -         
 
 -         --替换为调度的服务器的IP
 
 -         TCP.replace(st, ed + 1, rs.ip)
 
 -         
 
 -         --替换data[5]和data[st - 2]位置的长度
 
 -         TCP.replace(5, 6, string.char(string.byte(data, 5) + len_diff))
 
 -         TCP.replace(st - 2, st - 1, string.char(string.byte(data, st - 2) + len_diff))
 
 -         
 
 -         --修改包总长度
 
 -         TCP.replace(1, 2, string.char(total_len + total_len_diff))
 
 -         
 
 -         dbg("deal with packet 1 finish")
 
 - end
 
  
- --处理第二个带VIP的包
 
 - function deal_with_packet_2(data, st, ed)
 
 -         dbg("deal with packet 2")
 
 -         
 
 -         --首个字节为包总长度
 
 -         local total_len = string.byte(data, 1)
 
 -         --总长度差额
 
 -         local total_len_diff = 0;
 
 -         
 
 -         --新旧IP字符串长度
 
 -         local old_ip_len = ed - st + 1
 
 -         local new_ip_len = string.len(rs.ip)
 
 -         local len_diff = 0
 
 -                 
 
 -         dbg("total_len: "..total_len)
 
 -         dbg("new ip len: "..new_ip_len..", old_ip_len: "..old_ip_len)
 
  
-         len_diff = new_ip_len - old_ip_len
 
 -         total_len_diff = len_diff        
 
 -         
 
 -         dbg("len_dif: "..len_diff..", data[5]: "..string.byte(data, 5))
 
 -         dbg("total_len_diff: "..total_len_diff)
 
 -         
 
 -         --替换为调度的服务器的IP
 
 -         TCP.replace(st, ed + 1, rs.ip)
 
 -         
 
 -         --替换data[5]位置的长度
 
 -         TCP.replace(5, 6, string.char(string.byte(data, 5) + len_diff))
 
 -         
 
 -         --修改包总长度
 
 -         TCP.replace(1, 2, string.char(total_len + total_len_diff))
 
 -         
 
 -         dbg("deal with packet 2 finish")
 
 - end
 
  
- event CLIENT_DATA 
 
 - {
 
 -     dbg("CLIENT_DATA")
 
 -         
 
 -         local data = TCP.payload()
 
 -         
 
 -         if not data
 
 -         then
 
 -                 return 0
 
 -         end
 
 -         
 
 -         local st, ed = 0, 0
 
 -         
 
 -         local vip = TCP.localaddr()
 
 -         
 
 -         dbg("vip: "..vip)
 
 -         
 
 -         --查找VIP
 
 -         st, ed = string.find(data, vip, ed + 1)
 
 -         
 
 -         if not st
 
 -         then
 
 -                 dbg("can't find vip "..vip)
 
 -                 
 
 -                 TCP.release()
 
 -                 TCP.collect()
 
 -                 
 
 -                 return 0
 
 -         end
 
 -         
 
 -         if packet == 1
 
 -         then
 
 -                 deal_with_packet_1(data, st, ed)
 
 -                 --后面继续收集数据
 
 -                 TCP.collect()
 
 -         elseif packet == 2
 
 -         then
 
 -                 deal_with_packet_2(data, st, ed)
 
 -                 --后面的包不再处理
 
 -         else
 
 -                 dbg("ERROR: stop!")
 
 -         end
 
 -         
 
 -         dbg("finish, packet "..packet)
 
 -         
 
 -         packet = packet + 1
 
 -         
 
 -         TCP.release()
 
 - }
 
  复制代码 
 |