paramiko 之代理

一、总览

代理主要通过 AF_INET socket 来与远程通信,通过 AF_UNIX socket 在本地与其它进程通信。


一个完整的代理通道的简单例子图

agent.py 下的几个类主要做不同功能的代理组件,下面是个人理解,最好结合源码看。


二、类详解

1、AgentProxyThread(threading.Thread) 基类

该类是一个多线程类,初始化时接收一个 agent 类存在 _agent 变量中(paramiko 使用 AgentServerProxy 包装了这个类的实例,并将 AgentServerProxy 作为 agent 给它使用),调用 start 时会开启一个新的线程,跑到 run 逻辑。
run 逻辑流程如下:

  1. 通过 get_connection 拿到目标连接;
  2. 通过 _agent.connect 打开 agent 端的连接,并存在 agent._conn 下;
  3. 通过 _communicate 打开通信循环;

该类充当交互双方的中间人,代理的主要中间处理人。


1)AgentLocalProxy(AgentProxyThread)

该类的 get_connection 将会通过传入的 agent 的 get_filename 拿到文件路径,然后使用 AF_UNIX 族的 socket 创建本地进程间通信连接并返回。
该类将处理 agent 与文件之间的信息交互:

AgentLocalProxy 的代理示意图

2)AgentRemoteProxy(AgentProxyThread)

该类除了传入一个 agent 外还额外传入一个 channel,get_connection 将传入的 channel 返回。
该类将处理 agent 与指定的 channel 之间的信息交互:

AgentRemoteProxy 的代理示意图

***修正:图中 Agent 没有对应的类的说法是错的,有一个对应的类 AgentClientProxy,这个后面讲。


2、AgentSSH(object) 基类

实现一个 _connect 方法,该方法接收一个 conn 连接,向该连接发送认证请求拿到公钥。
conn 可以是一个 paramiko 内的 channel 也可以是一个 socket 连接。

1)AgentServerProxy(AgentSSH)

需要传入一个 paramiko 的 transport 类。
这个类会创建一个文件,并将自己作为指定的 agent 通过 AgentLocalProxy 进行与文件之间的交互,流程如下:

  1. 在本地创建一个文件;
  2. 创建一个 AgentLocalProxy,将自己作为指定的 agent 并实现 get_filename 接口,调用 AgentLocalProxy 的 start 方法开启代理进程;
  3. connect 时通过 open_forward_agent_channel() 获得一个传入的 transport 下的 channel 作为 _conn,并对此连接跑一次 _connect;
  4. 通过 AgentLocalProxy 进行 agent 连接到本地文件的一个通信转发。


    AgentServerProxy 代理示例

2)Agent(AgentSSH)

单纯用于获取公钥的类,该类 __init__ 的流程如下:

  1. 跑 AgentSSH 的 __init__;
  2. 主动连接到 os.environ["SSH_AUTH_SOCK"] 下的文件路径;
  3. 调用 _connect 请求公钥,存到 self._keys 下。

通过 get_key 可以获取该 Agent 上存储的 keys。

Agent 获取公钥示例

3、AgentClientProxy(object)

该类的 __init__ 方法接收一个 channel 对象,存在 __chanR 变量下。
该类的执行流程如下:

  1. 创建一个 AgentRemoteProxy,并以此作为介质将自己作为 Agent 与 __chanR 进行通信;
  2. 创建一个到 os.environ["SSH_AUTH_SOCK"] 路径对应文件的 socket 连接(AF_UNIX),作进程间通信;


    AgentClientProxy 作代理的示例

4、AgentRequestHandler(object)

这个类用来包装一个 channel,使其向服务器发送端口转发的请求,流程如下:

  1. 客户端提供一个 channel,用 AgentRequestHandler(channel) 来包装这个 channel;
  2. AgentRequestHandler 控制 channel 调用 request_forward_agent,设定回调函数为 _forward_agent_handler;
  3. 服务端调用 ServerInterface 上的 check_channel_forward_agent_request 进行处理;
  4. 若成功则调用回调函数将指定的 channel 信道加到 handler 的列表下。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容