Commit d7b0dd1e authored by ibuler's avatar ibuler

[UPdate] 更新coco

parent 1a754877
...@@ -47,7 +47,7 @@ authors' sake, the GPL requires that modified versions be marked as ...@@ -47,7 +47,7 @@ authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to changed, so that their problems will not be attributed erroneously to
authors of previous versions. authors of previous versions.
Some devices are designed to deny users access to install or run Some devices are designed to deny users access to install or start_worker
modified versions of the software inside them, although the manufacturer modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic protecting users' freedom to change the software. The systematic
...@@ -129,11 +129,11 @@ implementation is available to the public in source code form. A ...@@ -129,11 +129,11 @@ implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component "Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system (kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to (if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it. produce the work, or an object code interpreter used to start_worker it.
The "Corresponding Source" for a work in object code form means all The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to work) start_worker the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but programs which are used unmodified in performing those activities but
...@@ -156,12 +156,12 @@ same work. ...@@ -156,12 +156,12 @@ same work.
All rights granted under this License are granted for the term of All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a permission to start_worker the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law. rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not You may make, start_worker and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you of having them make modifications exclusively for you, or provide you
...@@ -435,7 +435,7 @@ material under section 10. ...@@ -435,7 +435,7 @@ material under section 10.
9. Acceptance Not Required for Having Copies. 9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work start_worker a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However, to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or nothing other than this License grants you permission to propagate or
...@@ -446,7 +446,7 @@ covered work, you indicate your acceptance of this License to do so. ...@@ -446,7 +446,7 @@ covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients. 10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and receives a license from the original licensors, to start_worker, modify and
propagate that work, subject to this License. You are not responsible propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License. for enforcing compliance by third parties with this License.
...@@ -486,7 +486,7 @@ this License. ...@@ -486,7 +486,7 @@ this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and make, use, sell, offer for sale, import and otherwise start_worker, modify and
propagate the contents of its contributor version. propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express In the following three paragraphs, a "patent license" is any express
......
...@@ -31,7 +31,7 @@ Also some config you need kown: ...@@ -31,7 +31,7 @@ Also some config you need kown:
## Start ## Start
# python run_server.py # python start_server.py
When your start ssh server, It will register with jumpserver api, When your start ssh server, It will register with jumpserver api,
......
...@@ -18,7 +18,7 @@ from .httpd import HttpServer ...@@ -18,7 +18,7 @@ from .httpd import HttpServer
from .logger import create_logger from .logger import create_logger
from .tasks import TaskHandler from .tasks import TaskHandler
from .recorder import get_command_recorder_class, ServerReplayRecorder from .recorder import get_command_recorder_class, ServerReplayRecorder
from .utils import get_logger from .utils import get_logger, register_app, register_service
__version__ = '1.3.0' __version__ = '1.3.0'
...@@ -67,6 +67,7 @@ class Coco: ...@@ -67,6 +67,7 @@ class Coco:
self.replay_recorder_class = None self.replay_recorder_class = None
self.command_recorder_class = None self.command_recorder_class = None
self._task_handler = None self._task_handler = None
register_app(self)
@property @property
def name(self): def name(self):
...@@ -79,12 +80,13 @@ class Coco: ...@@ -79,12 +80,13 @@ class Coco:
def service(self): def service(self):
if self._service is None: if self._service is None:
self._service = AppService(self) self._service = AppService(self)
register_service(self._service)
return self._service return self._service
@property @property
def sshd(self): def sshd(self):
if self._sshd is None: if self._sshd is None:
self._sshd = SSHServer(self) self._sshd = SSHServer()
return self._sshd return self._sshd
@property @property
......
# -*- coding: utf-8 -*-
#
current_app = []
current_service = []
...@@ -5,15 +5,13 @@ import os ...@@ -5,15 +5,13 @@ import os
import socket import socket
import uuid import uuid
import traceback import traceback
from flask_socketio import SocketIO, Namespace, join_room, leave_room from flask_socketio import SocketIO, Namespace, join_room
from flask import Flask, request, current_app, redirect from flask import Flask, request, current_app, redirect
from copy import deepcopy
from .models import Request, Client, WSProxy from .models import Request, Client, WSProxy
from .proxy import ProxyServer from .proxy import ProxyServer
from .utils import get_logger from .utils import get_logger
__version__ = '0.5.0'
BASE_DIR = os.path.dirname(os.path.dirname(__file__)) BASE_DIR = os.path.dirname(os.path.dirname(__file__))
logger = get_logger(__file__) logger = get_logger(__file__)
......
...@@ -8,30 +8,16 @@ import time ...@@ -8,30 +8,16 @@ import time
import os import os
import gzip import gzip
import json import json
import shutil
import jms_storage import jms_storage
from .utils import get_logger from .utils import get_logger, Singleton
from .alignment import MemoryQueue from .alignment import MemoryQueue
logger = get_logger(__file__) logger = get_logger(__file__)
BUF_SIZE = 1024 BUF_SIZE = 1024
class Singleton(type):
def __init__(cls, *args, **kwargs):
cls.__instance = None
super().__init__(*args, **kwargs)
def __call__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super().__call__(*args, **kwargs)
return cls.__instance
else:
return cls.__instance
class ReplayRecorder(metaclass=abc.ABCMeta): class ReplayRecorder(metaclass=abc.ABCMeta):
def __init__(self, app, session=None): def __init__(self, app, session=None):
self.app = app self.app = app
......
...@@ -34,7 +34,7 @@ class SFTPServer(paramiko.SFTPServerInterface): ...@@ -34,7 +34,7 @@ class SFTPServer(paramiko.SFTPServerInterface):
self._sftp[host] = sftp self._sftp[host] = sftp
return sftp return sftp
else: else:
raise OSError("Can not connect asset sftp server") raise OSError("Can not connect asset sftp server: {}".format(msg))
else: else:
return self._sftp[host] return self._sftp[host]
......
...@@ -5,9 +5,12 @@ ...@@ -5,9 +5,12 @@
import os import os
import socket import socket
import threading import threading
import random
import paramiko import paramiko
from multiprocessing.reduction import recv_handle, send_handle
from multiprocessing import Process, Pipe
from .utils import ssh_key_gen, get_logger from .utils import ssh_key_gen, get_logger, get_app
from .interface import SSHInterface from .interface import SSHInterface
from .interactive import InteractiveServer from .interactive import InteractiveServer
from .models import Client, Request from .models import Client, Request
...@@ -19,11 +22,15 @@ BACKLOG = 5 ...@@ -19,11 +22,15 @@ BACKLOG = 5
class SSHServer: class SSHServer:
def __init__(self, app): def __init__(self):
self.app = app
self.stop_evt = threading.Event() self.stop_evt = threading.Event()
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.host_key_path = os.path.join(self.app.root_path, 'keys', 'host_rsa_key') self.host_key_path = os.path.join(self.app.root_path, 'keys', 'host_rsa_key')
self.workers = []
self.pipe = None
@property
def app(self):
return get_app()
@property @property
def host_key(self): def host_key(self):
...@@ -36,22 +43,45 @@ class SSHServer: ...@@ -36,22 +43,45 @@ class SSHServer:
with open(self.host_key_path, 'w') as f: with open(self.host_key_path, 'w') as f:
f.write(ssh_key) f.write(ssh_key)
def run(self): def start_worker(self, in_pipe, out_pipe):
print("APP: {}".format(self.app))
print("APP sessions: {}".format(self.app))
out_pipe.close()
while not self.stop_evt.is_set():
fd = recv_handle(in_pipe)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, fileno=fd)
addr = sock.getpeername()
thread = threading.Thread(target=self.handle_connection, args=(sock, addr))
thread.daemon = True
thread.start()
def start_server(self, in_pipe, out_pipe, workers):
in_pipe.close()
host = self.app.config["BIND_HOST"] host = self.app.config["BIND_HOST"]
port = self.app.config["SSHD_PORT"] port = self.app.config["SSHD_PORT"]
print('Starting ssh server at {}:{}'.format(host, port)) print('Starting ssh server at {}:{}'.format(host, port))
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.bind((host, port)) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.listen(BACKLOG) sock.bind((host, port))
sock.listen(BACKLOG)
while not self.stop_evt.is_set(): while not self.stop_evt.is_set():
try: client, addr = sock.accept()
sock, addr = self.sock.accept() logger.info("Get ssh request from {}".format(addr))
logger.info("Get ssh request from {}: {}".format(addr[0], addr[1])) send_handle(out_pipe, client.fileno(), random.choice(workers).pid)
thread = threading.Thread(target=self.handle_connection, args=(sock, addr)) client.close()
thread.daemon = True
thread.start() def run(self):
except Exception as e: in_pipe, out_pipe = Pipe()
logger.error("Start SSH server error: {}".format(e)) self.pipe = (in_pipe, out_pipe)
workers = []
for i in range(4):
worker = Process(target=self.start_worker, args=(in_pipe, out_pipe))
worker.start()
workers.append(worker)
self.start_server(in_pipe, out_pipe, workers)
in_pipe.close()
out_pipe.close()
def handle_connection(self, sock, addr): def handle_connection(self, sock, addr):
transport = paramiko.Transport(sock, gss_kex=False) transport = paramiko.Transport(sock, gss_kex=False)
......
...@@ -15,10 +15,24 @@ import paramiko ...@@ -15,10 +15,24 @@ import paramiko
import pyte import pyte
from . import char from . import char
from .ctx import current_app, current_service
BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
class Singleton(type):
def __init__(cls, *args, **kwargs):
cls.__instance = None
super().__init__(*args, **kwargs)
def __call__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super().__call__(*args, **kwargs)
return cls.__instance
else:
return cls.__instance
def ssh_key_string_to_obj(text, password=None): def ssh_key_string_to_obj(text, password=None):
key = None key = None
try: try:
...@@ -355,4 +369,26 @@ def net_input(client, prompt='Opt> ', sensitive=False): ...@@ -355,4 +369,26 @@ def net_input(client, prompt='Opt> ', sensitive=False):
input_data.append(data) input_data.append(data)
def register_app(app):
current_app.insert(0, app)
def register_service(service):
current_service.insert(0, service)
def get_app():
if current_app:
return current_app[0]
else:
raise ValueError("App not found")
def get_service():
if current_service:
return current_app[0]
else:
raise ValueError("Service not found")
ugettext = _gettext() ugettext = _gettext()
...@@ -126,7 +126,7 @@ if __name__ == '__main__': ...@@ -126,7 +126,7 @@ if __name__ == '__main__':
parser.add_argument( parser.add_argument(
'action', type=str, default='start', 'action', type=str, default='start',
choices=("start", "stop", "restart", "status"), choices=("start", "stop", "restart", "status"),
help="Action to run" help="Action to start_worker"
) )
parser.add_argument('-d', '--daemon', nargs="?", const=1) parser.add_argument('-d', '--daemon', nargs="?", const=1)
......
...@@ -28,7 +28,7 @@ psutil==5.4.1 ...@@ -28,7 +28,7 @@ psutil==5.4.1
pyasn1==0.4.2 pyasn1==0.4.2
pycparser==2.18 pycparser==2.18
PyNaCl==1.2.1 PyNaCl==1.2.1
pyte==0.7.0 pyte==0.8.0
python-dateutil==2.6.1 python-dateutil==2.6.1
python-engineio==2.1.0 python-engineio==2.1.0
python-gssapi==0.6.4 python-gssapi==0.6.4
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment