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=
若无特殊说明,所发博文皆为原创,转载请务必注明出处、保留原文地址。欢迎交流分享!如果您有任何问题,请联系我!