У меня есть служба ssh, работающая на сокете Unix, и у меня есть локальный сервер 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????\[email protected],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,[email protected]>aes128-ctr,aes192-ctr,aes256-ctr,[email protected][email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1none,[email protected],[email protected]
д., что кажется правильным. Я решил, что причина зависания в том, что я использую 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) и наоборот.