def _setup(self): """ 尝试获取当前主机的主机名称、MAC地址、联网IP地址 :return: """ self.host_name = hostname() if LOCAL_MAC: # 如果没有指定本机MAC,尝试自动获取 self.mac = bytes().fromhex(LOCAL_MAC) else: self.mac = bytes().fromhex(mac()) if LOCAL_IP: # 如果没有指定本机IP,尝试自动获取 self.ip = LOCAL_IP else: self.ip = ipaddress() if not self.host_name or not self.mac or not self.ip: raise DrCOMException( "[DrCOM.__init__]:Can not fetch NIC info, please raise a issues @ github" ) self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self.socket.settimeout(3) try: self.socket.bind(("", 61440)) except socket.error: raise DrCOMException( "[DrCOM.__init__]:Can not bind 61440 port,please retry after a while" )
def __initialise__(self): """ 尝试获取当前主机的主机名称、MAC地址、联网IP地址 :return: """ self.host_name = hostname() if LOCAL_MAC: # 如果没有指定本机MAC,尝试自动获取 self.mac = bytes().fromhex(LOCAL_MAC) else: self.mac = bytes().fromhex(mac()) if LOCAL_IP: # 如果没有指定本机IP,尝试自动获取 self.ip = LOCAL_IP else: self.ip = ipaddress() if not self.host_name or not self.mac or not self.ip: Log(logging.ERROR, 10, "[DrCOM.__init__]:无法获取本机的NIC信息,请直接提交到该项目issues") raise DrCOMException("无法获取本机的NIC信息") self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self.socket.settimeout(3) try: self.socket.bind(("", 61440)) except socket.error: Log(logging.ERROR, 10, "[DrCOM.__init__]:无法绑定61440端口,请检查是否有其他进程占据了该端口") raise DrCOMException("无法绑定本机61440端口")
def send_alive_pkg1(self): """ 发送类型一的心跳包 :return: """ pkg = b'\xff' pkg += md5(b'\x03\x01' + self.salt + self.pwd.encode('ascii')) # MD5_A pkg += b'\x00' * 3 pkg += self.auth_info pkg += struct.pack('!H', int(time.time()) % 0xFFFF) pkg += b'\x00' * 3 data, address = self._send_package(pkg, (self.server_ip, 61440)) if data[0] == 0x07: Log( logging.DEBUG, 0, "[DrCOM.send_alive_pkg1]:Successful sending heartbeat package type 1..." ) else: # 当收到的数据包没法识别的时候 exception = DrCOMException( "[DrCOM.send_alive_pkg1]:Receive unknown packages content...") exception.last_pkg = data raise exception
def _setup(self): """ 尝试获取当前主机的主机名称、MAC地址、联网IP地址 :return: """ self.host_name = hostname() if LOCAL_MAC: # 如果没有指定本机MAC,尝试自动获取 self.mac = bytes().fromhex(LOCAL_MAC) else: self.mac = bytes().fromhex(mac()) if LOCAL_IP: # 如果没有指定本机IP,尝试自动获取 self.ip = LOCAL_IP else: self.ip = ipaddress() if not self.host_name or not self.mac or not self.ip: raise DrCOMException("请确保已经接入有线网") self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self.socket.settimeout(3) try: self.socket.bind(("", 61440)) except (OSError, socket.error): raise DrCOMException("检测到重复启动客户端")
def login(self): """ 登录到目标服务器方法 :return: """ pkg = self._make_login_package() data, address = self._send_package(pkg, (self.server_ip, 61440)) if data[0] == 0x04: self.auth_info = data[23:39] # 在这里设置当前为登录状态 self.login_flag = True res = DrCOMResponse() res.msg = "已经连接上校园网络" return res elif data[0] == 0x05: if len(data) > 32: if data[32] == 0x31: raise DrCOMException( "Failure on login because the wrong username...") if data[32] == 0x33: raise DrCOMException( "Failure on login because the wrong password...") else: exception = DrCOMException("Receive unknown packages content...") exception.last_pkg = data raise exception
def prepare(self): """ 获取服务器IP和Salt :return: """ self._setup() random_value = struct.pack( "<H", int(time.time() + random.randint(0xF, 0xFF)) % 0xFFFF) pkg = b'\x01\x02' + random_value + b'\x0a' + b'\x00' * 15 # 尝试目前已知的学校认证服务器地址 for _ in [(SERVER_IP, 61440), ("1.1.1.1", 61440), ("202.1.1.1", 61440)]: data, address = self._send_package(pkg, _) # 未获取合理IP地址则进行下一个服务器地址尝试 if data[0:4] == b'\x02\x02' + random_value: self.server_ip = address[0] self.salt = data[4:8] self.ready_flag = True res = DrCOMResponse() res.msg = "已做好接入有线网的准备" return res if not self.server_ip or not self.salt: exception = DrCOMException("无法检测到验证服务器") exception.last_pkg = pkg raise exception
def logout(self): """ 登出,仅测试了BISTU版本 登出过程一共会有6个包,分3组,每组2个 第一组同alive_pkg1的发送与确认 第二组似乎是用于告知网关准备登出 第三组会发送登出的详细信息包括用户名等 """ # 第一组 初步判断是为了判断当前网络是否联通 # 发送的数据包的最后两个字节可能有验证功能 self.send_alive_pkg1() # 第二组 登出准备 # 与alive_pkg1的最后两个字节相同 pkg = b'\x01\x03' pkg += b'\x00\x00' pkg += b'\x0a' pkg += b'\x00' * 15 data, address = self._send_package(pkg, (self.server_ip, 61440)) if data[0:2] != b'\x02\x03': Log( logging.ERROR, 70, "[DrCOM.login]:Receive unknown packages content: {}".format( data)) # 第三组 pkg = self._make_logout_package() data, address = self._send_package(pkg, (self.server_ip, 61440)) if data[0] == 0x04: self.login_flag = False else: Log( logging.ERROR, 71, "[DrCOM.logout]:Receive unknown packages content: {}".format( data)) if self.login_flag: exception = DrCOMException("Failure on logout to DrCOM...") exception.last_pkg = pkg raise exception
def login(self): """ 登录到目标服务器方法 :return: """ pkg = self._make_login_package() data, address = self._send_package(pkg, (self.server_ip, 61440)) Log(logging.DEBUG, 0, "[DrCOM.login]:Receive PKG content: {}".format(data)) if data[0] == 0x04: self.auth_info = data[23:39] # 在这里设置当前为登录状态并且也处于在线状态 self.login_flag = True self.alive_flag = True Log(logging.INFO, 0, "[DrCOM.login]:Successfully login to DrCOM Server...") elif data[0] == 0x05: if len(data) > 32: if data[32] == 0x31: Log( logging.ERROR, 31, "[DrCOM.login]:Failure on login because the wrong username..." ) if data[32] == 0x33: Log( logging.ERROR, 32, "[DrCOM.login]:Failure on login because the wrong password..." ) else: Log( logging.ERROR, 30, "[DrCOM.login]:Receive unknown packages content: {}".format( data)) if not self.login_flag: exception = DrCOMException("Failure on login to DrCOM...") exception.last_pkg = pkg raise exception
def logout(self): """ 登出,仅测试了BISTU版本 登出过程一共会有6个包,分3组,每组2个 第一组同alive_pkg1的发送与确认 第二组似乎是用于告知网关准备登出 第三组会发送登出的详细信息包括用户名等 """ # 与alive_pkg1的最后两个字节相同 pkg = b'\x01\x03' pkg += b'\x00\x00' pkg += b'\x0a' pkg += b'\x00' * 15 data, address = self._send_package(pkg, (self.server_ip, 61440)) if data[0:2] != b'\x02\x03': exception = DrCOMException( "[DrCOM.logout]:Receive unknown packages content...") exception.last_pkg = data raise exception # 第三组 pkg = self._make_logout_package() data, address = self._send_package(pkg, (self.server_ip, 61440)) if data[0] != 0x04: exception = DrCOMException( "[DrCOM.logout]:Receive unknown packages content...") exception.last_pkg = data raise exception self.login_flag = False
def send_alive_pkg2(self, num, key, cls): """ 发送类型二的心跳包 :return: """ pkg = self._make_alive_package(num=num, key=key, cls=cls) data, address = self._send_package(pkg, (self.server_ip, 61440)) if data[0] == 0x07: Log( logging.DEBUG, 0, "[DrCOM.send_alive_pkg2]:Successful sending heartbeat package 2[{}]..." .format(cls)) response = data[16:20] return response else: # 当收到的数据包没法识别的时候 exception = DrCOMException( "[DrCOM.send_alive_pkg2]:Receive unknown packages content...") exception.last_pkg = data raise exception
def prepare(self): """ 获取服务器IP和Salt :return: """ random_value = struct.pack( "<H", int(time.time() + random.randint(0xF, 0xFF)) % 0xFFFF) pkg = b'\x01\x02' + random_value + b'\x0a' + b'\x00' * 15 # 尝试目前已知的学校认证服务器地址 for _ in [(SERVER_IP, 61440), ("1.1.1.1", 61440), ("202.1.1.1", 61440)]: data, address = self._send_package(pkg, _) # 未获取合理IP地址则进行下一个服务器地址尝试 Log(logging.DEBUG, 0, "[DrCOM.prepare]:Receive PKG content: {}".format(data)) if data[0:4] == b'\x02\x02' + random_value: self.server_ip = address[0] self.salt = data[4:8] Log( logging.DEBUG, 0, "[DrCOM.prepare]:Server IP: {}, Salt: {}".format( self.server_ip, self.salt)) return else: Log( logging.WARNING, 20, "[DrCOM.prepare]:Receive unknown packages content: {}". format(data)) if not self.server_ip or not self.salt: exception = DrCOMException( "[DrCOM.prepare]:Cannot find any available server...") exception.last_pkg = pkg raise exception