• ssh channel功能实现源码分析


    一、相关资料

    可以从下面地址下载工程源码l
    ssh使用的RFC协议在下面文档中描述

    使用channel的原因通常是两台主机A、B不能直接联通,但是它们都和M联通,并且M机器上运行了sshd服务器,也就是一方可以通过ssh和中转机联通。此时可以使用中转机M来联通A和B两台机器。

    二、命令行参数(-L/-R)的处理

    openssh-8.0ssh.c
    void
    add_local_forward(Options *options, const struct Forward *newfwd)
    {
    ……
    options->local_forwards = xreallocarray(options->local_forwards,
    options->num_local_forwards + 1,
    ……
    }

    void
    add_remote_forward(Options *options, const struct Forward *newfwd)
    {
    ……
    options->remote_forwards = xreallocarray(options->remote_forwards,
    options->num_remote_forwards + 1,
    sizeof(*options->remote_forwards));
    ……
    }

    三、Local端口有连接时处理

    1、ssh客户端的处理


    openssh-8.0channels.c
    static void
    channel_post_port_listener(struct ssh *ssh, Channel *c,
    fd_set *readset, fd_set *writeset)
    {
    ……
    } else {
    nextstate = SSH_CHANNEL_OPENING;
    rtype = "direct-tcpip";
    }

    addrlen = sizeof(addr);
    newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
    ……
    if (nextstate != SSH_CHANNEL_DYNAMIC)
    port_open_helper(ssh, nc, rtype);
    }
    ……
    }

    static void
    port_open_helper(struct ssh *ssh, Channel *c, char *rtype)
    {
    ……
    open_preamble(ssh, __func__, c, rtype);
    if (strcmp(rtype, "direct-tcpip") == 0) {
    /* target host, port */
    if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 ||
    (r = sshpkt_put_u32(ssh, c->host_port)) != 0) {
    fatal("%s: channel %i: reply %s", __func__,
    c->self, ssh_err(r));
    }
    }
    ……
    }
    static void
    open_preamble(struct ssh *ssh, const char *where, Channel *c, const char *type)
    {
    int r;

    if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 ||
    (r = sshpkt_put_cstring(ssh, type)) != 0 ||
    (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
    (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
    (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) {
    fatal("%s: channel %i: open: %s", where, c->self, ssh_err(r));
    }
    }

    2、sshd对于SSH2_MSG_CHANNEL_OPEN命令的处理

    static int
    server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
    {
    ……
    } else if (strcmp(ctype, "direct-tcpip") == 0) {
    c = server_request_direct_tcpip(ssh, &reason, &errmsg);
    }
    ……
    }

    static Channel *
    server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg)
    {
    ……
    c = channel_connect_to_port(ssh, target, target_port,
    "direct-tcpip", "direct-tcpip", reason, errmsg);
    ……
    }

    四、服务器端(Remote)有连接时处理

    1、客户端对-R命令行参数的处理

    int
    channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)
    {
    ……
    if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
    (r = sshpkt_put_cstring(ssh, "tcpip-forward")) != 0 ||
    (r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */
    (r = sshpkt_put_cstring(ssh,
    channel_rfwd_bind_host(fwd->listen_host))) != 0 ||
    (r = sshpkt_put_u32(ssh, fwd->listen_port)) != 0 ||
    (r = sshpkt_send(ssh)) != 0 ||
    (r = ssh_packet_write_wait(ssh)) != 0)
    fatal("%s: request tcpip-forward: %s",
    __func__, ssh_err(r));
    ……
    }

    3、sshd对该命令的处理

    static int
    server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
    {
    ……
    /* -R style forwarding */
    if (strcmp(rtype, "tcpip-forward") == 0) {
    ……
    ssh_packet_send_debug(ssh, "Server has disabled port forwarding.");
    } else {
    /* Start listening on the port */
    success = channel_setup_remote_fwd_listener(ssh, &fwd,
    &allocated_listen_port, &options.fwd_opts);
    }
    ……
    }
    ……
    }

    4、当有连接到sshd所在服务器指定端口时

    static void
    port_open_helper(struct ssh *ssh, Channel *c, char *rtype)
    {
    ……
    open_preamble(ssh, __func__, c, rtype);
    ……
    if ((r = sshpkt_send(ssh)) != 0)
    fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r));
    free(remote_ipaddr);
    free(local_ipaddr);
    }

    5、ssh客户端对于连接的处理

    /* XXXX move to generic input handler */
    static int
    client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
    {
    ……
    if (strcmp(ctype, "forwarded-tcpip") == 0) {
    c = client_request_forwarded_tcpip(ssh, ctype, rchan, rwindow,
    rmaxpack);
    ……
    }

  • 相关阅读:
    06-继承与多态(动手动脑与验证)
    课堂测试四(文件读写)
    字符串加密
    String方法阅读笔记
    03-类与对象(动手动脑)
    计算已经创建了多少个对象
    递归练习(课程作业)
    02-方法(动手动脑)
    猜数字游戏
    JAVA语言实现简单登录界面
  • 原文地址:https://www.cnblogs.com/tsecer/p/11364643.html
Copyright © 2020-2023  润新知