mirror of https://github.com/jumpserver/jumpserver
perf: 优化 Ping 和 telnet
parent
01c2e7128d
commit
dd8bc5798b
|
@ -1,9 +1,11 @@
|
||||||
|
import socket
|
||||||
from ipaddress import ip_network, ip_address
|
from ipaddress import ip_network, ip_address
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.translation import gettext_lazy as _
|
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 .geoip import get_ip_city_by_geoip
|
||||||
|
from .ipip import get_ip_city_by_ipip
|
||||||
|
|
||||||
|
|
||||||
def is_ip_address(address):
|
def is_ip_address(address):
|
||||||
|
@ -89,3 +91,11 @@ def get_ip_city(ip):
|
||||||
if country == '中国' and is_zh:
|
if country == '中国' and is_zh:
|
||||||
return city
|
return city
|
||||||
return get_ip_city_by_geoip(ip)
|
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
|
||||||
|
|
|
@ -24,21 +24,24 @@ from terminal.notifications import CommandExecutionAlert
|
||||||
|
|
||||||
class Job(JMSOrgBaseModel, PeriodTaskModelMixin):
|
class Job(JMSOrgBaseModel, PeriodTaskModelMixin):
|
||||||
name = models.CharField(max_length=128, null=True, verbose_name=_('Name'))
|
name = models.CharField(max_length=128, null=True, verbose_name=_('Name'))
|
||||||
|
|
||||||
instant = models.BooleanField(default=False)
|
instant = models.BooleanField(default=False)
|
||||||
args = models.CharField(max_length=1024, default='', verbose_name=_('Args'), null=True, blank=True)
|
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,
|
module = models.CharField(max_length=128, choices=Modules.choices, default=Modules.shell, verbose_name=_('Module'),
|
||||||
verbose_name=_('Module'), null=True)
|
null=True)
|
||||||
chdir = models.CharField(default="", max_length=1024, verbose_name=_('Chdir'), null=True, blank=True)
|
chdir = models.CharField(default="", max_length=1024, verbose_name=_('Chdir'), null=True, blank=True)
|
||||||
timeout = models.IntegerField(default=-1, verbose_name=_('Timeout (Seconds)'))
|
timeout = models.IntegerField(default=-1, verbose_name=_('Timeout (Seconds)'))
|
||||||
|
|
||||||
playbook = models.ForeignKey('ops.Playbook', verbose_name=_("Playbook"), null=True, on_delete=models.SET_NULL)
|
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"))
|
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)
|
creator = models.ForeignKey('users.User', verbose_name=_("Creator"), on_delete=models.SET_NULL, null=True)
|
||||||
assets = models.ManyToManyField('assets.Asset', verbose_name=_("Assets"))
|
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 = models.CharField(max_length=128, default='root', verbose_name=_('Runas'))
|
||||||
runas_policy = models.CharField(max_length=128, choices=RunasPolicies.choices, default=RunasPolicies.skip,
|
runas_policy = models.CharField(max_length=128, choices=RunasPolicies.choices, default=RunasPolicies.skip,
|
||||||
verbose_name=_('Runas policy'))
|
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)
|
comment = models.CharField(max_length=1024, default='', verbose_name=_('Comment'), null=True, blank=True)
|
||||||
version = models.IntegerField(default=0)
|
version = models.IntegerField(default=0)
|
||||||
history = HistoricalRecords()
|
history = HistoricalRecords()
|
||||||
|
|
|
@ -7,6 +7,8 @@ import socket
|
||||||
import struct
|
import struct
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from common.utils import lookup_domain
|
||||||
|
|
||||||
# From /usr/include/linux/icmp.h; your milage may vary.
|
# From /usr/include/linux/icmp.h; your milage may vary.
|
||||||
ICMP_ECHO_REQUEST = 8 # Seems to be the same on Solaris.
|
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
|
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
|
Send `count' ping with `psize' size to `dest_addr' with
|
||||||
the given `timeout' and display the result.
|
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):
|
for i in range(count):
|
||||||
print("ping %s with ..." % dest_addr, end="")
|
|
||||||
try:
|
try:
|
||||||
delay = ping(dest_addr, timeout, psize)
|
delay = ping(dest_addr, timeout, psize)
|
||||||
except socket.gaierror as e:
|
except socket.gaierror as e:
|
||||||
print("failed. (socket error: '%s')" % str(e))
|
display("failed. (socket error: '%s')" % str(e))
|
||||||
break
|
break
|
||||||
|
|
||||||
if delay is None:
|
if delay is None:
|
||||||
print("failed. (timeout within %ssec.)" % timeout)
|
display("Request timeout for icmp_seq %i" % i)
|
||||||
else:
|
else:
|
||||||
delay = delay * 1000
|
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()
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
import socket
|
import socket
|
||||||
import telnetlib
|
import telnetlib
|
||||||
|
|
||||||
|
from common.utils import lookup_domain
|
||||||
|
|
||||||
PROMPT_REGEX = r'[\<|\[](.*)[\>|\]]'
|
PROMPT_REGEX = r'[\<|\[](.*)[\>|\]]'
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,10 +18,29 @@ def telnet(dest_addr, port_number=23, timeout=10):
|
||||||
return True, output.decode('utf-8', 'ignore')
|
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__":
|
if __name__ == "__main__":
|
||||||
print(telnet(dest_addr='1.1.1.1', port_number=2222))
|
print(verbose_telnet(dest_addr='1.1.1.1', port_number=2222))
|
||||||
print(telnet(dest_addr='baidu.com', port_number=80))
|
print(verbose_telnet(dest_addr='baidu.com', port_number=80))
|
||||||
print(telnet(dest_addr='baidu.com', port_number=8080))
|
print(verbose_telnet(dest_addr='baidu.com', port_number=8080))
|
||||||
print(telnet(dest_addr='192.168.4.1', port_number=2222))
|
print(verbose_telnet(dest_addr='192.168.4.1', port_number=2222))
|
||||||
print(telnet(dest_addr='192.168.4.1', port_number=2223))
|
print(verbose_telnet(dest_addr='192.168.4.1', port_number=2223))
|
||||||
print(telnet(dest_addr='ssssss', port_number=-1))
|
print(verbose_telnet(dest_addr='ssssss', port_number=-1))
|
||||||
|
|
|
@ -7,7 +7,7 @@ from channels.generic.websocket import JsonWebsocketConsumer
|
||||||
|
|
||||||
from common.db.utils import close_old_connections
|
from common.db.utils import close_old_connections
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
from .utils import ping, telnet
|
from .utils import verbose_ping, verbose_telnet
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
@ -21,45 +21,20 @@ class ToolsWebsocket(JsonWebsocketConsumer):
|
||||||
else:
|
else:
|
||||||
self.close()
|
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):
|
def imitate_ping(self, dest_addr, timeout=3, count=5, psize=64):
|
||||||
"""
|
"""
|
||||||
Send `count' ping with `psize' size to `dest_addr' with
|
Send `count' ping with `psize' size to `dest_addr' with
|
||||||
the given `timeout' and display the result.
|
the given `timeout' and display the result.
|
||||||
"""
|
"""
|
||||||
logger.info('receive request ping {}'.format(dest_addr))
|
logger.info('receive request ping {}'.format(dest_addr))
|
||||||
self.send_json({'msg': 'Trying {0}...\r\n'.format(dest_addr)})
|
verbose_ping(dest_addr, timeout, count, psize, display=self.send_msg)
|
||||||
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})
|
|
||||||
|
|
||||||
def imitate_telnet(self, dest_addr, port_num=23, timeout=10):
|
def imitate_telnet(self, dest_addr, port_num=23, timeout=10):
|
||||||
logger.info('receive request telnet {}'.format(dest_addr))
|
logger.info('receive request telnet {}'.format(dest_addr))
|
||||||
self.send_json({'msg': 'Trying {0} {1}...\r\n'.format(dest_addr, port_num)})
|
verbose_telnet(dest_addr, port_num, timeout, display=self.send_msg)
|
||||||
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})
|
|
||||||
|
|
||||||
def receive(self, text_data=None, bytes_data=None, **kwargs):
|
def receive(self, text_data=None, bytes_data=None, **kwargs):
|
||||||
data = json.loads(text_data)
|
data = json.loads(text_data)
|
||||||
|
|
Loading…
Reference in New Issue