Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
C
coco
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
coco
Commits
af0cb201
Commit
af0cb201
authored
Oct 23, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix some bug
parent
74713b64
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
72 additions
and
55 deletions
+72
-55
forward.py
coco/forward.py
+26
-5
interactive.py
coco/interactive.py
+11
-8
interface.py
coco/interface.py
+1
-1
models.py
coco/models.py
+7
-12
session.py
coco/session.py
+2
-3
sshd.py
coco/sshd.py
+20
-21
ws.py
coco/ws.py
+5
-5
No files found.
coco/forward.py
View file @
af0cb201
...
@@ -5,22 +5,26 @@ import threading
...
@@ -5,22 +5,26 @@ import threading
import
logging
import
logging
import
paramiko
import
paramiko
import
time
from
.session
import
Session
from
.session
import
Session
from
.models
import
Server
from
.models
import
Server
logger
=
logging
.
getLogger
(
__file__
)
logger
=
logging
.
getLogger
(
__file__
)
TIMEOUT
=
8
class
ProxyServer
:
class
ProxyServer
:
def
__init__
(
self
,
app
,
client
,
request
):
def
__init__
(
self
,
app
,
client
):
self
.
app
=
app
self
.
app
=
app
self
.
request
=
request
self
.
client
=
client
self
.
client
=
client
self
.
request
=
client
.
request
self
.
server
=
None
self
.
server
=
None
self
.
connecting
=
True
def
proxy
(
self
,
asset
,
system_user
):
def
proxy
(
self
,
asset
,
system_user
):
self
.
send_connecting_message
()
self
.
server
=
self
.
get_server_conn
(
asset
,
system_user
)
self
.
server
=
self
.
get_server_conn
(
asset
,
system_user
)
if
self
.
server
is
None
:
if
self
.
server
is
None
:
return
return
...
@@ -46,6 +50,7 @@ class ProxyServer:
...
@@ -46,6 +50,7 @@ class ProxyServer:
"""
"""
def
get_server_conn
(
self
,
asset
,
system_user
):
def
get_server_conn
(
self
,
asset
,
system_user
):
logger
.
info
(
"Connect to
%
s"
%
asset
.
hostname
)
if
not
self
.
validate_permission
(
asset
,
system_user
):
if
not
self
.
validate_permission
(
asset
,
system_user
):
self
.
client
.
send
(
b
'No permission'
)
self
.
client
.
send
(
b
'No permission'
)
return
None
return
None
...
@@ -57,14 +62,18 @@ class ProxyServer:
...
@@ -57,14 +62,18 @@ class ProxyServer:
ssh
.
connect
(
asset
.
ip
,
port
=
asset
.
port
,
ssh
.
connect
(
asset
.
ip
,
port
=
asset
.
port
,
username
=
system_user
.
username
,
username
=
system_user
.
username
,
password
=
system_user
.
password
,
password
=
system_user
.
password
,
pkey
=
system_user
.
private_key
)
pkey
=
system_user
.
private_key
,
timeout
=
TIMEOUT
)
except
paramiko
.
AuthenticationException
as
e
:
except
paramiko
.
AuthenticationException
as
e
:
self
.
client
.
send
(
"Authentication failed: {}"
.
format
(
e
)
.
encode
(
"utf-8"
))
self
.
client
.
send
(
"
[Errno 66]
Authentication failed: {}"
.
format
(
e
)
.
encode
(
"utf-8"
))
return
None
return
None
except
socket
.
error
as
e
:
except
socket
.
error
as
e
:
self
.
client
.
send
(
"
Connection server error:
{}"
.
format
(
e
)
.
encode
(
"utf-8"
))
self
.
client
.
send
(
" {}"
.
format
(
e
)
.
encode
(
"utf-8"
))
return
None
return
None
finally
:
self
.
connecting
=
False
self
.
client
.
send
(
b
'
\r\n
'
)
term
=
self
.
request
.
meta
.
get
(
'term'
,
'xterm'
)
term
=
self
.
request
.
meta
.
get
(
'term'
,
'xterm'
)
width
=
self
.
request
.
meta
.
get
(
'width'
,
80
)
width
=
self
.
request
.
meta
.
get
(
'width'
,
80
)
...
@@ -85,3 +94,15 @@ class ProxyServer:
...
@@ -85,3 +94,15 @@ class ProxyServer:
thread
.
daemon
=
True
thread
.
daemon
=
True
thread
.
start
()
thread
.
start
()
def
send_connecting_message
(
self
):
def
func
():
delay
=
0.0
self
.
client
.
send
(
'Connecting to {} {:.1f}'
.
format
(
'abc.com'
,
delay
)
.
encode
(
'utf-8'
))
while
self
.
connecting
and
delay
<
TIMEOUT
:
self
.
client
.
send
(
'
\x08\x08\x08
{:.1f}'
.
format
(
delay
)
.
encode
(
'utf-8'
))
time
.
sleep
(
0.1
)
delay
+=
0.1
thread
=
threading
.
Thread
(
target
=
func
)
thread
.
daemon
=
True
thread
.
start
()
coco/interactive.py
View file @
af0cb201
#!coding: utf-8
#!coding: utf-8
import
logging
import
socket
import
socket
import
threading
import
threading
...
@@ -9,13 +10,15 @@ from .forward import ProxyServer
...
@@ -9,13 +10,15 @@ from .forward import ProxyServer
from
.models
import
Asset
,
SystemUser
from
.models
import
Asset
,
SystemUser
from
.session
import
Session
from
.session
import
Session
logger
=
logging
.
getLogger
(
__file__
)
class
InteractiveServer
:
class
InteractiveServer
:
def
__init__
(
self
,
app
,
request
,
client
):
def
__init__
(
self
,
app
,
client
):
self
.
app
=
app
self
.
app
=
app
self
.
request
=
request
self
.
client
=
client
self
.
client
=
client
self
.
request
=
client
.
request
def
display_banner
(
self
):
def
display_banner
(
self
):
self
.
client
.
send
(
char
.
CLEAR_CHAR
)
self
.
client
.
send
(
char
.
CLEAR_CHAR
)
...
@@ -40,8 +43,7 @@ class InteractiveServer:
...
@@ -40,8 +43,7 @@ class InteractiveServer:
"""
"""
# Todo: 实现自动hostname或IP补全
# Todo: 实现自动hostname或IP补全
input_data
=
[]
input_data
=
[]
parser
=
TtyIOParser
(
self
.
request
.
meta
.
get
(
"width"
,
80
),
parser
=
TtyIOParser
()
self
.
request
.
meta
.
get
(
"height"
,
24
))
self
.
client
.
send
(
wr
(
prompt
,
before
=
1
,
after
=
0
))
self
.
client
.
send
(
wr
(
prompt
,
before
=
1
,
after
=
0
))
while
True
:
while
True
:
data
=
self
.
client
.
recv
(
10
)
data
=
self
.
client
.
recv
(
10
)
...
@@ -128,10 +130,10 @@ class InteractiveServer:
...
@@ -128,10 +130,10 @@ class InteractiveServer:
def
search_and_proxy
(
self
,
opt
,
from_result
=
False
):
def
search_and_proxy
(
self
,
opt
,
from_result
=
False
):
asset
=
Asset
(
id
=
1
,
hostname
=
"testserver"
,
ip
=
"192.168.244.164"
,
port
=
22
)
asset
=
Asset
(
id
=
1
,
hostname
=
"testserver"
,
ip
=
"192.168.244.164"
,
port
=
22
)
system_user
=
SystemUser
(
id
=
2
,
username
=
"root"
,
password
=
"redhat"
,
name
=
"web"
)
system_user
=
SystemUser
(
id
=
2
,
username
=
"root"
,
password
=
"redhat"
,
name
=
"web"
)
self
.
connect
(
asset
,
system_user
)
self
.
proxy
(
asset
,
system_user
)
def
connect
(
self
,
asset
,
system_user
):
def
proxy
(
self
,
asset
,
system_user
):
forwarder
=
ProxyServer
(
self
.
app
,
self
.
client
,
self
.
request
)
forwarder
=
ProxyServer
(
self
.
app
,
self
.
client
)
forwarder
.
proxy
(
asset
,
system_user
)
forwarder
.
proxy
(
asset
,
system_user
)
def
replay_session
(
self
,
session_id
):
def
replay_session
(
self
,
session_id
):
...
@@ -145,7 +147,8 @@ class InteractiveServer:
...
@@ -145,7 +147,8 @@ class InteractiveServer:
try
:
try
:
opt
=
self
.
get_choice
()
opt
=
self
.
get_choice
()
self
.
dispatch
(
opt
)
self
.
dispatch
(
opt
)
except
socket
.
error
:
except
socket
.
error
as
e
:
logger
.
error
(
"Cocket error
%
s"
%
e
)
break
break
self
.
close
()
self
.
close
()
...
...
coco/interface.py
View file @
af0cb201
...
@@ -100,7 +100,7 @@ class SSHInterface(paramiko.ServerInterface):
...
@@ -100,7 +100,7 @@ class SSHInterface(paramiko.ServerInterface):
return
paramiko
.
OPEN_SUCCEEDED
return
paramiko
.
OPEN_SUCCEEDED
def
check_channel_shell_request
(
self
,
channel
):
def
check_channel_shell_request
(
self
,
channel
):
logger
.
info
(
"Check channel shell request:
%
s"
%
channel
)
logger
.
info
(
"Check channel shell request:
%
s"
%
channel
.
get_id
()
)
self
.
event
.
set
()
self
.
event
.
set
()
return
True
return
True
...
...
coco/models.py
View file @
af0cb201
...
@@ -58,11 +58,12 @@ class SystemUser(Decoder):
...
@@ -58,11 +58,12 @@ class SystemUser(Decoder):
class
Request
:
class
Request
:
def
__init__
(
self
,
remote_ip
=
""
):
def
__init__
(
self
,
addr
):
self
.
type
=
""
self
.
type
=
""
self
.
meta
=
{}
self
.
meta
=
{}
self
.
user
=
None
self
.
user
=
None
self
.
remote_ip
=
remote_ip
self
.
addr
=
addr
self
.
remote_ip
=
self
.
addr
[
0
]
self
.
change_size_event
=
threading
.
Event
()
self
.
change_size_event
=
threading
.
Event
()
self
.
date_start
=
datetime
.
datetime
.
now
()
self
.
date_start
=
datetime
.
datetime
.
now
()
...
@@ -74,13 +75,13 @@ class Client:
...
@@ -74,13 +75,13 @@ class Client:
```
```
client = Client(chan, addr, user)
client = Client(chan, addr, user)
```
```
"""
"""
def
__init__
(
self
,
chan
,
addr
,
user
):
def
__init__
(
self
,
chan
,
request
):
self
.
chan
=
chan
self
.
chan
=
chan
self
.
addr
=
addr
self
.
request
=
request
self
.
user
=
user
self
.
user
=
request
.
user
self
.
addr
=
request
.
addr
def
fileno
(
self
):
def
fileno
(
self
):
return
self
.
chan
.
fileno
()
return
self
.
chan
.
fileno
()
...
@@ -119,7 +120,6 @@ class Server:
...
@@ -119,7 +120,6 @@ class Server:
self
.
output
=
''
self
.
output
=
''
self
.
_in_input_state
=
True
self
.
_in_input_state
=
True
self
.
_input_initial
=
False
self
.
_input_initial
=
False
self
.
_in_auto_complete_state
=
False
self
.
_in_vim_state
=
False
self
.
_in_vim_state
=
False
def
fileno
(
self
):
def
fileno
(
self
):
...
@@ -140,11 +140,6 @@ class Server:
...
@@ -140,11 +140,6 @@ class Server:
del
self
.
output_data
[:]
del
self
.
output_data
[:]
self
.
_in_input_state
=
True
self
.
_in_input_state
=
True
# if b == '\t':
# self._in_auto_complete_state = True
# else:
# self._in_auto_complete_state = False
print
(
"Send:
%
s"
%
b
)
print
(
"Send:
%
s"
%
b
)
return
self
.
chan
.
send
(
b
)
return
self
.
chan
.
send
(
b
)
...
...
coco/session.py
View file @
af0cb201
...
@@ -37,7 +37,7 @@ class Session:
...
@@ -37,7 +37,7 @@ class Session:
:param silent: If true not send welcome message
:param silent: If true not send welcome message
:return:
:return:
"""
"""
logger
.
info
(
"Session
%
add watcher
%
s"
%
(
self
,
watcher
))
logger
.
info
(
"Session
%
s
add watcher
%
s"
%
(
self
,
watcher
))
if
not
silent
:
if
not
silent
:
watcher
.
send
(
"Welcome to watch session {}
\r\n
"
.
format
(
self
.
id
)
.
encode
(
"utf-8"
))
watcher
.
send
(
"Welcome to watch session {}
\r\n
"
.
format
(
self
.
id
)
.
encode
(
"utf-8"
))
self
.
sel
.
register
(
watcher
,
selectors
.
EVENT_READ
)
self
.
sel
.
register
(
watcher
,
selectors
.
EVENT_READ
)
...
@@ -165,8 +165,7 @@ class Session:
...
@@ -165,8 +165,7 @@ class Session:
def
close
(
self
):
def
close
(
self
):
self
.
running
=
False
self
.
running
=
False
for
chan
in
[
self
.
client
,
self
.
server
]
+
self
.
watchers
+
self
.
sharers
:
self
.
server
.
close
()
chan
.
close
()
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
id
return
self
.
id
...
...
coco/sshd.py
View file @
af0cb201
...
@@ -22,18 +22,9 @@ class SSHServer:
...
@@ -22,18 +22,9 @@ class SSHServer:
self
.
stop_event
=
threading
.
Event
()
self
.
stop_event
=
threading
.
Event
()
self
.
sock
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
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
.
host_key
=
self
.
get_host_key
()
def
listen
(
self
):
@property
host
=
self
.
app
.
config
[
"BIND_HOST"
]
def
host_key
(
self
):
port
=
self
.
app
.
config
[
"SSHD_PORT"
]
print
(
'Starting ssh server at
%(host)
s:
%(port)
s'
%
{
"host"
:
host
,
"port"
:
port
})
self
.
sock
.
setsockopt
(
socket
.
SOL_SOCKET
,
socket
.
SO_REUSEADDR
,
1
)
self
.
sock
.
bind
((
host
,
port
))
self
.
sock
.
listen
(
BACKLOG
)
def
get_host_key
(
self
):
if
not
os
.
path
.
isfile
(
self
.
host_key_path
):
if
not
os
.
path
.
isfile
(
self
.
host_key_path
):
self
.
gen_host_key
()
self
.
gen_host_key
()
return
paramiko
.
RSAKey
(
filename
=
self
.
host_key_path
)
return
paramiko
.
RSAKey
(
filename
=
self
.
host_key_path
)
...
@@ -44,7 +35,13 @@ class SSHServer:
...
@@ -44,7 +35,13 @@ class SSHServer:
f
.
write
(
ssh_key
)
f
.
write
(
ssh_key
)
def
run
(
self
):
def
run
(
self
):
self
.
listen
()
host
=
self
.
app
.
config
[
"BIND_HOST"
]
port
=
self
.
app
.
config
[
"SSHD_PORT"
]
print
(
'Starting ssh server at
%(host)
s:
%(port)
s'
%
{
"host"
:
host
,
"port"
:
port
})
self
.
sock
.
setsockopt
(
socket
.
SOL_SOCKET
,
socket
.
SO_REUSEADDR
,
1
)
self
.
sock
.
bind
((
host
,
port
))
self
.
sock
.
listen
(
BACKLOG
)
while
not
self
.
stop_event
.
is_set
():
while
not
self
.
stop_event
.
is_set
():
try
:
try
:
sock
,
addr
=
self
.
sock
.
accept
()
sock
,
addr
=
self
.
sock
.
accept
()
...
@@ -63,7 +60,7 @@ class SSHServer:
...
@@ -63,7 +60,7 @@ class SSHServer:
logger
.
warning
(
"Failed load moduli -- gex will be unsupported"
)
logger
.
warning
(
"Failed load moduli -- gex will be unsupported"
)
transport
.
add_server_key
(
self
.
host_key
)
transport
.
add_server_key
(
self
.
host_key
)
request
=
Request
()
request
=
Request
(
addr
)
server
=
SSHInterface
(
self
.
app
,
request
)
server
=
SSHInterface
(
self
.
app
,
request
)
try
:
try
:
transport
.
start_server
(
server
=
server
)
transport
.
start_server
(
server
=
server
)
...
@@ -72,6 +69,7 @@ class SSHServer:
...
@@ -72,6 +69,7 @@ class SSHServer:
sys
.
exit
(
1
)
sys
.
exit
(
1
)
except
EOFError
:
except
EOFError
:
logger
.
warning
(
"EOF Error"
)
logger
.
warning
(
"EOF Error"
)
sys
.
exit
(
1
)
chan
=
transport
.
accept
(
10
)
chan
=
transport
.
accept
(
10
)
if
chan
is
None
:
if
chan
is
None
:
...
@@ -83,19 +81,20 @@ class SSHServer:
...
@@ -83,19 +81,20 @@ class SSHServer:
logger
.
warning
(
"Client not request a valid request"
)
logger
.
warning
(
"Client not request a valid request"
)
sys
.
exit
(
2
)
sys
.
exit
(
2
)
client
=
Client
(
chan
,
addr
,
request
.
user
)
client
=
Client
(
chan
,
request
)
self
.
app
.
add_client
(
client
)
self
.
app
.
add_client
(
client
)
self
.
dispatch
(
request
,
client
)
self
.
dispatch
(
client
)
def
dispatch
(
self
,
request
,
client
):
def
dispatch
(
self
,
client
):
if
request
.
type
==
'pty'
:
request_type
=
client
.
request
.
type
InteractiveServer
(
self
.
app
,
request
,
client
)
.
activate
()
if
request_type
==
'pty'
:
elif
request
.
type
==
'exec'
:
InteractiveServer
(
self
.
app
,
client
)
.
activate
()
elif
request_type
==
'exec'
:
pass
pass
elif
request
.
type
==
'subsystem'
:
elif
request
_
type
==
'subsystem'
:
pass
pass
else
:
else
:
client
.
send
(
"Not support request type:
%
s"
%
request
.
type
)
client
.
send
(
"Not support request type:
%
s"
%
request
_
type
)
def
shutdown
(
self
):
def
shutdown
(
self
):
self
.
stop_event
.
set
()
self
.
stop_event
.
set
()
coco/ws.py
View file @
af0cb201
...
@@ -20,8 +20,10 @@ class BaseWehSocketHandler:
...
@@ -20,8 +20,10 @@ class BaseWehSocketHandler:
def
prepare
(
self
):
def
prepare
(
self
):
self
.
app
=
self
.
settings
[
"app"
]
self
.
app
=
self
.
settings
[
"app"
]
child
,
parent
=
socket
.
socketpair
()
child
,
parent
=
socket
.
socketpair
()
addr
=
(
self
.
request
.
remote_ip
,
0
)
request
=
Request
((
self
.
request
.
remote_ip
,
0
))
self
.
client
=
Client
(
parent
,
addr
,
self
.
current_user
)
request
.
user
=
self
.
current_user
self
.
request
.
__dict__
.
update
(
request
.
__dict__
)
self
.
client
=
Client
(
parent
,
self
.
request
)
self
.
proxy
=
WSProxy
(
self
,
child
)
self
.
proxy
=
WSProxy
(
self
,
child
)
self
.
app
.
clients
.
append
(
self
.
client
)
self
.
app
.
clients
.
append
(
self
.
client
)
...
@@ -35,9 +37,7 @@ class BaseWehSocketHandler:
...
@@ -35,9 +37,7 @@ class BaseWehSocketHandler:
class
InteractiveWehSocketHandler
(
BaseWehSocketHandler
,
tornado
.
websocket
.
WebSocketHandler
):
class
InteractiveWehSocketHandler
(
BaseWehSocketHandler
,
tornado
.
websocket
.
WebSocketHandler
):
@tornado.web.authenticated
@tornado.web.authenticated
def
open
(
self
):
def
open
(
self
):
request
=
Request
(
self
.
request
.
remote_ip
)
InteractiveServer
(
self
.
app
,
self
.
client
)
.
activate_async
()
self
.
request
.
__dict__
.
update
(
request
.
__dict__
)
InteractiveServer
(
self
.
app
,
self
.
request
,
self
.
client
)
.
activate_async
()
def
on_message
(
self
,
message
):
def
on_message
(
self
,
message
):
try
:
try
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment