如何在Python3中发送仅含单个CRLF的HTTP 101 SSH协议头?
问题分析与解决方案
你遇到的核心问题是BaseHTTPRequestHandler的默认行为会在HTTP响应头末尾自动添加换行,加上错误设置的Content-Type头影响,导致SSH客户端收到了多余的换行符,不符合RFC 4253对SSH版本交换格式的要求。
问题根源
- 代码缺少HTTP 101切换协议必须的
Upgrade和Connection头,客户端无法正确识别协议切换的意图; - 设置了
Content-type: text/plain头,可能触发服务器自动添加额外换行; end_headers()方法会自动在HTTP头末尾添加一个\r\n,而你发送的SSH字符串没有包含要求的单个CRLF,最终导致客户端收到的数据流出现多余换行。
正确实现代码
以下两种方式都能解决问题:
方式一:使用BaseHTTPRequestHandler的API并修正头信息
class MyServer(BaseHTTPRequestHandler): def do_GET(self): # 发送101切换协议状态码 self.send_response(101) # 必须添加的协议切换头 self.send_header("Upgrade", "ssh") self.send_header("Connection", "Upgrade") # 不需要设置Content-type,因为已切换到SSH协议 self.end_headers() # 直接发送带单个CRLF的SSH版本字符串 self.wfile.write(b"SSH-2.0-OpenSSH_9.5\r\n")
方式二:手动构建完整响应(更可控)
如果想完全绕过BaseHTTPRequestHandler的自动处理逻辑,可以直接通过连接发送字节数据:
class MyServer(BaseHTTPRequestHandler): def do_GET(self): # 构建符合HTTP 101规范的完整响应,包含SSH版本字符串 full_response = ( b"HTTP/1.1 101 Switching Protocols\r\n" b"Upgrade: ssh\r\n" b"Connection: Upgrade\r\n" b"\r\n" # HTTP头结束标记 b"SSH-2.0-OpenSSH_9.5\r\n" # 符合RFC的SSH版本交换内容 ) self.connection.sendall(full_response)
关键说明
- 必须添加
Upgrade: ssh和Connection: Upgrade头,这是HTTP 101协议切换的强制要求,否则客户端可能无法正确切换到SSH协议; - 直接在SSH版本字符串末尾添加
\r\n,确保符合RFC 4253的格式要求,避免依赖服务器自动添加换行; - 移除
Content-type头,因为切换到SSH协议后,HTTP的Content-Type不再适用。
内容的提问来源于stack exchange,提问作者Shakiba Moshiri
相关产品推荐
相关产品推荐

