使用Python连接SOCKS5认证代理服务器,并在本地端口转发为HTTP代理的脚本。
为解决 Proxy SwitchyOmega 无法连接带密码认证的 SOCKS5 服务器的问题,我们可以使用 Python 编写一个脚本来连接 SOCKS5 服务器,并在本地转发为 HTTP 服务器。
- 配置 SOCKS5 代理服务器的连接信息。
- 实现一个 HTTP 代理服务器,将请求通过 SOCKS5 代理进行转发。
- 启动 HTTP 代理服务器,并在终端显示上传和下载数据量。
以下是具体步骤和代码实现。
1. 安装所需库
首先,请确保你已经安装了以下库:
pip install requests pysocks
如果报错,请尝试备用安装环境库
pip install altgraph==0.17.4 anyio==4.3.0 appdirs==1.4.4 argon2-cffi==23.1.0 argon2-cffi-bindings==21.2.0 arrow==1.3.0 astroid==3.1.0 asttokens==2.4.1 async-lru==2.0.4 async-timeout==4.0.3 attrs==23.2.0 Babel==2.14.0 beautifulsoup4==4.12.3 bleach==6.1.0 bleak==0.22.1 bleak-winrt==1.2.0 certifi==2024.2.2 cffi==1.16.0 charset-normalizer==3.3.2 click==8.1.7 colorama==0.4.6 comm==0.2.2 contourpy==1.2.0 cryptography==41.0.4 cycler==0.12.1 debugpy==1.8.1 decorator==5.1.1 defusedxml==0.7.1 dill==0.3.8 enum-compat==0.0.3 exceptiongroup==1.2.0 executing==2.0.1 fastjsonschema==2.19.1 fonttools==4.50.0 fqdn==1.5.1 fuzzywuzzy==0.18.0 h11==0.14.0 httpcore==1.0.4 httpx==0.27.0 idna==3.6 importlib_metadata==7.1.0 importlib_resources==6.3.1 ipykernel==6.29.3 ipython==8.18.1 ipywidgets==8.1.2 isoduration==20.11.0 isort==5.13.2 jedi==0.19.1 Jinja2==3.1.3 json5==0.9.24 jsonpointer==2.4 jsonschema==4.21.1 jsonschema-specifications==2023.12.1 jupyter==1.0.0 jupyter-console==6.6.3 jupyter-events==0.10.0 jupyter-lsp==2.2.4 jupyter_client==8.6.1 jupyter_core==5.7.2 jupyter_server==2.13.0 jupyter_server_terminals==0.5.3 jupyterlab==4.1.5 jupyterlab_pygments==0.3.0 jupyterlab_server==2.25.4 jupyterlab_widgets==3.0.10 keyboard==0.13.5 keyring==23.0.0 kiwisolver==1.4.5 Levenshtein==0.25.1 MarkupSafe==2.1.5 matplotlib==3.8.3 matplotlib-inline==0.1.6 mccabe==0.7.0 mistune==3.0.2 MouseInfo==0.1.3 nbclient==0.10.0 nbconvert==7.16.3 nbformat==5.10.3 nest-asyncio==1.6.0 notebook==7.1.2 notebook_shim==0.2.4 npyscreen==4.10.5 ntplib==0.4.0 numpy==1.26.4 opencv-python==4.9.0.80 overrides==7.7.0 packaging==24.0 pandas==1.1.5 pandocfilters==1.5.1 parso==0.8.3 pefile==2023.2.7 pillow==10.2.0 platformdirs==4.2.0 prometheus_client==0.20.0 prompt-toolkit==3.0.43 psutil==5.9.8 pure-eval==0.2.2 PyAutoGUI==0.9.54 PyBluez==0.30 pychrome==0.2.4 pycookiecheat==0.6.0 pycparser==2.21 pyee==11.1.0 pygatt==4.0.5 PyGetWindow==0.0.9 Pygments==2.17.2 pyinstaller==6.6.0 pyinstaller-hooks-contrib==2024.5 pylint==3.1.0 PyMsgBox==1.0.9 pynput==1.7.6 pyparsing==3.1.2 pyperclip==1.8.2 pypiwin32==223 pyppeteer==2.0.0 PyRect==0.2.0 PyScreeze==0.1.30 pyserial==3.5 PySocks==1.7.1 pytesseract==0.3.10 python-dateutil==2.9.0.post0 python-json-logger==2.0.7 python-Levenshtein==0.25.1 pytweening==1.2.0 pytz==2024.1 pywin32==306 pywin32-ctypes==0.2.2 pywinpty==2.0.13 PyYAML==6.0.1 pyzmq==25.1.2 qtconsole==5.5.1 QtPy==2.4.1 rapidfuzz==3.9.0 referencing==0.34.0 requests==2.31.0 rfc3339-validator==0.1.4 rfc3986-validator==0.1.1 rpds-py==0.18.0 Send2Trash==1.8.2 six==1.16.0 sniffio==1.3.1 soupsieve==2.5 stack-data==0.6.3 terminado==0.18.1 tinycss2==1.2.1 tomli==2.0.1 tomlkit==0.12.5 tornado==6.4 tqdm==4.66.4 traitlets==5.14.2 types-python-dateutil==2.9.0.20240316 typing_extensions==4.10.0 uri-template==1.3.0 urllib3==1.26.18 wcwidth==0.2.13 webcolors==1.13 webencodings==0.5.1 websocket-client==1.7.0 websockets==10.4 widgetsnbextension==4.0.10 zipp==3.18.1
2. 创建配置文件
我们需要创建一个配置文件来保存SOCKS5代理的配置信息。创建一个名为 socks5.ini
的文件,内容如下:
[SOCKS5]
HOST=your_socks5_proxy_host
PORT=your_socks5_proxy_port
USERNAME=your_username
PASSWORD=your_password
请根据实际情况填写你的SOCKS5代理的主机、端口、用户名和密码。
3. 编写代码
以下是实现的完整代码,将其保存为 socks5_http_proxy.py
:
import socketserver
import http.server
import socket
import socks
import select
import threading
import time
import configparser
from urllib.parse import urlparse
# 读取SOCKS5配置文件
config = configparser.ConfigParser()
config.read('socks5.ini')
SOCKS5_PROXY_HOST = config['SOCKS5']['HOST']
SOCKS5_PROXY_PORT = int(config['SOCKS5']['PORT'])
SOCKS5_USERNAME = config['SOCKS5']['USERNAME']
SOCKS5_PASSWORD = config['SOCKS5']['PASSWORD']
# 全局变量来跟踪数据传输量
total_upload = 0
total_download = 0
current_upload = 0
current_download = 0
lock = threading.Lock()
# 设置SOCKS5代理
socks.set_default_proxy(
socks.SOCKS5,
SOCKS5_PROXY_HOST,
SOCKS5_PROXY_PORT,
username=SOCKS5_USERNAME,
password=SOCKS5_PASSWORD
)
socket.socket = socks.socksocket
class ProxyHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
def log_message(self, format, *args):
return # 禁用默认的日志记录
def do_GET(self):
self.handle_http_request()
def do_POST(self):
self.handle_http_request()
def handle_http_request(self):
global total_upload, total_download, current_upload, current_download
url = self.path
parsed_url = urlparse(url)
hostname = parsed_url.hostname
port = parsed_url.port or (443 if parsed_url.scheme == 'https' else 80)
try:
conn = socks.socksocket()
conn.connect((hostname, port))
self.send_response(200)
self.end_headers()
if self.command == 'GET':
request_line = f"{self.command} {parsed_url.path}?{parsed_url.query} HTTP/1.1\r\n"
headers = "\r\n".join([f"{k}: {v}" for k, v in self.headers.items()])
conn.sendall((request_line + headers + "\r\n\r\n").encode('utf-8'))
elif self.command == 'POST':
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
request_line = f"{self.command} {parsed_url.path} HTTP/1.1\r\n"
headers = "\r\n".join([f"{k}: {v}" for k, v in self.headers.items()])
conn.sendall((request_line + headers + "\r\n\r\n").encode('utf-8') + post_data)
with lock:
total_upload += content_length
current_upload += content_length
response_data = b""
while True:
data = conn.recv(8192)
if not data:
break
response_data += data
self.wfile.write(data)
with lock:
total_download += len(data)
current_download += len(data)
except Exception as e:
self.send_error(500, str(e).encode('ascii', 'replace').decode())
finally:
conn.close()
def print_status():
global current_upload, current_download, total_upload, total_download
while True:
time.sleep(1)
with lock:
# 转换当前上传和下载速率为 KB/s
current_upload_kb = current_upload / 1024
current_download_kb = current_download / 1024
# 转换总上传和下载数据量为 MB 或 GB
total_upload_mb = total_upload / (1024 * 1024)
total_download_mb = total_download / (1024 * 1024)
if total_upload_mb >= 1024:
total_upload_str = f"{total_upload_mb / 1024:.2f} GB"
else:
total_upload_str = f"{total_upload_mb:.2f} MB"
if total_download_mb >= 1024:
total_download_str = f"{total_download_mb / 1024:.2f} GB"
else:
total_download_str = f"{total_download_mb:.2f} MB"
print(f"\r当前上传: {current_upload_kb:.2f} KB/s | 当前下载: {current_download_kb:.2f} KB/s | 总上传: {total_upload_str} | 总下载: {total_download_str}", end='')
current_upload = 0
current_download = 0
def start_proxy_server():
PORT = 18888
httpd = socketserver.ThreadingTCPServer(('', PORT), ProxyHTTPRequestHandler)
threading.Thread(target=httpd.serve_forever, daemon=True).start()
print(f'本地HTTP代理服务器运行在端口 {PORT}')
if __name__ == '__main__':
# 启动状态显示线程
status_thread = threading.Thread(target=print_status)
status_thread.daemon = True
status_thread.start()
# 启动代理服务器
start_proxy_server()
# 保持主线程运行
while True:
time.sleep(1)
4. 运行代理服务器
在终端运行代理服务器:
python socks5_http_proxy.py
你会看到类似以下的输出:
本地HTTP代理服务器运行在端口 18888
当前上传: 0.00 KB/s | 当前下载: 0.00 KB/s | 总上传: 0.00 MB | 总下载: 0.00 MB
5. 使用代理服务器
在浏览器或其他支持代理配置的应用中,将代理设置为 http://localhost:18888
。
结语
通过这篇教程,我们成功地创建了一个通过SOCKS5代理转发的HTTP代理服务器,并在本地端口监听。你可以根据需要进行扩展和修改,以满足特定的需求。如果你有任何问题或建议,欢迎在评论区留言。