def parse_routes(self, items): routes = [] while items: if items[0] == '*': logger.debug("parse traceroute like: *") route = { 'ip': '*', 'hostname': '*', 'location': None, 'response_times': 0 } items = items[1:] elif items.index('ms') == 3: logger.debug( "parse traceroute like: \"bogon (10.199.13.51) 6.527 ms\"" ) hostname = items[0].strip() ip = items[1].strip('(').strip(')').strip() ipt = IpLocation(self.parameters) location = ipt.get_location(ip) rtime = float(items[2]) route = { 'ip': ip, 'hostname': hostname, 'location': location, 'response_times': rtime } items = items[4:] elif items.index('ms') == 1: logger.debug("parse traceroute like: \"6.527 ms\"") rtime = float(items[0]) preroute = routes[len(routes) - 1] if preroute: route = { 'ip': preroute['ip'], 'hostname': preroute['hostname'], 'location': preroute['location'], 'response_times': rtime } else: route = { 'ip': '*', 'hostname': '*', 'location': '', 'response_times': rtime } items = items[2:] else: logger.error("Can not parse route: %s" % items) routes.append(route) return routes
def execute(self): data = dict() ip_list = [] cname_list = [] mx_list = [] ns_list = [] # terminal_request_send_time self.terminal_request_send_time = time.time() self.parameters["terminal_request_send_time"] = self.terminal_request_send_time if self.dns_server: try: dns_query = dns.message.make_query(qname=self.destination, rdtype=self.rdtype) querya = dns.query.udp(dns_query, self.dns_server, timeout=self.dns_timeout) data_ptime = querya.time * 1000 answer = querya.answer except dns.exception.Timeout as e: logger.exception("dns timeout exception") return DnsError(url=self.destination, error=e, parameters=self.parameters).dns_timeout_error() except (resolver.NXDOMAIN, socket.gaierror) as e: logger.exception("dns server exception") return DnsError(url=self.destination, error=e, parameters=self.parameters).dns_server_error() else: dns_servers = resolver.get_default_resolver().nameservers if not dns_servers: logger.error("do not have dns servers") return DnsError(url=self.destination, parameters=self.parameters).miss_default_error() dns_query = dns.message.make_query(qname=self.destination, rdtype=self.rdtype) timeout_flag = 0 dns_server_flag = 0 for dns_server in dns_servers: try: querya = dns.query.udp(dns_query, dns_server, timeout=self.dns_timeout) data_ptime = querya.time * 1000 answer = querya.answer self.dns_server = dns_server break except dns.exception.Timeout as e: logger.exception("dns server {} got timeout exception".format(str(dns_server))) timeout_flag += 1 if timeout_flag + dns_server_flag == len(dns_servers): return DnsError(url=self.destination, error=e, parameters=self.parameters).dns_timeout_error() except (resolver.NXDOMAIN, socket.gaierror) as e: logger.exception("dns server {} got server exception".format(str(dns_server))) dns_server_flag += 1 if timeout_flag + dns_server_flag == len(dns_servers): return DnsError(url=self.destination, error=e, parameters=self.parameters).dns_server_error() self.terminal_response_receive_time = time.time() ipt = IpLocation(self.parameters) for queryans in answer: for item in queryans.items: # A记录 又称IP指向 if item.rdtype == rdatatype.A: ip_dict = dict() ip = item.address ip_dict["ip"] = ip location = ipt.get_location(ip) ip_dict["location"] = location ip_list.append(ip_dict) # CNAME 通常称别名指向 elif item.rdtype == rdatatype.CNAME: cname_list.append(str(item.target)) # MAIL记录 elif item.rdtype == rdatatype.MX: mx_list.append(str(item.exchange)) # NS记录 elif item.rdtype == rdatatype.NS: ns_list.append(str(item.target)) if self.dns_method == "mx": if mx_list: data["mxs"] = mx_list else: return DnsError(url=self.destination, parameters=self.parameters).dns_query_error() elif self.dns_method == "a": if ip_list: data["ips"] = ip_list else: return DnsError(url=self.destination, parameters=self.parameters).dns_query_error() elif self.dns_method == "ns": if ns_list: data["ns"] = ns_list else: return DnsError(url=self.destination, parameters=self.parameters).dns_query_error() elif self.dns_method == "cname": if cname_list: data["cnames"] = cname_list else: return DnsError(url=self.destination, parameters=self.parameters).dns_query_error() else: return DnsError(url=self.destination, parameters=self.parameters).dns_query_error() data["destination"] = self.destination data["ptime"] = data_ptime data["dns_server"] = dict() data["dns_server"]["ip"] = self.dns_server data["dns_server"]["location"] = ipt.get_location(self.dns_server) result = { "status": 0, "data": data, "stamp": { "server_request_generate_time": self.server_request_generate_time, "terminal_request_receive_time": self.terminal_request_receive_time, "terminal_request_send_time": self.terminal_request_send_time, "terminal_response_receive_time": self.terminal_response_receive_time, } } return result
def ping(self): try: terminal_request_send_time = time.time() logger.debug("starting ping {} ......".format(self.destination)) pobj = Ping(self.destination, self.parameters) data = pobj.ping() logger.debug("ending ping {} ......".format(self.destination)) terminal_response_receive_time = time.time() except Exception as e: exc_msg = repr(e) # import traceback # exc_msg = traceback.format_exc() ping_result = { "status": 1, "data": { "errorinfo": exc_msg, "errorcode": 140 }, "stamp": { "server_request_generate_time": self.server_request_generate_time, "terminal_request_receive_time": self.terminal_request_receive_time, "terminal_request_send_time": terminal_request_send_time, "terminal_response_receive_time": time.time(), } } return ping_result if data: ipt = IpLocation(self.parameters) ping_result = { "status": 0, "data": { "destination": self.destination, "destination_ip": data.destination_ip, "destination_location": ipt.get_location(data.destination_ip), "packet_send": self.count, "packet_receive": (self.count - data.packet_lost), "packet_loss": data.packet_lost, "packet_size": data.packet_size, "avg_time": data.avg_rtt, "max_time": data.max_rtt, "min_time": data.min_rtt, }, "stamp": { "server_request_generate_time": self.server_request_generate_time, "terminal_request_receive_time": self.terminal_request_receive_time, "terminal_request_send_time": terminal_request_send_time, "terminal_response_receive_time": terminal_response_receive_time, } } else: ping_result = { "status": 1, "data": { "errorinfo": "Unable to establish communication, data acquisition failed:" + self.destination, "errorcode": 141 }, "stamp": { "server_request_generate_time": self.server_request_generate_time, "terminal_request_receive_time": self.terminal_request_receive_time, "terminal_request_send_time": terminal_request_send_time, "terminal_response_receive_time": terminal_response_receive_time, } } return ping_result
def get_access_interface(self, interface): interface_json = {"type": "wired", "name": interface} wireless_keys = ["wlan"] for wireless_key in wireless_keys: if interface.find(wireless_key) >= 0: interface_json["type"] = "wireless" break info = netifaces.ifaddresses(interface) # 地址信息 interface_json["macaddress"] = None info_mac = info.get(netifaces.AF_LINK) if info_mac: if len(info_mac) == 1: interface_json["macaddress"] = info_mac[0].get("addr").replace( ":", "").lower() else: logger.error( "get mac address for interface {} wrong: {}".format( interface, str(info_mac))) else: logger.error( "cannot get mac address for interface {}".format(interface)) ipl = IpLocation(self.parameters) ipp = IpPublic(self.parameters) # ip地址信息, need to consider with gateway info_ipv4 = info.get(netifaces.AF_INET) if info_ipv4 and len(info_ipv4) == 1: local_ip = info_ipv4[0].get("addr") interface_json["local_ip"] = local_ip interface_json["local_location"] = ipl.get_location(local_ip) interface_json["netmask"] = info_ipv4[0].get("netmask") interface_json["broadcast"] = info_ipv4[0].get("broadcast") interface_json["is_default"] = False elif info_ipv4 and len(info_ipv4) > 1: """ 存在1个接口对应n个IP, 例如 $ ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether b8:27:eb:f9:41:74 brd ff:ff:ff:ff:ff:ff inet 10.10.36.222/24 brd 10.10.36.255 scope global eth0 valid_lft forever preferred_lft forever inet 10.10.36.55/24 brd 10.10.36.255 scope global secondary eth0 valid_lft forever preferred_lft forever inet6 fe80::ba27:ebff:fef9:4174/64 scope link valid_lft forever preferred_lft forever """ msg = "interface: {} have {} ip, natrix do not support, please check your network!".format( interface, len(info)) logger.warning(msg) local_ip = None s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: # doesn't even have to be reachable s.connect(('10.255.255.255', 1)) local_ip = s.getsockname()[0] except Exception: msg = "Cannot get an default ip for interface {}".format( interface) logger.exception(msg) if local_ip: for info in info_ipv4: if info.get("addr") == local_ip: interface_json["local_ip"] = info.get("addr") interface_json["local_location"] = ipl.get_location( local_ip) interface_json["netmask"] = info.get("netmask") interface_json["broadcast"] = info.get("broadcast") interface_json["is_default"] = False if not interface_json.get("local_ip"): interface_json["local_ip"] = None interface_json["local_location"] = None interface_json["netmask"] = None interface_json["broadcast"] = None interface_json["is_default"] = False else: msg = "interface {} do not have IPV4 address".format(interface) logger.warning(msg) interface_json["local_ip"] = None interface_json["local_location"] = None interface_json["netmask"] = None interface_json["broadcast"] = None interface_json["is_default"] = False # in all situation, set gateway to None interface_json["gateway"] = None # 公网IP if interface_json["local_ip"]: public_ip = ipp.get_publicip(interface) interface_json["public_ip"] = public_ip else: interface_json["public_ip"] = None if interface_json.get("public_ip"): interface_json["public_location"] = ipl.get_location( interface_json.get("public_ip")) else: interface_json["public_location"] = None # 连接信息 if interface_json["local_ip"]: interface_json["access_intranet"] = self.access_intranet(interface) interface_json["access_corporate"] = self.access_corporate( interface) interface_json["access_internet"] = self.access_internet(interface) else: interface_json["access_intranet"] = False interface_json["access_corporate"] = False interface_json["access_internet"] = False return interface_json
def parse_response_info(self): # 最后一次请求的URL last_url = self.pcurl.getinfo(pycurl.EFFECTIVE_URL) # 响应代码 get_status http_code = self.pcurl.getinfo(pycurl.HTTP_CODE) # 重定向 # 重定向次数 redirect_count = self.pcurl.getinfo(pycurl.REDIRECT_COUNT) # 如果存在转向的话,花费的时间 # 重定向所消耗的时间 redirect_time = self.pcurl.getinfo(pycurl.REDIRECT_TIME) * 1000 # TODO, 重定向历史信息 # 最后一次连接的远程IP地址 ipt = IpLocation(self.parameters) remote_ip = self.pcurl.getinfo(pycurl.PRIMARY_IP) remote_location = ipt.get_location(remote_ip) # TODO, 通过IP信息得到地址和地域信息 # 最后一次连接的远程端口号 remote_port = self.pcurl.getinfo(pycurl.PRIMARY_PORT) # 最后一次连接的本地IP地址 local_ip = self.pcurl.getinfo(pycurl.LOCAL_IP) local_location = ipt.get_location(local_ip) # 最后一次连接的本地端口号 local_port = self.pcurl.getinfo(pycurl.LOCAL_PORT) # 时间信息 # 请求总的时间 get_total_time # 传输结束时所消耗的总时间 total_time = self.pcurl.getinfo(pycurl.TOTAL_TIME) * 1000 # DNS解析-->TCP连接-->跳转【如有】-->SSL握手【如有】-->客户端准备-->服务器响应-->数据传输 # 域名解析时间 ms # DNS解析所消耗的时间 namelookup_time = self.pcurl.getinfo(pycurl.NAMELOOKUP_TIME) * 1000 # 建立连接时间 ms # 建立连接所消耗的时间 connect_time = self.pcurl.getinfo(pycurl.CONNECT_TIME) * 1000 # 从发起请求到SSL建立握手时间 appconnect_time = self.pcurl.getinfo(pycurl.APPCONNECT_TIME) * 1000 # 连接上后到开始传输时的时间 # 从建立连接到准备传输所消耗的时间 pretransfer_time = self.pcurl.getinfo(pycurl.PRETRANSFER_TIME) * 1000 # 接收到第一个字节的时间 # 从建立连接到数据开始传输所消耗的时间 starttransfer_time = self.pcurl.getinfo( pycurl.STARTTRANSFER_TIME) * 1000 # 需要对时间做一些处理 # 从而让 # DNS解析-->TCP连接-->SSL握手(如有)-->客户端准备-->服务器响应-->数据传输 # totoal_time = period_nslookup + period_tcp_connect + period_ssl_connect # + period_request + period_response + period_transfer # TCP连接耗时 period_tcp_connect = connect_time - namelookup_time # SSL连接耗时 if appconnect_time > connect_time: period_ssl_connect = appconnect_time - connect_time else: period_ssl_connect = 0 # Request请求耗时 if appconnect_time > connect_time: period_request = pretransfer_time - appconnect_time else: period_request = pretransfer_time - connect_time # Response处理耗时 period_response = starttransfer_time - pretransfer_time # Response传输耗时 period_transfer = float(total_time) - float(starttransfer_time) # 数据信息 # 上传数据包大小 size_upload = self.pcurl.getinfo(pycurl.SIZE_UPLOAD) # 下载数据包大小 size_download = self.pcurl.getinfo(pycurl.SIZE_DOWNLOAD) # 上传速度 speed_upload = self.pcurl.getinfo(pycurl.SPEED_UPLOAD) # 下载速度 speed_download = self.pcurl.getinfo(pycurl.SPEED_DOWNLOAD) # 头部大小 header_size = self.pcurl.getinfo(pycurl.HEADER_SIZE) self.http_result = { "status": 0, "data": { "url": self.destination, "last_url": last_url, "status_code": http_code, "redirect_count": redirect_count, "redirect_time": redirect_time, "remote_ip": remote_ip, "remote_location": remote_location, "remote_port": remote_port, "local_ip": local_ip, "local_location": local_location, "local_port": local_port, "total_time": total_time, "period_nslookup": namelookup_time, "period_tcp_connect": period_tcp_connect, "period_ssl_connect": period_ssl_connect, "period_request": period_request, "period_response": period_response, "period_transfer": period_transfer, "header_size": header_size, "size_upload": size_upload, "size_download": size_download, "speed_upload": speed_upload, "speed_download": speed_download, }, "stamp": { "server_request_generate_time": self.server_request_generate_time, "terminal_request_receive_time": self.terminal_request_receive_time, "terminal_request_send_time": self.terminal_request_send_time, "terminal_response_receive_time": self.terminal_response_receive_time, } } return self.http_result