python学习——proxy代理工具

有很多理由让你的工具箱中保留一个TCP代理,它不仅可以将流量从一个主机转发给另一个主机,而且可以评估基于网路的软件。

——Python 黑帽子:黑客与渗透测试编程之道

目录

一、TCP proxy源码

二、proxy源码精讲

2.1 整体框架

2.2 main函数

2.3 server_loop函数

2.4 proxy_handler

三、涉及重要知识整理

3.1 网络编程

3.2 线程编程

四、总结


一、TCP proxy源码

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import sys
import socket
import threading



# 16进制处理函数
def hexdump(src, length=16):
    result = []
    digits = 4 if isinstance(src, unicode) else 2

    for i in xrange(0, len(src), length):
       s = src[i:i+length]
       hexa = b' '.join(["%0*X" % (digits, ord(x))  for x in s])
       text = b''.join([x if 0x20 <= ord(x) < 0x7F else b'.'  for x in s])
       result.append( b"%04X   %-*s   %s" % (i, length*(digits + 1), hexa, text) )

    print b'\n'.join(result)

#数据接收
def receive_from(connection):
        
        buffer = ""

	#发送2秒延迟
	connection.settimeout(2)
	
        try:
                # 从缓冲区里读数据,直到没有数据或超时
                while True:
                        data = connection.recv(4096)
                        
                        if not data:
                                break
                        
                        buffer += data              
                
        except:
		pass
        
        return buffer

# 请求处理
def request_handler(buffer):
	#可以添加修改操作代码
	return buffer

# 响应处理
def response_handler(buffer):
	# 可以添加修改操作代码
	return buffer


def proxy_handler(client_socket, remote_host, remote_port, receive_first):
        
        # 连接远程主机
        remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        remote_socket.connect((remote_host,remote_port))

        # 从远程主机接收数据
        if receive_first:
                
                remote_buffer = receive_from(remote_socket)
                hexdump(remote_buffer)
		
                # 发送到响应处理函数
		remote_buffer = response_handler(remote_buffer)
                
                # 如果有数据给本地客户端,发送它
                if len(remote_buffer):
                        print "[<==] Sending %d bytes to localhost." % len(remote_buffer)
                        client_socket.send(remote_buffer)
                        
	#从本地循环读取数据,发送给远程客户端和本地
	while True:
		
		# 从本地读取
		local_buffer = receive_from(client_socket)


		if len(local_buffer):	
			
			print "[==>] Received %d bytes from localhost." % len(local_buffer)
			hexdump(local_buffer)
			
			# 发送给响应处理函数
			local_buffer = request_handler(local_buffer)
			
			#发送给远程主机
			remote_socket.send(local_buffer)
			print "[==>] Sent to remote."
		
		
		# 接收响应信息
		remote_buffer = receive_from(remote_socket)

		if len(remote_buffer):
			
			print "[<==] Received %d bytes from remote." % len(remote_buffer)
			hexdump(remote_buffer)
			
			# 发送给本地响应处理
			remote_buffer = response_handler(remote_buffer)
		
			# 将响应发送给本地socket
			client_socket.send(remote_buffer)
			
			print "[<==] Sent to localhost."
		
		# 两边都没有数据,关闭连接
		if not len(local_buffer) or not len(remote_buffer):
			client_socket.close()
			remote_socket.close()
			print "[*] No more data. Closing connections."
		
			break
		
def server_loop(local_host,local_port,remote_host,remote_port,receive_first):
                
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        try:
                server.bind((local_host,local_port))
        except:
                print "[!!] Failed to listen on %s:%d" % (local_host,local_port)
                print "[!!] Check for other listening sockets or correct permissions."
                sys.exit(0)
                
        print "[*] Listening on %s:%d" % (local_host,local_port)
        
        
        server.listen(5)        
        
        while True:
                client_socket, addr = server.accept()
               
                #打印本地连接信息
                print "[==>] Received incoming connection from %s:%d" % (addr[0],addr[1])
                
                # 创建一个线程去连接远程主机
                proxy_thread = threading.Thread(target=proxy_handler,args=(client_socket,remote_host,remote_port,receive_first))
                proxy_thread.start()

def main():
        
    if len(sys.argv[1:]) != 5:
        print "Usage: ./proxy.py [localhost] [localport] [remotehost] [remoteport] [receive_first]"
        print "Example: ./proxy.py 127.0.0.1 9000 10.12.132.1 9000 True"
        sys.exit(0)
    
    # 设置本地监听参数
    local_host  = sys.argv[1]
    local_port  = int(sys.argv[2])
    
    # 设置远程目标
    remote_host = sys.argv[3]
    remote_port = int(sys.argv[4])
    
    # 告诉代理在发送给远程主机之前连接和接收数据
    receive_first = sys.argv[5]
    
    if "True" in receive_first:
	    receive_first = True
    else:
	    receive_first = False
	    
    
    # 设置好监听
    server_loop(local_host,local_port,remote_host,remote_port,receive_first)
        
main() 

二、proxy源码精讲

2.1 整体框架

2.2 main函数

2.3 server_loop函数

2.4 proxy_handler

三、涉及重要知识整理

3.1 网络编程

Python 提供了两个级别访问的网络服务:

  • 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。
  • 高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。

Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求:

格式:socket.socket([family[, type[, protocal]]])

  参数

family: 套接字家族可以使AF_UNIX或者AF_INET
type: 套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
protocol: 一般不填默认为0

   函数

3.2 线程编程

Python创建Thread对象语法如下:

import threading
threading.Thread(target=None, name=None,  args=())

参数

target 是函数名字,需要调用的函数。
name 设置线程名字。
args 函数需要的参数,以元祖( tuple)的形式传入

函数

run(): 用以表示线程活动的方法。
start():启动线程活动。
join(): 等待至线程中止。
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。

四、总结

有志者自有千计万计,无志者只感千难万难。

猜你喜欢

转载自blog.csdn.net/xlsj228/article/details/91038785