纯Python实现的chisel客户端,与jpillora/chisel服务器完全兼容。
- ✅ 本地端口转发 (
-L) - 将远程服务转发到本地 - ✅ 远程端口转发 (
-R) - 将本地服务暴露到远程服务器 - ✅ SOCKS5代理 (
--socks) - SOCKS5代理支持 - ✅ 完整的chisel v3协议兼容
- ✅ WebSocket over SSH传输
- ✅ 用户名/密码认证
# 克隆项目
git clone https://github.com/windviki/pychisel.git
cd pychisel
# 使用uv安装依赖
uv sync将远程SSH服务转发到本地端口2222:
uv run chisel.py --auth user:password -L 2222:remote-host:22 ws://chisel-server:8080然后连接:
ssh -p 2222 localhost将本地HTTP服务(端口3000)暴露到远程服务器的端口8080:
uv run chisel.py --auth user:password -R 8080:localhost:3000 ws://chisel-server:8080现在访问远程服务器的8080端口会被转发到你本地的3000端口。
启动本地SOCKS5代理:
uv run chisel.py --auth user:password --socks 1080 ws://chisel-server:8080--auth USER:PASS 用户名和密码认证
-L PORT:HOST:PORT 本地端口转发
-R PORT:HOST:PORT 远程端口转发
--socks PORT 启用SOCKS5代理
--fingerprint 服务器主机密钥指纹验证
PyChisel通过以下技术实现chisel协议:
- WebSocket传输层 - 使用
websocket-client库建立WebSocket连接,设置Sec-WebSocket-Protocol: chisel-v3头部 - SSH over WebSocket - 使用
paramiko库在WebSocket上运行SSH协议 - 自定义Transport - 继承
paramiko.Transport类,重写_check_banner()方法接受chisel版本号 - 流式读取 - 实现带缓冲区的WebSocket适配器,处理SSH协议的分包需求
- 通道类型支持 - 支持chisel自定义的
chisel通道类型 - 反向通道处理 - 实现ServerInterface接受服务器发起的通道请求
class WebSocketAdapter:
# 缓冲区分块读取,处理SSH协议的流式需求
def recv(self, bufsize):
# 从缓冲区返回数据,或读取新的WebSocket消息class ChiselTransport(paramiko.Transport):
def _check_banner(self):
# 接受 "SSH-chisel-v3-server" 版本格式
if version not in ("1.99", "2.0", "chisel"):
raise IncompatiblePeer(...)
def _parse_channel_open(self, m):
# 处理服务器发起的通道(用于reverse转发)
# 接受"chisel"类型通道并立即启动数据转发# SSH认证后发送JSON配置
config = {
"Version": "0.0.0-src",
"Remotes": [{
"LocalHost": "0.0.0.0",
"LocalPort": "8080",
"LocalProto": "tcp",
"RemoteHost": "localhost",
"RemotePort": "3000",
"RemoteProto": "tcp",
"Socks": False,
"Reverse": True, # 对于-R转发
"Stdio": False
}]
}
# 使用紧凑JSON(无空格),与Go的json.Marshal一致
transport.global_request("config", json.dumps(config, separators=(',', ':')).encode())PyChisel现已完全可用,所有核心功能正常工作!
已实现功能:
- WebSocket连接握手
- SSH协议版本协商
- 用户名/密码认证
- 配置协议实现与发送
- 本地端口转发 (
-L) - 完全工作 - 远程端口转发 (
-R) - 完全工作 ✨ 新增 - SOCKS5代理 (
--socks) - 已实现 - HTTP/SSH/MongoDB等协议全部测试通过
最新实现 (2026-02-06):
- ✅ 反向通道支持 - 实现ChiselServerInterface接受服务器通道请求
- ✅ 通道打开处理 - 重写_parse_channel_open处理服务器发起的通道
- ✅ Reverse转发数据流 - 在_parse_channel_open中直接启动数据泵
- ✅ 配置格式修正 -
-R参数格式:R:server_port:client_host:client_port
| 服务 | 协议 | 状态 | 说明 |
|---|---|---|---|
| HTTP (test-whoami) | Web | ✅ 成功 | HTTP响应 |
| SSH (test-ws) | SSH | ✅ 成功 | OpenSSH banner |
| MongoDB (test-mongo) | TCP | ✅ 成功 | TCP连接成功 |
测试命令:
# 服务端
./chisel/chisel server --reverse --port 8080 --auth test:password
# 客户端
python3 -m http.server 9101 & # 启动测试服务
uv run chisel.py --auth test:password -R 9100:localhost:9101 ws://localhost:8080
# 测试
curl http://localhost:9100/ # 访问服务器端口,转发到客户端9101测试结果:
2026-02-06 16:10:32,113 - INFO - Accepting channel: kind=chisel, chanid=0
2026-02-06 16:10:32,151 - INFO - Connected to local target localhost:9101
2026-02-06 16:10:32,202 - INFO - src->dst: received 77 bytes, forwarding...
2026-02-06 16:10:32,246 - INFO - dst->src: received 1339 bytes, forwarding...
2026-02-06 16:10:33,274 - INFO - dst->src: completed
✅ 成功处理3个HTTP请求,数据双向转发正常!
根本原因:SSH GLOBAL_REQUEST的payload应该是原始字节,不是长度前缀的string。
修复:手动构建消息,payload直接附加JSON字节。
根本原因:Paramiko默认拒绝服务器发起的通道请求。
修复:
- 实现
ChiselServerInterface接受"chisel"通道类型 - 重写
_parse_channel_open处理CHANNEL_OPEN消息 - 在通道接受后立即启动数据转发线程
根本原因:
- Remotes格式错误(字符串数组 vs 对象数组)
- JSON格式差异(有空格 vs 无空格)
修复:
- 使用对象数组格式
- 使用紧凑JSON:
json.dumps(config, separators=(',', ':'))
根本原因:WebSocket ping超时导致误判EOF。
修复:
- 禁用ping超时:
ping_timeout=None - 底层socket无限阻塞:
settimeout(None) - recv()超时抛出异常而非返回空数据
paramiko>=4.0.0- SSH协议实现websocket-client>=1.9.0- WebSocket客户端- Python 3.11+
| 特性 | chisel (Go) | PyChisel (Python) |
|---|---|---|
| WebSocket | gorilla/websocket | websocket-client |
| SSH | golang.org/x/crypto/ssh | paramiko |
| 协议版本 | chisel-v3 | chisel-v3 ✓ |
| 配置协议 | JSON over SSH | JSON over SSH ✓ |
| 通道类型 | chisel | chisel ✓ |
| 本地转发 | ✓ | ✓ |
| 远程转发 | ✓ | ✓ |
| SOCKS代理 | ✓ | ✓ |
MIT License - 详见 LICENSE 文件
欢迎提交Issue和Pull Request!
本项目灵感来源于 jpillora/chisel,实现了其Python版本的客户端。