pytho转发工具
知道创宇Knownsec曾给出的一个rtcp.py脚本做转发之用,不过只支持单点连接。
# -*- coding: utf-8 -*-
'''
filename:rtcp.py
@desc:
利用python的socket端口转发,用于远程维护
如果连接不到远程,会sleep 36s,最多尝试200(即两小时)
@usage:
./rtcp.py stream1 stream2
stream为:l:port或c:host:port
l:port表示监听指定的本地端口
c:host:port表示监听远程指定的端口
@author: watercloud, zd, knownsec team
@web: www.knownsec.com, blog.knownsec.com
@date: 2009-7
'''
import socket
import sys
import threading
import time
streams = [None, None] # 存放需要进行数据转发的两个数据流(都是SocketObj对象)
debug = 1 # 调试状态 0 or 1
def _usage():
print 'Usage: ./rtcp.py stream1 stream2\nstream : l:port or c:host:port'
def _get_another_stream(num):
'''
从streams获取另外一个流对象,如果当前为空,则等待
'''
if num == 0:
num = 1
elif num == 1:
num = 0
else:
raise "ERROR"
while True:
if streams[num] == 'quit':
print("can't connect to the target, quit now!")
sys.exit(1)
if streams[num] != None:
return streams[num]
else:
time.sleep(1)
def _xstream(num, s1, s2):
'''
交换两个流的数据
num为当前流编号,主要用于调试目的,区分两个回路状态用。
'''
try:
while True:
#注意,recv函数会阻塞,直到对端完全关闭(close后还需要一定时间才能关闭,最快关闭方法是shutdow)
buff = s1.recv(1024)
if debug > 0:
print num,"recv"
if len(buff) == 0: #对端关闭连接,读不到数据
print num,"one closed"
break
s2.sendall(buff)
if debug > 0:
print num,"sendall"
except :
print num,"one connect closed."
try:
s1.shutdown(socket.SHUT_RDWR)
s1.close()
except:
pass
try:
s2.shutdown(socket.SHUT_RDWR)
s2.close()
except:
pass
streams[0] = None
streams[1] = None
print num, "CLOSED"
def _server(port, num):
'''
处理服务情况,num为流编号(第0号还是第1号)
'''
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.bind(('0.0.0.0', port))
srv.listen(1)
while True:
conn, addr = srv.accept()
print "connected from:", addr
streams[num] = conn # 放入本端流对象
s2 = _get_another_stream(num) # 获取另一端流对象
_xstream(num, conn, s2)
def _connect(host, port, num):
''' 处理连接,num为流编号(第0号还是第1号)
@note: 如果连接不到远程,会sleep 36s,最多尝试200(即两小时)
'''
not_connet_time = 0
wait_time = 36
try_cnt = 199
while True:
if not_connet_time > try_cnt:
streams[num] = 'quit'
print('not connected')
return None
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
conn.connect((host, port))
except Exception, e:
print ('can not connect %s:%s!' % (host, port))
not_connet_time += 1
time.sleep(wait_time)
continue
print "connected to %s:%i" % (host, port)
streams[num] = conn #放入本端流对象
s2 = _get_another_stream(num) #获取另一端流对象
_xstream(num, conn, s2)
if __name__ == '__main__':
if len(sys.argv) != 3:
_usage()
sys.exit(1)
tlist = [] # 线程列表,最终存放两个线程对象
targv = [sys.argv[1], sys.argv[2] ]
for i in [0, 1]:
s = targv[i] # stream描述 c:ip:port 或 l:port
sl = s.split(':')
if len(sl) == 2 and (sl[0] == 'l' or sl[0] == 'L'): # l:port
t = threading.Thread(target=_server, args=(int(sl[1]), i))
tlist.append(t)
elif len(sl) == 3 and (sl[0] == 'c' or sl[0] == 'C'): # c:host:port
t = threading.Thread(target=_connect, args=(sl[1], int(sl[2]), i))
tlist.append(t)
else:
_usage()
sys.exit(1)
for t in tlist:
t.start()
for t in tlist:
t.join()
sys.exit(0)
使用举例:
1. 公网主机:./rtcp.py l:10001 l:10002 在本地监听了10001与10002两个端口,这样两端口可以相互传输数据了;
2. 目标主机:./rtcp.py c:localhost:22 c:115.116.117.118:10001 把本地的22端口与转发到公网主机的10001端口,使这两个端口也可以互相传输数据了。
3. 此时我们可以通过ssh登录目标主机:ssh 115.116.117.118 -p 10002
原理:当目标主机连接了公网主机的10001端口时,我们通过10002端口发送的数据数据就会传给10001端口,然后传给目标主机的22端口。
配合lcx
10.0.0.1内网机: lcx -slave 8.8.8.8 10001 10.0.0.1 3389
8.8.8.8公网机器:python rtcp.py l:10001 l:10002
然后远程连接8.8.8.8:10002 就好了。
此脚本,支持多client同时连接
来自:http://www.91ri.org/9367.html
代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import socket
import threading
import logging
import optparse
class PipeThread(threading.Thread):
def __init__(self, source_fd, target_fd):
super(PipeThread, self).__init__()
self.logger = logging.getLogger('PipeThread')
self.source_fd = source_fd
self.target_fd = target_fd
self.source_addr = self.source_fd.getpeername()
self.target_addr = self.target_fd.getpeername()
def run(self):
while True:
try:
data = self.source_fd.recv(4096)
if len(data) > 0:
self.logger.debug('read %04i from %s:%d', len(data),self.source_addr[0], self.source_addr[1])
sent = self.target_fd.send(data)
self.logger.debug('write %04i to %s:%d', sent,self.target_addr[0], self.target_addr[1])
else:
break
except socket.error:
break
self.logger.debug('connection %s:%d is closed.', self.source_addr[0],self.source_addr[1])
self.logger.debug('connection %s:%d is closed.', self.target_addr[0],self.target_addr[1])
self.source_fd.close()
self.target_fd.close()
class Forwarder(object):
def __init__(self, ip, port, remoteip, remoteport, backlog=5):
self.remoteip = remoteip
self.remoteport = remoteport
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((ip, port))
self.sock.listen(backlog)
def run(self):
while True:
client_fd, client_addr = self.sock.accept()
target_fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
target_fd.connect((self.remoteip, self.remoteport))
threads = [
PipeThread(client_fd, target_fd),
PipeThread(target_fd, client_fd)
]
for t in threads:
t.setDaemon(True)
t.start()
def __del__(self):
self.sock.close()
if __name__ == '__main__':
parser = optparse.OptionParser()
parser.add_option('-l', '--local-ip', dest='local_ip',help='Local IP address to bind to')
parser.add_option('-p', '--local-port',type='int', dest='local_port',help='Local port to bind to')
parser.add_option('-r', '--remote-ip', dest='remote_ip',help='Local IP address to bind to')
parser.add_option('-P', '--remote-port',type='int', dest='remote_port',help='Remote port to bind to')
parser.add_option('-v', '--verbose',action='store_true', dest='verbose',help='verbose')
opts, args = parser.parse_args()
if len(sys.argv) == 1 or len(args) > 0:
parser.print_help()
exit()
if not (opts.local_ip and opts.local_port and opts.remote_ip and opts.remote_port):
parser.print_help()
exit()
if opts.verbose:
log_level = logging.DEBUG
else:
log_level = logging.CRITICAL
logging.basicConfig(level=log_level, format='%(name)-11s: %(message)s')
forwarder = Forwarder(opts.local_ip, opts.local_port, opts.remote_ip, opts.remote_port)
try:
forwarder.run()
except KeyboardInterrupt:
print 'quit'
exit()
声明:
作者:ssooking 联系邮箱:c3Nvb2tpbmdAeWVhaC5uZXQ=
若无特殊说明,所发博文皆为原创,转载请务必注明出处、保留原文地址。欢迎交流分享!如果您有任何问题,请联系我!
作者:ssooking 联系邮箱:c3Nvb2tpbmdAeWVhaC5uZXQ=
若无特殊说明,所发博文皆为原创,转载请务必注明出处、保留原文地址。欢迎交流分享!如果您有任何问题,请联系我!

浙公网安备 33010602011771号