-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproxy.py
More file actions
132 lines (116 loc) · 4.27 KB
/
proxy.py
File metadata and controls
132 lines (116 loc) · 4.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# -*- coding: utf-8 -*-
"""
通用本地代理服务器
功能:将本地请求转发到指定的目标网站
支持自定义端口和目标网址
"""
from http.server import HTTPServer, BaseHTTPRequestHandler
import sys
import os
import threading
import time
import ctypes
# 全局变量
TARGET_URL = ''
PORT = 0
class ProxyHandler(BaseHTTPRequestHandler):
def do_GET(self):
# 动态导入 requests,减少启动依赖报错
import requests
# 1. 构建目标 URL
target = f"{TARGET_URL}{self.path}"
try:
# 2. 将服务器的响应返回给浏览器
self.send_response(resp.status_code)
for name, value in resp.headers.items():
if name.lower() not in ['content-encoding', 'transfer-encoding', 'content-length']:
self.send_header(name, value)
self.end_headers()
self.wfile.write(resp.content)
except Exception as e:
self.send_response(500)
self.send_header('Content-Type', 'text/html; charset=utf-8')
self.end_headers()
error_html = f"""
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>代理错误</title></head>
<body style="font-family:Microsoft YaHei;padding:50px;">
<h1 style="color:red;">代理错误</h1>
<p>请求地址:{target}</p>
<p>错误信息:{str(e)}</p>
</body></html>
""".encode('utf-8')
self.wfile.write(error_html)
def do_POST(self):
self.do_GET()
def do_HEAD(self):
self.do_GET()
def log_message(self, format, *args):
print(f"[{self.log_date_time_string()}] {format % args}")
sys.stdout.flush()
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
def main():
global TARGET_URL, PORT
print("=" * 60)
print("本地代理服务器 - 通用版")
print("=" * 60)
print()
# 1. 获取用户输入
while True:
input_url = input("请输入目标网址 (例如 https://github.com/FatFatYoung): ").strip()
if input_url.startswith(('http://', 'https://')):
TARGET_URL = input_url.rstrip('/') # 去掉末尾斜杠
break
else:
print("[错误] 网址必须以 http:// 或 https:// 开头")
while True:
input_port = input("请输入本地监听端口 (1-65535): ").strip()
try:
port_val = int(input_port)
if 1 <= port_val <= 65535:
PORT = port_val
break
else:
print("[错误] 端口必须在 1 到 65535 之间")
except ValueError:
print("[错误] 端口必须是纯数字")
print()
print("-" * 40)
print(f"目标网站:{TARGET_URL}")
print(f"监听地址:http://127.0.0.1:{PORT}")
# 2. 权限检查(仅针对低端口号)
if PORT < 1024:
if not is_admin():
print(f"[错误] 端口 {PORT} < 1024,需要管理员权限!")
print("请右键点击程序,选择【以管理员身份运行】。")
input("按回车键退出...")
sys.exit(1)
print("[OK] 管理员权限检查通过")
else:
print(f"[OK] 端口 {PORT} > 1024,无需管理员权限")
print("-" * 40)
print("按 Ctrl+C 停止服务...")
print("=" * 60)
# 3. 启动服务器
try:
server = HTTPServer(('127.0.0.1', PORT), ProxyHandler)
print(f"[OK] 服务启动成功,正在监听 {PORT} 端口...")
server.serve_forever()
except OSError as e:
if e.winerror == 10048:
print(f"[错误] 端口 {PORT} 已被占用!")
elif e.winerror == 10013:
print(f"[错误] 端口 {PORT} 访问被拒绝(可能需要管理员权限)!")
else:
print(f"[错误] {str(e)}")
input("按回车键退出...")
except KeyboardInterrupt:
print("\n正在停止服务...")
server.shutdown()
print("服务已停止")
if __name__ == '__main__':
main()