Class Net::SSH::Service::Forward
In: lib/net/ssh/service/forward.rb
lib/net/ssh/service/forward.rb
Parent: Object

This class implements various port forwarding services for use by Net::SSH clients. The Forward class should never need to be instantiated directly; instead, it should be accessed via the singleton instance returned by Connection::Session#forward:

  ssh.forward.local(1234, "www.capify.org", 80)

Methods

Included Modules

Loggable Loggable

Attributes

session  [R]  The underlying connection service instance that the port-forwarding services employ.
session  [R]  The underlying connection service instance that the port-forwarding services employ.

Public Class methods

Instantiates a new Forward service instance atop the given connection service session. This will register new channel open handlers to handle the specialized channels that the SSH port forwarding protocols employ.

[Source]

    # File lib/net/ssh/service/forward.rb, line 24
24:     def initialize(session)
25:       @session = session
26:       self.logger = session.logger
27:       @remote_forwarded_ports = {}
28:       @local_forwarded_ports = {}
29:       @agent_forwarded = false
30: 
31:       session.on_open_channel('forwarded-tcpip', &method(:forwarded_tcpip))
32:       session.on_open_channel('auth-agent', &method(:auth_agent_channel))
33:       session.on_open_channel('auth-agent@openssh.com', &method(:auth_agent_channel))
34:     end

Instantiates a new Forward service instance atop the given connection service session. This will register new channel open handlers to handle the specialized channels that the SSH port forwarding protocols employ.

[Source]

    # File lib/net/ssh/service/forward.rb, line 24
24:     def initialize(session)
25:       @session = session
26:       self.logger = session.logger
27:       @remote_forwarded_ports = {}
28:       @local_forwarded_ports = {}
29:       @agent_forwarded = false
30: 
31:       session.on_open_channel('forwarded-tcpip', &method(:forwarded_tcpip))
32:       session.on_open_channel('auth-agent', &method(:auth_agent_channel))
33:       session.on_open_channel('auth-agent@openssh.com', &method(:auth_agent_channel))
34:     end

Public Instance methods

Returns a list of all active locally forwarded ports. The returned value is an array of arrays, where each element is a two-element tuple consisting of the local port and bind address corresponding to the forwarding port.

[Source]

     # File lib/net/ssh/service/forward.rb, line 101
101:     def active_locals
102:       @local_forwarded_ports.keys
103:     end

Returns a list of all active locally forwarded ports. The returned value is an array of arrays, where each element is a two-element tuple consisting of the local port and bind address corresponding to the forwarding port.

[Source]

     # File lib/net/ssh/service/forward.rb, line 101
101:     def active_locals
102:       @local_forwarded_ports.keys
103:     end

Returns all active forwarded remote ports. The returned value is an array of two-element tuples, where the first element is the port on the remote host and the second is the bind address.

[Source]

     # File lib/net/ssh/service/forward.rb, line 159
159:     def active_remotes
160:       @remote_forwarded_ports.keys
161:     end

Returns all active forwarded remote ports. The returned value is an array of two-element tuples, where the first element is the port on the remote host and the second is the bind address.

[Source]

     # File lib/net/ssh/service/forward.rb, line 159
159:     def active_remotes
160:       @remote_forwarded_ports.keys
161:     end

Enables SSH agent forwarding on the given channel. The forwarded agent will remain active even after the channel closes—the channel is only used as the transport for enabling the forwarded connection. You should never need to call this directly—it is called automatically the first time a session channel is opened, when the connection was created with :forward_agent set to true:

   Net::SSH.start("remote.host", "me", :forwrd_agent => true) do |ssh|
     ssh.open_channel do |ch|
       # agent will be automatically forwarded by this point
     end
     ssh.loop
   end

[Source]

     # File lib/net/ssh/service/forward.rb, line 176
176:     def agent(channel)
177:       return if @agent_forwarded
178:       @agent_forwarded = true
179: 
180:       channel.send_channel_request("auth-agent-req@openssh.com") do |achannel, success|
181:         if success
182:           debug { "authentication agent forwarding is active" }
183:         else
184:           achannel.send_channel_request("auth-agent-req") do |a2channel, success2|
185:             if success2
186:               debug { "authentication agent forwarding is active" }
187:             else
188:               error { "could not establish forwarding of authentication agent" }
189:             end
190:           end
191:         end
192:       end
193:     end

Enables SSH agent forwarding on the given channel. The forwarded agent will remain active even after the channel closes—the channel is only used as the transport for enabling the forwarded connection. You should never need to call this directly—it is called automatically the first time a session channel is opened, when the connection was created with :forward_agent set to true:

   Net::SSH.start("remote.host", "me", :forwrd_agent => true) do |ssh|
     ssh.open_channel do |ch|
       # agent will be automatically forwarded by this point
     end
     ssh.loop
   end

[Source]

     # File lib/net/ssh/service/forward.rb, line 176
176:     def agent(channel)
177:       return if @agent_forwarded
178:       @agent_forwarded = true
179: 
180:       channel.send_channel_request("auth-agent-req@openssh.com") do |achannel, success|
181:         if success
182:           debug { "authentication agent forwarding is active" }
183:         else
184:           achannel.send_channel_request("auth-agent-req") do |a2channel, success2|
185:             if success2
186:               debug { "authentication agent forwarding is active" }
187:             else
188:               error { "could not establish forwarding of authentication agent" }
189:             end
190:           end
191:         end
192:       end
193:     end

Terminates an active local forwarded port. If no such forwarded port exists, this will raise an exception. Otherwise, the forwarded connection is terminated.

  ssh.forward.cancel_local(1234)
  ssh.forward.cancel_local(1234, "0.0.0.0")

[Source]

    # File lib/net/ssh/service/forward.rb, line 90
90:     def cancel_local(port, bind_address="127.0.0.1")
91:       socket = @local_forwarded_ports.delete([port, bind_address])
92:       socket.shutdown rescue nil
93:       socket.close rescue nil
94:       session.stop_listening_to(socket)
95:     end

Terminates an active local forwarded port. If no such forwarded port exists, this will raise an exception. Otherwise, the forwarded connection is terminated.

  ssh.forward.cancel_local(1234)
  ssh.forward.cancel_local(1234, "0.0.0.0")

[Source]

    # File lib/net/ssh/service/forward.rb, line 90
90:     def cancel_local(port, bind_address="127.0.0.1")
91:       socket = @local_forwarded_ports.delete([port, bind_address])
92:       socket.shutdown rescue nil
93:       socket.close rescue nil
94:       session.stop_listening_to(socket)
95:     end

Requests that a remote forwarded port be cancelled. The remote forwarded port on the remote host, bound to the given address on the remote host, will be terminated, but not immediately. This method returns immediately after queueing the request to be sent to the server. If for some reason the port cannot be cancelled, an exception will be raised (asynchronously).

If you want to know when the connection has been cancelled, it will no longer be present in the active_remotes list. If you want to block until the port is no longer active, you could do something like this:

  ssh.forward.cancel_remote(1234, "0.0.0.0")
  ssh.loop { ssh.forward.active_remotes.include?([1234, "0.0.0.0"]) }

[Source]

     # File lib/net/ssh/service/forward.rb, line 146
146:     def cancel_remote(port, host="127.0.0.1")
147:       session.send_global_request("cancel-tcpip-forward", :string, host, :long, port) do |success, response|
148:         if success
149:           @remote_forwarded_ports.delete([port, host])
150:         else
151:           raise Net::SSH::Exception, "could not cancel remote forward request on #{host}:#{port}"
152:         end
153:       end
154:     end

Requests that a remote forwarded port be cancelled. The remote forwarded port on the remote host, bound to the given address on the remote host, will be terminated, but not immediately. This method returns immediately after queueing the request to be sent to the server. If for some reason the port cannot be cancelled, an exception will be raised (asynchronously).

If you want to know when the connection has been cancelled, it will no longer be present in the active_remotes list. If you want to block until the port is no longer active, you could do something like this:

  ssh.forward.cancel_remote(1234, "0.0.0.0")
  ssh.loop { ssh.forward.active_remotes.include?([1234, "0.0.0.0"]) }

[Source]

     # File lib/net/ssh/service/forward.rb, line 146
146:     def cancel_remote(port, host="127.0.0.1")
147:       session.send_global_request("cancel-tcpip-forward", :string, host, :long, port) do |success, response|
148:         if success
149:           @remote_forwarded_ports.delete([port, host])
150:         else
151:           raise Net::SSH::Exception, "could not cancel remote forward request on #{host}:#{port}"
152:         end
153:       end
154:     end

Starts listening for connections on the local host, and forwards them to the specified remote host/port via the SSH connection. This method accepts either three or four arguments. When four arguments are given, they are:

  • the local address to bind to
  • the local port to listen on
  • the remote host to forward connections to
  • the port on the remote host to connect to

If three arguments are given, it is as if the local bind address is "127.0.0.1", and the rest are applied as above.

  ssh.forward.local(1234, "www.capify.org", 80)
  ssh.forward.local("0.0.0.0", 1234, "www.capify.org", 80)

[Source]

    # File lib/net/ssh/service/forward.rb, line 51
51:     def local(*args)
52:       if args.length < 3 || args.length > 4
53:         raise ArgumentError, "expected 3 or 4 parameters, got #{args.length}"
54:       end
55: 
56:       bind_address = "127.0.0.1"
57:       bind_address = args.shift if args.first.is_a?(String) && args.first =~ /\D/
58: 
59:       local_port = args.shift.to_i
60:       remote_host = args.shift
61:       remote_port = args.shift.to_i
62: 
63:       socket = TCPServer.new(bind_address, local_port)
64: 
65:       @local_forwarded_ports[[local_port, bind_address]] = socket
66: 
67:       session.listen_to(socket) do |server|
68:         client = server.accept
69:         debug { "received connection on #{bind_address}:#{local_port}" }
70: 
71:         channel = session.open_channel("direct-tcpip", :string, remote_host, :long, remote_port, :string, bind_address, :long, local_port) do |achannel|
72:           achannel.info { "direct channel established" }
73:         end
74: 
75:         prepare_client(client, channel, :local)
76:   
77:         channel.on_open_failed do |ch, code, description|
78:           channel.error { "could not establish direct channel: #{description} (#{code})" }
79:           channel[:socket].close
80:         end
81:       end
82:     end

Starts listening for connections on the local host, and forwards them to the specified remote host/port via the SSH connection. This method accepts either three or four arguments. When four arguments are given, they are:

  • the local address to bind to
  • the local port to listen on
  • the remote host to forward connections to
  • the port on the remote host to connect to

If three arguments are given, it is as if the local bind address is "127.0.0.1", and the rest are applied as above.

  ssh.forward.local(1234, "www.capify.org", 80)
  ssh.forward.local("0.0.0.0", 1234, "www.capify.org", 80)

[Source]

    # File lib/net/ssh/service/forward.rb, line 51
51:     def local(*args)
52:       if args.length < 3 || args.length > 4
53:         raise ArgumentError, "expected 3 or 4 parameters, got #{args.length}"
54:       end
55: 
56:       bind_address = "127.0.0.1"
57:       bind_address = args.shift if args.first.is_a?(String) && args.first =~ /\D/
58: 
59:       local_port = args.shift.to_i
60:       remote_host = args.shift
61:       remote_port = args.shift.to_i
62: 
63:       socket = TCPServer.new(bind_address, local_port)
64: 
65:       @local_forwarded_ports[[local_port, bind_address]] = socket
66: 
67:       session.listen_to(socket) do |server|
68:         client = server.accept
69:         debug { "received connection on #{bind_address}:#{local_port}" }
70: 
71:         channel = session.open_channel("direct-tcpip", :string, remote_host, :long, remote_port, :string, bind_address, :long, local_port) do |achannel|
72:           achannel.info { "direct channel established" }
73:         end
74: 
75:         prepare_client(client, channel, :local)
76:   
77:         channel.on_open_failed do |ch, code, description|
78:           channel.error { "could not establish direct channel: #{description} (#{code})" }
79:           channel[:socket].close
80:         end
81:       end
82:     end

Requests that all connections on the given remote-port be forwarded via the local host to the given port/host. The last argument describes the bind address on the remote host, and defaults to 127.0.0.1.

This method will return immediately, but the port will not actually be forwarded immediately. If the remote server is not able to begin the listener for this request, an exception will be raised asynchronously.

If you want to know when the connection is active, it will show up in the active_remotes list. If you want to block until the port is active, you could do something like this:

  ssh.forward.remote(80, "www.google.com", 1234, "0.0.0.0")
  ssh.loop { !ssh.forward.active_remotes.include?([1234, "0.0.0.0"]) }

[Source]

     # File lib/net/ssh/service/forward.rb, line 119
119:     def remote(port, host, remote_port, remote_host="127.0.0.1")
120:       session.send_global_request("tcpip-forward", :string, remote_host, :long, remote_port) do |success, response|
121:         if success
122:           debug { "remote forward from remote #{remote_host}:#{remote_port} to #{host}:#{port} established" }
123:           @remote_forwarded_ports[[remote_port, remote_host]] = Remote.new(host, port)
124:         else
125:           error { "remote forwarding request failed" }
126:           raise Net::SSH::Exception, "remote forwarding request failed"
127:         end
128:       end
129:     end

Requests that all connections on the given remote-port be forwarded via the local host to the given port/host. The last argument describes the bind address on the remote host, and defaults to 127.0.0.1.

This method will return immediately, but the port will not actually be forwarded immediately. If the remote server is not able to begin the listener for this request, an exception will be raised asynchronously.

If you want to know when the connection is active, it will show up in the active_remotes list. If you want to block until the port is active, you could do something like this:

  ssh.forward.remote(80, "www.google.com", 1234, "0.0.0.0")
  ssh.loop { !ssh.forward.active_remotes.include?([1234, "0.0.0.0"]) }

[Source]

     # File lib/net/ssh/service/forward.rb, line 119
119:     def remote(port, host, remote_port, remote_host="127.0.0.1")
120:       session.send_global_request("tcpip-forward", :string, remote_host, :long, remote_port) do |success, response|
121:         if success
122:           debug { "remote forward from remote #{remote_host}:#{remote_port} to #{host}:#{port} established" }
123:           @remote_forwarded_ports[[remote_port, remote_host]] = Remote.new(host, port)
124:         else
125:           error { "remote forwarding request failed" }
126:           raise Net::SSH::Exception, "remote forwarding request failed"
127:         end
128:       end
129:     end
remote_to(port, host, remote_port, remote_host="127.0.0.1")

Alias for remote

remote_to(port, host, remote_port, remote_host="127.0.0.1")

Alias for remote

[Validate]