summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Nilsson <hans@erlang.org>2019-08-15 12:51:54 +0200
committerHans Nilsson <hans@erlang.org>2019-09-20 10:31:47 +0200
commit33b9ea4ca66f63adae4679ae6351c121a588d4dd (patch)
tree6aa8e775a6b3f8e74680e52622b0c71aa4065e82
parent0bb391db6e31d5c2672a865cfae4b7051e1cc88c (diff)
downloaderlang-33b9ea4ca66f63adae4679ae6351c121a588d4dd.tar.gz
ssh: direct-tcpip, server part
Added handling of SSH_MSG_CHANNEL_OPEN(diret-tcpip) and a new boolean option tcpip_tunnel_in with default false.
-rw-r--r--lib/ssh/doc/src/ssh.xml10
-rw-r--r--lib/ssh/src/ssh.hrl2
-rw-r--r--lib/ssh/src/ssh_connection.erl61
-rw-r--r--lib/ssh/src/ssh_options.erl6
4 files changed, 79 insertions, 0 deletions
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index 7f5be7b17d..2314474c36 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -694,6 +694,16 @@
</datatype>
<datatype>
+ <name name="tcpip_tunnel_in_daemon_option"/>
+ <desc>
+ <p>Enables (<c>true</c>) or disables (<c>false</c>) the possibility to tunnel a TCP/IP connection in to a
+ <seealso marker="ssh:ssh#daemon-2">server</seealso>.
+ Disabled per default.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
<name name="tcpip_tunnel_out_daemon_option"/>
<desc>
<p>Enables (<c>true</c>) or disables (<c>false</c>) the possibility to tunnel a TCP/IP connection out of a
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index 301e0d91e5..7afa6fcd16 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -303,6 +303,7 @@
| exec_daemon_option()
| ssh_cli_daemon_option()
| tcpip_tunnel_out_daemon_option()
+ | tcpip_tunnel_in_daemon_option()
| authentication_daemon_options()
| diffie_hellman_group_exchange_daemon_option()
| negotiation_timeout_daemon_option()
@@ -331,6 +332,7 @@
-type ssh_cli_daemon_option() :: {ssh_cli, mod_args() | no_cli }.
-type tcpip_tunnel_out_daemon_option() :: {tcpip_tunnel_out, boolean()} .
+-type tcpip_tunnel_in_daemon_option() :: {tcpip_tunnel_in, boolean()} .
-type send_ext_info_daemon_option() :: {send_ext_info, boolean()} .
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
index 0caf5cd819..318e0ca35d 100644
--- a/lib/ssh/src/ssh_connection.erl
+++ b/lib/ssh/src/ssh_connection.erl
@@ -583,6 +583,67 @@ handle_msg(#ssh_msg_channel_open{channel_type = "session" = Type,
{[{connection_reply, FailMsg}], Connection0}
end;
+handle_msg(#ssh_msg_channel_open{channel_type = "direct-tcpip",
+ sender_channel = RemoteId,
+ initial_window_size = WindowSize,
+ maximum_packet_size = PacketSize,
+ data = <<?DEC_BIN(HostToConnect,_L1), ?UINT32(PortToConnect),
+ ?DEC_BIN(_OriginatorIPaddress,_L2), ?UINT32(_OrignatorPort)
+ >>
+ },
+ #connection{channel_cache = Cache,
+ channel_id_seed = ChId,
+ options = Options,
+ sub_system_supervisor = SubSysSup
+ } = C,
+ server) ->
+
+ {ReplyMsg, NextChId} =
+ case ?GET_OPT(tcpip_tunnel_in, Options) of
+ %% May add more to the option, like allowed ip/port pairs to connect to
+ false ->
+ {channel_open_failure_msg(RemoteId,
+ ?SSH_OPEN_CONNECT_FAILED,
+ "Forwarding disabled", "en"),
+ ChId};
+
+ true ->
+ case gen_tcp:connect(binary_to_list(HostToConnect), PortToConnect,
+ [{active,false}, binary]) of
+ {ok,Sock} ->
+ {ok,Pid} = ssh_subsystem_sup:start_channel(server, SubSysSup, self(),
+ ssh_tcpip_forward_srv, ChId,
+ [Sock], undefined, Options),
+ ssh_client_channel:cache_update(Cache,
+ #channel{type = "direct-tcpip",
+ sys = "none",
+ local_id = ChId,
+ remote_id = RemoteId,
+ user = Pid,
+ recv_window_size = ?DEFAULT_WINDOW_SIZE,
+ recv_packet_size = ?DEFAULT_PACKET_SIZE,
+ send_window_size = WindowSize,
+ send_packet_size = PacketSize,
+ send_buf = queue:new()
+ }),
+ gen_tcp:controlling_process(Sock, Pid),
+ ssh_tcpip_forward_srv:use_socket(Pid, Sock),
+
+ {channel_open_confirmation_msg(RemoteId, ChId,
+ ?DEFAULT_WINDOW_SIZE,
+ ?DEFAULT_PACKET_SIZE),
+ ChId + 1};
+
+ {error,Error} ->
+ {channel_open_failure_msg(RemoteId,
+ ?SSH_OPEN_CONNECT_FAILED,
+ io_lib:format("Forwarded connection refused: ~p",[Error]),
+ "en"),
+ ChId}
+ end
+ end,
+ {[{connection_reply, ReplyMsg}], C#connection{channel_id_seed = NextChId}};
+
handle_msg(#ssh_msg_channel_open{channel_type = "session",
sender_channel = RemoteId},
Connection,
diff --git a/lib/ssh/src/ssh_options.erl b/lib/ssh/src/ssh_options.erl
index 7a2bb95298..505f248720 100644
--- a/lib/ssh/src/ssh_options.erl
+++ b/lib/ssh/src/ssh_options.erl
@@ -335,6 +335,12 @@ default(server) ->
class => user_option
},
+ tcpip_tunnel_in =>
+ #{default => false,
+ chk => fun erlang:is_boolean/1,
+ class => user_option
+ },
+
system_dir =>
#{default => "/etc/ssh",
chk => fun(V) -> check_string(V) andalso check_dir(V) end,