如何用 Python 搭建一个代理服务器
想做一个中转代理服务器,用 python 写,在浏览器上设置代理 ip : port ,然后把所有的 http 和 https 的包都进行转发,同时做一些不可描述的事情,如何搞呢?
如何用 Python 搭建一个代理服务器
看看 SS 的源码不就知道了。。。
要搭一个简单的HTTP代理服务器,用Python的http.server模块和socketserver就能搞定。下面这个代码示例创建了一个基础的转发代理,能处理HTTP的GET和CONNECT请求(后者用于HTTPS隧道)。
import socket
import select
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import ThreadingMixIn
import urllib.parse
class ProxyHTTPRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
# 解析客户端请求的URL
url = urllib.parse.urlparse(self.path)
if not url.netloc:
# 如果路径是完整的URL(某些客户端直接发完整URL)
full_url = urllib.parse.urlparse('http://' + self.path)
host, port = full_url.netloc, 80
else:
host, port = url.netloc, 80
# 提取端口号
if ':' in host:
host, port = host.split(':', 1)
port = int(port)
# 连接到目标服务器
try:
with socket.create_connection((host, port), timeout=10) as target_sock:
# 构造HTTP请求行和头部
request_line = f"GET {url.path or '/'} HTTP/1.1\r\n"
headers = f"Host: {host}\r\n"
# 转发客户端的其他头部(除了Hop-by-hop头部)
for key, value in self.headers.items():
if key.lower() not in ['proxy-connection', 'connection', 'keep-alive']:
headers += f"{key}: {value}\r\n"
headers += "\r\n"
# 发送请求到目标服务器
target_sock.sendall((request_line + headers).encode())
# 接收响应并转发给客户端
self._relay_data(target_sock, self.connection)
except Exception as e:
self.send_error(502, f"Proxy Error: {str(e)}")
def do_CONNECT(self):
# HTTPS隧道处理
host_port = self.path.split(':', 1)
if len(host_port) == 2:
host, port = host_port[0], int(host_port[1])
else:
host, port = host_port[0], 443
try:
# 连接到目标服务器
target_sock = socket.create_connection((host, port), timeout=10)
# 告诉客户端连接已建立
self.send_response(200, 'Connection Established')
self.end_headers()
# 双向转发数据
sockets = [self.connection, target_sock]
while True:
readable, _, _ = select.select(sockets, [], [])
for sock in readable:
data = sock.recv(8192)
if not data:
return
# 将数据转发到另一个socket
other = target_sock if sock is self.connection else self.connection
other.sendall(data)
except Exception as e:
self.send_error(502, f"Tunnel Error: {str(e)}")
finally:
if 'target_sock' in locals():
target_sock.close()
def _relay_data(self, source, destination):
"""在两个socket之间转发数据"""
try:
while True:
data = source.recv(8192)
if not data:
break
destination.sendall(data)
except:
pass
def log_message(self, format, *args):
# 可选:自定义日志格式
print(f"[Proxy] {self.address_string()} - {format % args}")
class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
"""多线程HTTP服务器"""
daemon_threads = True
def run_proxy(host='localhost', port=8888):
server = ThreadingHTTPServer((host, port), ProxyHTTPRequestHandler)
print(f"代理服务器运行在 http://{host}:{port}")
try:
server.serve_forever()
except KeyboardInterrupt:
print("\n代理服务器已停止")
server.server_close()
if __name__ == '__main__':
run_proxy()
代码说明:
ProxyHTTPRequestHandler继承自BaseHTTPRequestHandler,重写了do_GET和do_CONNECT方法来处理两种主要请求。do_GET处理普通HTTP请求:解析URL,连接到目标服务器,转发请求和响应。do_CONNECT处理HTTPS隧道(CONNECT方法):建立到目标服务器的TCP连接,然后在客户端和目标服务器之间双向转发原始数据。ThreadingHTTPServer使用线程池处理并发连接。run_proxy()启动服务器,默认监听本地8888端口。
使用方法:
- 保存代码为
proxy.py - 运行
python proxy.py - 在浏览器或应用中配置代理为
localhost:8888
这个代理支持基本的HTTP和HTTPS流量转发。如果需要更完整的功能(如认证、缓存、访问控制等),可以考虑使用现成的库如 mitmproxy 或 squid。
用现成的库更省事。
容易,一搜就有教程。
当年有个人也是这样想的,然后就照着网上的 socks5 教程做了个 ss
接楼上~后来那个人被叫去喝茶了
故事继续发展。。 c 大去了美国
你确定是肉翻了吗?
楼主可以参考 https://github.com/inaz2/proxy2 。
不清楚是不是肉番,推特上看到有人说的
看你的描述 你应该是从零开始的
不过我推荐你最好不要开始
人生多美好啊 何必去浪费时间
嗯好
恩
-,-
发展成故事会了?
非常感谢
2333
肉翻是最好的方法
我们一开始用 Python 开发消息系统,后来改用 golang 。
其实现在很多 tunnel 都是用 golang 开发的,如果愿意学习,推荐看看:
1. https://github.com/getqujing/qtunnel (几百行代码,单向代理隧道,合适你的需求 , TCP 协议都支持)
2. https://github.com/ooclab/es (我们写的,从 Python 发展而来, 4000 行左右代码,双向对称设计)

