python socket实现http代理
import socket
from urllib.parse import urlparse
def proxy(client_socket):
'''代理客户端socket'''
recv_data = b''
while True:
tmp_data = client_socket.recv(1024)
recv_data += tmp_data
if len(tmp_data) < 1024:
break
headers = analysis_head(recv_data.decode().split('\r\n\r\n', 1)[0])
send_data = get_target_data(headers, recv_data.decode().split('\r\n\r\n', 1)[1])
head_data = send_data.decode('utf-8', errors='replace').split('\r\n\r\n', 1)[0]
body_data = send_data.decode('utf-8', errors='replace').split('\r\n\r\n', 1)[1].encode('utf-8')
head_data += '\r\n' + f'Content-Length: {len(body_data)}' + '\r\n\r\n'
send_data = head_data.encode('utf-8') + body_data
cut_send(client_socket, send_data)
def analysis_head(head_data):
'''分析请求头
Args:
head_data 原始请求头信息
Return:
headers 解析后的请求头字典
'''
head_list = head_data.split('\r\n')
method, url, protocol = head_list[0].split(' ')[0], head_list[0].split(' ')[1], head_list[0].split(' ')[2].split('/')[0]
headers = {}
url = urlparse(url)
headers['method'] = method
headers['target_url'] = url
headers['protocol'] = protocol
for _ in head_list[1:]:
key, value = _.split(':', 1)[0].strip(), _.split(':', 1)[1].strip()
headers[key] = value
return headers
def get_target_data(headers, body):
'''获取目标网站数据
Args:
headers 解析后的header字典
body 请求体
Return:
recv_data 目标网站数据
'''
target_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if len(headers.get('Host').split(':')) > 1:
port = int(headers.get('Host').split(':')[1])
elif headers.get('protocol') == 'HTTP':
port = 80
else:
port = 443
target_client.connect((socket.gethostbyname(headers.get('Host').split(':', 1)[0]), port))
body = body.encode('utf-8')
tmp_data = f"{headers.get('method')} {headers.get('target_url').path} {headers.get('protocol')}/1.1\r\nPragma: no-cache\r\nConnection: close\r\nContent-Length: {len(body)}\r\n"
del headers['method']
del headers['protocol']
del headers['target_url']
for key, value in headers.items():
tmp_data += f"{key}: {value}\r\n"
tmp_data += "\r\n"
target_client.settimeout(2)
cut_send(target_client, (tmp_data.encode() + body))
recv_data = b''
tmp_data = b''
while True:
tmp_data = target_client.recv(1024)
if tmp_data:
recv_data += tmp_data
else:
break
if not recv_data:
pass
target_client.close()
return recv_data
def cut_send(client_socket, data, length=1024):
for i in range(int(len(data)/length) + 1):
tmp = data[i*length:length*(i + 1)]
client_socket.send(tmp)
if __name__ == "__main__":
ip = '127.0.0.1'
port = 1080
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((ip, port))
server_socket.listen(128)
try:
while True:
client_socket, addr = server_socket.accept()
print(addr)
try:
proxy(client_socket)
except Exception as e:
print(repr(e), e.__traceback__.tb_lineno, '行')
finally:
client_socket.close()
except KeyboardInterrupt:
print('手动停止')
except Exception as e:
print(e)
finally:
server_socket.close()