From dd8bc5798b7ee1e8a72f5b87ede966dcc3fa4e23 Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 17 Feb 2023 19:38:34 +0800 Subject: [PATCH 1/2] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20Ping=20?= =?UTF-8?q?=E5=92=8C=20telnet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/utils/ip/utils.py | 12 +++++++++++- apps/ops/models/job.py | 11 +++++++---- apps/settings/utils/ping.py | 18 ++++++++++++----- apps/settings/utils/telnet.py | 33 +++++++++++++++++++++++++------ apps/settings/ws.py | 37 ++++++----------------------------- 5 files changed, 64 insertions(+), 47 deletions(-) diff --git a/apps/common/utils/ip/utils.py b/apps/common/utils/ip/utils.py index 6a6fce26b..e5d43911e 100644 --- a/apps/common/utils/ip/utils.py +++ b/apps/common/utils/ip/utils.py @@ -1,9 +1,11 @@ +import socket from ipaddress import ip_network, ip_address + from django.conf import settings from django.utils.translation import gettext_lazy as _ -from .ipip import get_ip_city_by_ipip from .geoip import get_ip_city_by_geoip +from .ipip import get_ip_city_by_ipip def is_ip_address(address): @@ -89,3 +91,11 @@ def get_ip_city(ip): if country == '中国' and is_zh: return city return get_ip_city_by_geoip(ip) + + +def lookup_domain(domain): + try: + return socket.gethostbyname(domain) + except Exception as e: + print("Cannot resolve %s: Unknown host, %s" % (domain, e)) + return None diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py index 5ee88c03c..2c0fb6113 100644 --- a/apps/ops/models/job.py +++ b/apps/ops/models/job.py @@ -24,21 +24,24 @@ from terminal.notifications import CommandExecutionAlert class Job(JMSOrgBaseModel, PeriodTaskModelMixin): name = models.CharField(max_length=128, null=True, verbose_name=_('Name')) + instant = models.BooleanField(default=False) args = models.CharField(max_length=1024, default='', verbose_name=_('Args'), null=True, blank=True) - module = models.CharField(max_length=128, choices=Modules.choices, default=Modules.shell, - verbose_name=_('Module'), null=True) + module = models.CharField(max_length=128, choices=Modules.choices, default=Modules.shell, verbose_name=_('Module'), + null=True) chdir = models.CharField(default="", max_length=1024, verbose_name=_('Chdir'), null=True, blank=True) timeout = models.IntegerField(default=-1, verbose_name=_('Timeout (Seconds)')) + playbook = models.ForeignKey('ops.Playbook', verbose_name=_("Playbook"), null=True, on_delete=models.SET_NULL) + type = models.CharField(max_length=128, choices=Types.choices, default=Types.adhoc, verbose_name=_("Type")) creator = models.ForeignKey('users.User', verbose_name=_("Creator"), on_delete=models.SET_NULL, null=True) assets = models.ManyToManyField('assets.Asset', verbose_name=_("Assets")) + use_parameter_define = models.BooleanField(default=False, verbose_name=(_('Use Parameter Define'))) + parameters_define = models.JSONField(default=dict, verbose_name=_('Parameters define')) runas = models.CharField(max_length=128, default='root', verbose_name=_('Runas')) runas_policy = models.CharField(max_length=128, choices=RunasPolicies.choices, default=RunasPolicies.skip, verbose_name=_('Runas policy')) - use_parameter_define = models.BooleanField(default=False, verbose_name=(_('Use Parameter Define'))) - parameters_define = models.JSONField(default=dict, verbose_name=_('Parameters define')) comment = models.CharField(max_length=1024, default='', verbose_name=_('Comment'), null=True, blank=True) version = models.IntegerField(default=0) history = HistoricalRecords() diff --git a/apps/settings/utils/ping.py b/apps/settings/utils/ping.py index 409edc83a..7b4f0a2a4 100644 --- a/apps/settings/utils/ping.py +++ b/apps/settings/utils/ping.py @@ -7,6 +7,8 @@ import socket import struct import time +from common.utils import lookup_domain + # From /usr/include/linux/icmp.h; your milage may vary. ICMP_ECHO_REQUEST = 8 # Seems to be the same on Solaris. @@ -126,24 +128,30 @@ def ping(dest_addr, timeout, psize, flag=0): return delay -def verbose_ping(dest_addr, timeout=2, count=5, psize=64): +def verbose_ping(dest_addr, timeout=2, count=5, psize=64, display=None): """ Send `count' ping with `psize' size to `dest_addr' with the given `timeout' and display the result. """ + ip = lookup_domain(dest_addr) + if not ip: + return + if display is None: + display = print + display("PING %s (%s): 56 data bytes" % (dest_addr, ip)) for i in range(count): - print("ping %s with ..." % dest_addr, end="") try: delay = ping(dest_addr, timeout, psize) except socket.gaierror as e: - print("failed. (socket error: '%s')" % str(e)) + display("failed. (socket error: '%s')" % str(e)) break if delay is None: - print("failed. (timeout within %ssec.)" % timeout) + display("Request timeout for icmp_seq %i" % i) else: delay = delay * 1000 - print("get ping in %0.4fms" % delay) + display("64 bytes from %s: icmp_seq=0 ttl=115 time=%.3f ms" % (ip, delay)) + time.sleep(1) print() diff --git a/apps/settings/utils/telnet.py b/apps/settings/utils/telnet.py index b8a7e81ef..6d9521dcb 100644 --- a/apps/settings/utils/telnet.py +++ b/apps/settings/utils/telnet.py @@ -3,6 +3,8 @@ import socket import telnetlib +from common.utils import lookup_domain + PROMPT_REGEX = r'[\<|\[](.*)[\>|\]]' @@ -16,10 +18,29 @@ def telnet(dest_addr, port_number=23, timeout=10): return True, output.decode('utf-8', 'ignore') +def verbose_telnet(dest_addr, port_number=23, timeout=10, display=None): + if display is None: + display = print + msg = '$ telnet %s %s' % (dest_addr, port_number) + display(msg) + ip = lookup_domain(dest_addr) + display('Trying %s...' % ip) + try: + is_connective, resp = telnet(dest_addr, port_number, timeout) + if is_connective: + template = 'Connected to {0} {1}.\r\n{2}Connection closed by foreign host.' + else: + template = 'telnet: connect to {0} {1} {2}\r\ntelnet: Unable to connect to remote host' + msg = template.format(dest_addr, port_number, resp) + except Exception as e: + msg = 'Error: %s' % e + display(msg) + + if __name__ == "__main__": - print(telnet(dest_addr='1.1.1.1', port_number=2222)) - print(telnet(dest_addr='baidu.com', port_number=80)) - print(telnet(dest_addr='baidu.com', port_number=8080)) - print(telnet(dest_addr='192.168.4.1', port_number=2222)) - print(telnet(dest_addr='192.168.4.1', port_number=2223)) - print(telnet(dest_addr='ssssss', port_number=-1)) + print(verbose_telnet(dest_addr='1.1.1.1', port_number=2222)) + print(verbose_telnet(dest_addr='baidu.com', port_number=80)) + print(verbose_telnet(dest_addr='baidu.com', port_number=8080)) + print(verbose_telnet(dest_addr='192.168.4.1', port_number=2222)) + print(verbose_telnet(dest_addr='192.168.4.1', port_number=2223)) + print(verbose_telnet(dest_addr='ssssss', port_number=-1)) diff --git a/apps/settings/ws.py b/apps/settings/ws.py index ff9084bdb..9e248536f 100644 --- a/apps/settings/ws.py +++ b/apps/settings/ws.py @@ -7,7 +7,7 @@ from channels.generic.websocket import JsonWebsocketConsumer from common.db.utils import close_old_connections from common.utils import get_logger -from .utils import ping, telnet +from .utils import verbose_ping, verbose_telnet logger = get_logger(__name__) @@ -21,45 +21,20 @@ class ToolsWebsocket(JsonWebsocketConsumer): else: self.close() + def send_msg(self, msg): + self.send_json({'msg': msg + '\r\n'}) + def imitate_ping(self, dest_addr, timeout=3, count=5, psize=64): """ Send `count' ping with `psize' size to `dest_addr' with the given `timeout' and display the result. """ logger.info('receive request ping {}'.format(dest_addr)) - self.send_json({'msg': 'Trying {0}...\r\n'.format(dest_addr)}) - for i in range(count): - msg = 'ping {0} with ...{1}\r\n' - try: - delay = ping(dest_addr, timeout, psize) - except Exception as e: - msg = msg.format(dest_addr, 'failed. (socket error: {})'.format(str(e))) - logger.error(msg) - self.send_json({'msg': msg}) - break - if delay is None: - msg = msg.format(dest_addr, 'failed. (timeout within {}s)'.format(timeout)) - else: - delay = delay * 1000 - msg = msg.format(dest_addr, 'get ping in %0.4fms' % delay) - self.send_json({'msg': msg}) + verbose_ping(dest_addr, timeout, count, psize, display=self.send_msg) def imitate_telnet(self, dest_addr, port_num=23, timeout=10): logger.info('receive request telnet {}'.format(dest_addr)) - self.send_json({'msg': 'Trying {0} {1}...\r\n'.format(dest_addr, port_num)}) - msg = 'Telnet: {}' - try: - is_connective, resp = telnet(dest_addr, port_num, timeout) - if is_connective: - msg = msg.format('Connected to {0} {1}\r\n{2}'.format(dest_addr, port_num, resp)) - else: - msg = msg.format('Connect to {0} {1} {2}\r\nTelnet: Unable to connect to remote host' - .format(dest_addr, port_num, resp)) - except Exception as e: - logger.error(msg) - msg = msg.format(str(e)) - finally: - self.send_json({'msg': msg}) + verbose_telnet(dest_addr, port_num, timeout, display=self.send_msg) def receive(self, text_data=None, bytes_data=None, **kwargs): data = json.loads(text_data) From 10e50c7c2ce70cbe66bc522ceeaad0414c35728f Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 17 Feb 2023 19:42:14 +0800 Subject: [PATCH 2/2] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20Ping?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/settings/utils/telnet.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/settings/utils/telnet.py b/apps/settings/utils/telnet.py index 6d9521dcb..22a1cf619 100644 --- a/apps/settings/utils/telnet.py +++ b/apps/settings/utils/telnet.py @@ -21,10 +21,11 @@ def telnet(dest_addr, port_number=23, timeout=10): def verbose_telnet(dest_addr, port_number=23, timeout=10, display=None): if display is None: display = print - msg = '$ telnet %s %s' % (dest_addr, port_number) - display(msg) ip = lookup_domain(dest_addr) - display('Trying %s...' % ip) + if not ip: + return + msg = 'Trying %s (%s:%s)' % (dest_addr, ip, port_number) + display(msg) try: is_connective, resp = telnet(dest_addr, port_number, timeout) if is_connective: