Loading

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()

  

posted @ 2016-11-23 19:28  ssooking  阅读(255)  评论(0编辑  收藏  举报