我有一个在 Unix 套接字上运行的 ssh 服务,并且我有一个本地 TCP 服务器,我希望将它定向到 unix 套接字的通道。
基本上当我这样做时:
$ ssh root@localhost -p 2000
然后我的本地 TCP 服务器获取请求并将其通过管道传输到 Unix 套接字和 TCP 客户端,在本例中为 ssh,从 Unix 套接字获取回复。相关代码:
let running_tunnel debug (tcp_ic, tcp_oc) () =
Lwt_io.with_connection a_unix_addr begin fun (mux_ic, mux_oc) ->
let%lwt _ = some_call with_an_arg
and _ =
(* Some setup code *)
let rec forever () =
Lwt_io.read_line tcp_ic >>= fun opening_message ->
Lwt_io.write_from_string_exactly
mux_oc opening_message 0 (String.length opening_message) >>= fun () ->
Lwt_io.read_line mux_ic >>= fun reply ->
Lwt_io.printl reply >>= fun () ->
Lwt_io.write_line tcp_oc reply >>= fun () ->
forever ()
in
forever ()
in
Lwt.return_unit
end
而这种作品。当我在命令行上调用 ssh 时它会“卡住”,但我知道我正在获取一些数据,因为对方的 ssh 标头是正确的,SSH-2.0-OpenSSH_6.7
. 我也让我的一方打印出初始 ssh 握手的更多部分,即我看到这个打印:
??^?W\zJ?~??curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1ssh-rsa,ssh-dss>aes128-ctr,aes192-ctr,aes256-ctr,chacha20-poly1305@openssh.com>aes128-ctr,aes192-ctr,aes256-ctr,chacha20-poly1305@openssh.com?umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1?umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1none,zlib@openssh.comnone,zlib@openssh.co
等,这似乎是正确的。我认为挂起的原因是因为我正在使用Lwt_io.read_line
所以我尝试了这个:
let rec forever () =
Lwt_io.read tcp_ic >>= fun opening_message ->
Lwt_io.write_from_string_exactly
mux_oc opening_message 0 (String.length opening_message) >>= fun () ->
Lwt_io.read mux_ic >>= fun reply ->
Lwt_io.printl reply >>= fun () ->
Lwt_io.write tcp_oc reply >>= fun () ->
forever ()
in
forever ()
实际上效果更糟,它甚至没有打印出最初的握手。我还尝试了专用的{write,read}_into
... 功能,但成功有限。在 strace/dtruce 下运行,我看到的最终结果如下:
read(0x6, "SSH-2.0-OpenSSH_6.9\r\n\0", 0x1000) = 21 0
write(0x1, "SSH-2.0-OpenSSH_6.9\n\0", 0x14) = 20 0
read(0x7, "\0", 0x1000) = -1 Err#35
write(0x7, "SSH-2.0-OpenSSH_6.9\0", 0x13) = 19 0
select(0x9, 0x7FFF5484F880, 0x7FFF5484F800, 0x7FFF5484F780, 0x0) = 1 0
read(0x7, "SSH-2.0-OpenSSH_6.7\r\n\0", 0x1000) = 21 0
write(0x1, "SSH-2.0-OpenSSH_6.7\n\0", 0x14) = 20 0
read(0x6, "\0", 0x1000) = -1 Err#35
write(0x6, "SSH-2.0-OpenSSH_6.7\n\0", 0x14) = 20 0
select(0x9, 0x7FFF5484F880, 0x7FFF5484F800, 0x7FFF5484F780, 0x0) = 1 0
read(0x6, "\0", 0x1000) = 1968 0
read(0x6, "\0", 0x1000) = -1 Err#35
^C
其中 6.9 是我的本地机器的 ssh,而 6.7 是 Unix 套接字后面的远程机器。对我来说似乎很奇怪的一件事是它是如何\r
被删除的,这会将读/写计数更改为 1。我不确定这是否是关键的区别。
理想情况下,我希望从 Lwt 中进行某种抽象,即只要此可读通道(TCP 套接字)上有可用数据,就将其直接写入可写通道(Unix 套接字),反之亦然。