Buckets:
| import subprocess | |
| import sys | |
| import os | |
| import importlib | |
| import site | |
| import socket | |
| import threading | |
| import time | |
| import argparse | |
| # 强制刷新 sys.path | |
| importlib.reload(site) | |
| import paramiko | |
| # 配置参数 | |
| USERNAME = os.environ.get("SSH_USERNAME", "") | |
| PASSWORD = os.environ.get("SSH_PASSWORD", "") | |
| HOST = os.environ.get("SSH_HOST", "") | |
| SSH_PORT = int(os.environ.get("SSH_PORT", "22")) | |
| REMOTE_PORT = int(os.environ.get("SSH_REMOTE", "65534")) | |
| LOCAL_HOST = "127.0.0.1" | |
| LOCAL_PORT = int(os.environ.get("SSH_LOCAL", "28000")) | |
| KEEP_ALIVE_INTERVAL = 60 | |
| def parse_args(): | |
| parser = argparse.ArgumentParser( | |
| description="SSH 反向端口转发" | |
| ) | |
| parser.add_argument( | |
| "--listen", | |
| action="store_true", | |
| help="允许转发机监听所有网卡地址 0.0.0.0" | |
| ) | |
| return parser.parse_args() | |
| class ReverseForwardServer(threading.Thread): | |
| def __init__( | |
| self, | |
| transport, | |
| remote_bind_host, | |
| remote_port, | |
| local_host, | |
| local_port | |
| ): | |
| super().__init__(daemon=True) | |
| self.transport = transport | |
| self.remote_bind_host = remote_bind_host | |
| self.remote_port = remote_port | |
| self.local_host = local_host | |
| self.local_port = local_port | |
| self.start() | |
| def run(self): | |
| try: | |
| allocated_port = self.transport.request_port_forward( | |
| self.remote_bind_host, | |
| self.remote_port | |
| ) | |
| print( | |
| f"请求远程服务器监听 " | |
| f"{self.remote_bind_host}:{allocated_port}," | |
| f"转发到本地 " | |
| f"{self.local_host}:{self.local_port}" | |
| ) | |
| except Exception as e: | |
| print(f"无法请求远程端口转发: {e}") | |
| return | |
| while self.transport.is_active(): | |
| try: | |
| chan = self.transport.accept(1) | |
| if chan is None: | |
| continue | |
| threading.Thread( | |
| target=self.handle_channel, | |
| args=(chan,), | |
| daemon=True, | |
| ).start() | |
| except Exception as e: | |
| print(f"处理通道时发生错误: {e}") | |
| break | |
| def handle_channel(self, chan): | |
| try: | |
| sock = socket.create_connection( | |
| ( | |
| self.local_host, | |
| self.local_port | |
| ) | |
| ) | |
| except Exception as e: | |
| print( | |
| f"无法连接到本地服务 " | |
| f"{self.local_host}:{self.local_port}: {e}" | |
| ) | |
| chan.close() | |
| return | |
| print( | |
| f"建立连接: " | |
| f"{chan.origin_addr} -> " | |
| f"{self.local_host}:{self.local_port}" | |
| ) | |
| def forward(src, dst): | |
| try: | |
| while True: | |
| data = src.recv(65536) | |
| if not data: | |
| break | |
| dst.sendall(data) | |
| except Exception: | |
| pass | |
| finally: | |
| try: | |
| src.close() | |
| except Exception: | |
| pass | |
| try: | |
| dst.close() | |
| except Exception: | |
| pass | |
| threading.Thread( | |
| target=forward, | |
| args=(chan, sock), | |
| daemon=True, | |
| ).start() | |
| threading.Thread( | |
| target=forward, | |
| args=(sock, chan), | |
| daemon=True, | |
| ).start() | |
| def main(): | |
| args = parse_args() | |
| # 默认只允许转发机本机访问 | |
| remote_bind_host = "127.0.0.1" | |
| # 带 --listen 时监听所有 IPv4 地址 | |
| if args.listen: | |
| remote_bind_host = "0.0.0.0" | |
| print( | |
| f"远程监听模式: " | |
| f"{remote_bind_host}:{REMOTE_PORT}" | |
| ) | |
| if args.listen: | |
| print( | |
| "已启用 --listen," | |
| "远程端口将尝试监听所有网卡。" | |
| ) | |
| print( | |
| "注意:SSH 服务端需要配置 " | |
| "GatewayPorts clientspecified" | |
| ) | |
| else: | |
| print( | |
| "未启用 --listen," | |
| "远程端口仅允许转发机本机访问。" | |
| ) | |
| while True: | |
| client = paramiko.SSHClient() | |
| client.set_missing_host_key_policy( | |
| paramiko.AutoAddPolicy() | |
| ) | |
| try: | |
| print( | |
| f"正在连接到 " | |
| f"{HOST}:{SSH_PORT}..." | |
| ) | |
| client.connect( | |
| hostname=HOST, | |
| port=SSH_PORT, | |
| username=USERNAME, | |
| password=PASSWORD, | |
| ) | |
| print("连接成功!") | |
| transport = client.get_transport() | |
| if ( | |
| transport is None | |
| or not transport.is_active() | |
| ): | |
| raise RuntimeError( | |
| "SSH Transport 不可用" | |
| ) | |
| transport.set_keepalive( | |
| KEEP_ALIVE_INTERVAL | |
| ) | |
| print( | |
| f"已设置保持连接,每 " | |
| f"{KEEP_ALIVE_INTERVAL} 秒" | |
| "发送一次心跳包" | |
| ) | |
| ReverseForwardServer( | |
| transport, | |
| remote_bind_host, | |
| REMOTE_PORT, | |
| LOCAL_HOST, | |
| LOCAL_PORT, | |
| ) | |
| print( | |
| f"远程监听 " | |
| f"{HOST}:{REMOTE_PORT} " | |
| f"({remote_bind_host})" | |
| ) | |
| print( | |
| f"转发目标 " | |
| f"{LOCAL_HOST}:{LOCAL_PORT}" | |
| ) | |
| while transport.is_active(): | |
| time.sleep(1) | |
| except KeyboardInterrupt: | |
| print("用户中断,关闭连接。") | |
| break | |
| except Exception as e: | |
| print(f"发生错误: {e}") | |
| print("5 秒后尝试重新连接...") | |
| time.sleep(5) | |
| finally: | |
| client.close() | |
| print("SSH 连接已关闭。") | |
| if __name__ == "__main__": | |
| main() |
Xet Storage Details
- Size:
- 6.25 kB
- Xet hash:
- b90d8a914075f592165e277622f7b006b5f11bb2ee023a5956f2577b94b94d9e
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.