File: chapter-6.html

package info (click to toggle)
libnet-ssh-ruby 1.1.2-1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 3,472 kB
  • ctags: 2,465
  • sloc: ruby: 10,848; makefile: 17
file content (456 lines) | stat: -rw-r--r-- 24,654 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
<html>
  <head>
    <title>Net::SSH Manual :: Chapter 6: Port Forwarding</title>
    <link type="text/css" rel="stylesheet" href="stylesheets/manual.css" />
  </head>
  
  <body>
    <div id="banner">
      <table border='0' cellpadding='0' cellspacing='0' width='100%'>
        <tr><td valign='top' align='left'>
          <div class="title">
            <span class="product">Net::SSH&mdash;</span><br />
            <span class="tagline">Secure Shell for Ruby</span>
          </div>
        </td><td valign='middle' align='right'>
          <div class="info">
            Net::SSH Version: <strong>1.1.2</strong><br />
            Manual Last Updated: <strong>2007-06-18 18:12 UTC</strong>
          </div>
        </td></tr>
      </table>
    </div>

    <table border='0' width='100%' cellpadding='0' cellspacing='0'>
      <tr><td valign='top'>

        <div id="navigation">
          <h1>Net::SSH Manual</h1>

          <h2>Chapters</h2>
          <ol type="I">
          
            <li>
                <a href="chapter-1.html">
                Introduction
                </a>
                
              <ol type="1">
                
                  <li><a href="chapter-1.html#s1">What is Net::SSH?</a></li>
                
                  <li><a href="chapter-1.html#s2">What isn&#8217;t Net::SSH?</a></li>
                
                  <li><a href="chapter-1.html#s3">Getting Net::SSH</a></li>
                
                  <li><a href="chapter-1.html#s4">License Information</a></li>
                
                  <li><a href="chapter-1.html#s5">Support</a></li>
                
                  <li><a href="chapter-1.html#s6">About the Author</a></li>
                
              </ol>
            </li>
          
            <li>
                <a href="chapter-2.html">
                Starting a Session
                </a>
                
              <ol type="1">
                
                  <li><a href="chapter-2.html#s1">Using Net::SSH.start</a></li>
                
                  <li><a href="chapter-2.html#s2">Using a Public/Private Key</a></li>
                
                  <li><a href="chapter-2.html#s3">Options</a></li>
                
                  <li><a href="chapter-2.html#s4">Using Net::SSH::Session</a></li>
                
              </ol>
            </li>
          
            <li>
                <a href="chapter-3.html">
                Channels
                </a>
                
              <ol type="1">
                
                  <li><a href="chapter-3.html#s1">What are Channels?</a></li>
                
                  <li><a href="chapter-3.html#s2">Session.loop</a></li>
                
                  <li><a href="chapter-3.html#s3">Channel Types</a></li>
                
                  <li><a href="chapter-3.html#s4">Opening a Channel</a></li>
                
                  <li><a href="chapter-3.html#s5">Callbacks</a></li>
                
                  <li><a href="chapter-3.html#s6">Channel Operations</a></li>
                
              </ol>
            </li>
          
            <li>
                <a href="chapter-4.html">
                Executing Commands
                </a>
                
              <ol type="1">
                
                  <li><a href="chapter-4.html#s1">Using Channels</a></li>
                
                  <li><a href="chapter-4.html#s2">Using #process.open</a></li>
                
                  <li><a href="chapter-4.html#s3">Using #process.popen3</a></li>
                
              </ol>
            </li>
          
            <li>
                <a href="chapter-5.html">
                User Shells
                </a>
                
              <ol type="1">
                
                  <li><a href="chapter-5.html#s1">Introduction</a></li>
                
                  <li><a href="chapter-5.html#s2">Using Channels</a></li>
                
                  <li><a href="chapter-5.html#s3">Shell Service</a></li>
                
                  <li><a href="chapter-5.html#s4">SyncShell Service</a></li>
                
                  <li><a href="chapter-5.html#s5">Terminal Clients</a></li>
                
              </ol>
            </li>
          
            <li><strong>
                <a href="chapter-6.html">
                Port Forwarding
                </a>
                </strong> <big>&larr;</big>
              <ol type="1">
                
                  <li><a href="chapter-6.html#s1">Introduction</a></li>
                
                  <li><a href="chapter-6.html#s2">Local-to-Remote</a></li>
                
                  <li><a href="chapter-6.html#s3">Remote-to-Local</a></li>
                
                  <li><a href="chapter-6.html#s4">Direct Channels</a></li>
                
                  <li><a href="chapter-6.html#s5">Remote-to-Local Handlers</a></li>
                
              </ol>
            </li>
          
            <li>
                <a href="chapter-7.html">
                Using Proxies
                </a>
                
              <ol type="1">
                
                  <li><a href="chapter-7.html#s1">Introduction</a></li>
                
                  <li><a href="chapter-7.html#s2"><span class="caps">HTTP</span></a></li>
                
                  <li><a href="chapter-7.html#s3"><span class="caps">SOCKS</span></a></li>
                
              </ol>
            </li>
          
          </ol>

          <h2>Other Documentation</h2>

          <ul>
            <li><a href="http://net-ssh.rubyforge.org/api/index.html">Net::SSH API</a></li>
            <li><a href="http://rubyforge.org/tracker/?atid=1842&group_id=274&func=browse">Net::SSH FAQ</a></li>
          </ul>

          <h2>Tutorials</h2>
          <ol>
          
          </ol>

          <p align="center"><strong>More To Come...</strong></p>

          <div class="license">
            <a href="http://creativecommons.org/licenses/by-sa/2.0/"><img alt="Creative Commons License" border="0" src="http://creativecommons.org/images/public/somerights" /></a><br />
            This manual is licensed under a <a href="http://creativecommons.org/licenses/by-sa/2.0/">Creative Commons License</a>.
          </div>
        </div>

      </td><td valign='top' width="100%">

        <div id="content">

           <div class="top"><div class="prevnext">
  
    <a href="chapter-5.html">Previous (5. User Shells)</a> |
  
  <a href="index.html">Up</a>
  
    | <a href="chapter-7.html">Next (7. Using Proxies)</a>
  
</div></div>

<h1>6. Port Forwarding</h1>



     <h2>
       <a name="s1"></a>
       6.1. Introduction
     </h2>

   

   <div class="section">
     <p>Port forwarding is a feature of the <span class="caps">SSH</span> protocol that allows you to specify a port on one of the hosts, and have network connections on that port forwarded to a port on a different host, using the <span class="caps">SSH</span> connection as a proxy. There are basically two ways to use this forwarding:</p>


	<ol>
	<li>A port on the local host is forwarded via the remote host to another machine. Any connection to the specified port will cause all subsequent data to be sent over the connection to the remote host, where it will then be forwarded to the requested destination host.</li>
		<li>A port on the remote host is forwarded over the connection to the local host, and from there to (potentially) some other remote destination. Any connection to the specified port on the remote host is forwarded over the connection to the local host, which then makes a connection to the specified remote destination and sends the data there.</li>
	</ol>


	<p>All port forwarding in the Net::SSH library is managed by the <code>#forward</code> service. Just invoke methods on that service to set up any of various port forwarding configurations.</p>


	<div class='figure'>
<span class='caption'>Accessing the #forward service [ruby]</span>
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="constant">Net</span><span class="punct">::</span><span class="constant">SSH</span><span class="punct">.</span><span class="ident">start</span><span class="punct">(</span> <span class="punct">'</span><span class="string">host</span><span class="punct">'</span> <span class="punct">)</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">session</span><span class="punct">|</span>
  <span class="ident">forward</span> <span class="punct">=</span> <span class="ident">session</span><span class="punct">.</span><span class="ident">forward</span>
  <span class="punct">...</span>
  <span class="ident">session</span><span class="punct">.</span><span class="ident">loop</span>
<span class="keyword">end</span></pre></div></td></tr></table></div></div>


	<p>You can define any number of forwards before invoking the main loop, in which case all of those forwards will be handled transparently (and silently) in parallel, over the same connection. (Isn&#8217;t <span class="caps">SSH</span> lovely?)</p>


	<p>Naturally, you can also have remote processes, <span class="caps">SFTP</span> sessions, and more all working at the same time on the connection.</p>
   </div>



     <h2>
       <a name="s2"></a>
       6.2. Local-to-Remote
     </h2>

   

   <div class="section">
     <p>Forwarding a local connection to a remote destination is simply a matter of invoking the <code>#local</code> method of the <code>#forward</code> service. The simplest version of the method just takes three parameters: the local port to listen on, and the remote host and port to forward the connection to:</p>


	<div class='figure'>
<span class='caption'>Forwarding a local port [ruby]</span>
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="constant">Net</span><span class="punct">::</span><span class="constant">SSH</span><span class="punct">.</span><span class="ident">start</span><span class="punct">(</span> <span class="punct">'</span><span class="string">host</span><span class="punct">'</span> <span class="punct">)</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">session</span><span class="punct">|</span>
  <span class="ident">session</span><span class="punct">.</span><span class="ident">forward</span><span class="punct">.</span><span class="ident">local</span><span class="punct">(</span> <span class="number">1234</span><span class="punct">,</span> <span class="punct">'</span><span class="string">www.google.com</span><span class="punct">',</span> <span class="number">80</span> <span class="punct">)</span>
  <span class="ident">session</span><span class="punct">.</span><span class="ident">loop</span>
<span class="keyword">end</span></pre></div></td></tr></table></div></div>


	<p>In the above example, then, any connection received on port 1234 will be forwarded to port 80 on &#8220;www.google.com&#8221;. This means that if you were to point a browser at &#8220;http://localhost:1234&#8221;, it would pull up <a href="http://www.google.com">Google</a>.</p>


	<p>By default, only connections <em>from the local host</em> are accepted. This is because the default bind address is 127.0.0.1. You can specify any bind address you want (including 0.0.0.0 to allow connections from anywhere) by specifying that address as the first parameter to <code>#local</code>, with the local port number immediately following.</p>


	<div class='figure'>
<span class='caption'>Specifying the bind address when forwarding a local port [ruby]</span>
<div class='body'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">session</span><span class="punct">.</span><span class="ident">forward</span><span class="punct">.</span><span class="ident">local</span><span class="punct">(</span> <span class="punct">'</span><span class="string">0.0.0.0</span><span class="punct">',</span> <span class="number">1234</span><span class="punct">,</span> <span class="punct">'</span><span class="string">www.google.com</span><span class="punct">',</span> <span class="number">80</span> <span class="punct">)</span></pre></div></div></div>


	<p>In this configuration, anyone from anywhere can connect to your machine on port 1234 and be forwarded to Google.</p>
   </div>



     <h2>
       <a name="s3"></a>
       6.3. Remote-to-Local
     </h2>

   

   <div class="section">
     <p>Forwarding remote connections to the local host is also straightforward; simply call the <code>#remote_to</code> method of the <code>#forward</code> service. This takes three (or four) parameters: the local port and host to be forwarded to (in that order), and the remote port to listen on. The fourth parameter is optional, and is the bind address on the remote machine; this defaults to &#8220;127.0.0.1&#8221;.</p>


	<div class='figure'>
<span class='caption'>Forwarding a remote port [ruby]</span>
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="constant">Net</span><span class="punct">::</span><span class="constant">SSH</span><span class="punct">.</span><span class="ident">start</span><span class="punct">(</span> <span class="punct">'</span><span class="string">host</span><span class="punct">'</span> <span class="punct">)</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">session</span><span class="punct">|</span>
  <span class="ident">session</span><span class="punct">.</span><span class="ident">forward</span><span class="punct">.</span><span class="ident">remote_to</span><span class="punct">(</span> <span class="number">80</span><span class="punct">,</span> <span class="punct">'</span><span class="string">www.google.com</span><span class="punct">',</span> <span class="number">1234</span> <span class="punct">)</span>
  <span class="ident">session</span><span class="punct">.</span><span class="ident">loop</span>
<span class="keyword">end</span></pre></div></td></tr></table></div></div>


	<p>The above example causes any connection on port 1234 of the remote machine (<em>from</em> the remote machine) to be forwarded via the local host to port 80 at www.google.com. To make things a bit more open, you could specify a bind address of 0.0.0.0:</p>


	<div class='figure'>
<span class='caption'>Specifying the bind address when forwarding a remote port [ruby]</span>
<div class='body'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">session</span><span class="punct">.</span><span class="ident">forward</span><span class="punct">.</span><span class="ident">remote_to</span><span class="punct">(</span> <span class="number">80</span><span class="punct">,</span> <span class="punct">'</span><span class="string">www.google.com</span><span class="punct">',</span> <span class="number">1234</span><span class="punct">,</span> <span class="punct">'</span><span class="string">0.0.0.0</span><span class="punct">'</span> <span class="punct">)</span></pre></div></div></div>
   </div>



     <h2>
       <a name="s4"></a>
       6.4. Direct Channels
     </h2>

   

   <div class="section">
     <p>Sometimes it might be nice to programmatically simulate a network connection on a local port and have it forwarded to the remote host. You can do this by means of the <code>#direct_channel</code> method.</p>


	<p>The <code>#direct_channel</code> method looks similar to <code>#local</code>: the first three parameters are the local port to simulate the connection from, and the remote host and port that the connection should be forwarded to. The fourth parameter, however, is a <em>handler</em>, an object that is used as a callback for a variety of different events.</p>


	<p>The handler for the <code>#direct_channel</code> method may implement any of the following callbacks (all are optional, though you probably want to implement at least one or two of them):</p>


	<table class="list">
		<tr>
			<th>Callback </th>
			<th>Description </th>
		</tr>
		<tr>
			<td style="vertical-align:top;text-align:center;"><code>confirm</code> </td>
			<td> This is invoked when the channel has been opened and the remote host has confirmed it. This accepts four parameters: the channel itself, the local port, remote host, and remote port. (In this way, the same handler may be used for multiple forward requests.)</td>
		</tr>
		<tr>
			<td style="vertical-align:top;text-align:center;"><code>process</code> </td>
			<td> After the channel has been confirmed, this is invoked, to process the channel. This callback will be invoked in a new Thread, so that if your handler needs to listen to a socket and then send data received from it over the channel, it can do so without blocking the main loop. The callback accepts a single parameter, the channel handle itself.</td>
		</tr>
		<tr>
			<td style="vertical-align:top;text-align:center;"><code>on_close</code> </td>
			<td> This is called when the channel over which this forwarded connection is being processed has been closed. The callback accepts a single parameter, the channel itself.</td>
		</tr>
		<tr>
			<td style="vertical-align:top;text-align:center;"><code>on_eof</code> </td>
			<td> When the remote machine indicates it will send no more data, this callback will be invoked. It accepts a single parameter, the channel itself.</td>
		</tr>
		<tr>
			<td style="vertical-align:top;text-align:center;"><code>on_receive</code> </td>
			<td> This is invoked when data is received from the remote machine. It accepts two parameters: the channel handle, and the data that was received.</td>
		</tr>
	</table>




	<p>For example, the following example pretends to be a client that has connected to the local host on a forwarded port:</p>


	<div class='figure'>
<span class='caption'>Using a handler object to mimic a forwarded port [ruby]</span>
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="keyword">class </span><span class="class">Handler</span>
  <span class="keyword">def </span><span class="method">on_receive</span><span class="punct">(</span> <span class="ident">channel</span><span class="punct">,</span> <span class="ident">data</span> <span class="punct">)</span>
    <span class="ident">puts</span> <span class="punct">&quot;</span><span class="string">got data: <span class="expr">#{data.inspect}</span></span><span class="punct">&quot;</span>
    <span class="ident">channel</span><span class="punct">.</span><span class="ident">send_data</span> <span class="punct">&quot;</span><span class="string">subsequent request</span><span class="punct">&quot;</span>
  <span class="keyword">end</span>

  <span class="keyword">def </span><span class="method">process</span><span class="punct">(</span> <span class="ident">channel</span> <span class="punct">)</span>
    <span class="ident">channel</span><span class="punct">.</span><span class="ident">send_data</span> <span class="punct">&quot;</span><span class="string">initial request</span><span class="punct">&quot;</span>
  <span class="keyword">end</span>
<span class="keyword">end</span>

<span class="constant">Net</span><span class="punct">::</span><span class="constant">SSH</span><span class="punct">.</span><span class="ident">start</span><span class="punct">(</span> <span class="punct">'</span><span class="string">host</span><span class="punct">'</span> <span class="punct">)</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">session</span><span class="punct">|</span>
  <span class="ident">session</span><span class="punct">.</span><span class="ident">forward</span><span class="punct">.</span><span class="ident">direct_channel</span><span class="punct">(</span> <span class="number">1234</span><span class="punct">,</span> <span class="punct">'</span><span class="string">somewhere.else.net</span><span class="punct">',</span>
    <span class="number">4321</span><span class="punct">,</span> <span class="constant">Handler</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">)</span>

  <span class="ident">session</span><span class="punct">.</span><span class="ident">loop</span>
<span class="keyword">end</span></pre></div></td></tr></table></div></div>


	<p>The local port number for <code>#direct_channel</code> has no real purpose, other than to report to the <span class="caps">SSH</span> server that the &#8220;virtual&#8221; connection occurred on that port.</p>
   </div>



     <h2>
       <a name="s5"></a>
       6.5. Remote-to-Local Handlers
     </h2>

   

   <div class="section">
     <p>You can use handlers going in the other direction, too. If you want to programmatically process forwarded data from a remote host, you can use the <code>#remote</code> method.  This takes two parameters, with an optional third parameter. The two required parameters are the handler to use, and the remote port that should be listened to. The optional parameter is the remote bind address, which defaults to &#8216;127.0.0.1&#8217;.</p>


	<p>(Incidentally, if the port is 0, a new port will be allocated for you automatically by the server.)</p>


	<p>Whenever connections are received on the remote port, they will be forwarded to the handler, which may implement the following callbacks:</p>


	<table class="list">
		<tr>
			<th>Callback </th>
			<th>Description </th>
		</tr>
		<tr>
			<td style="vertical-align:top;text-align:center;"><code>error</code> </td>
			<td> This is invoked if the forward could not be initiated. It accepts a single parameter, which is the error message. </td>
		</tr>
		<tr>
			<td style="vertical-align:top;text-align:center;"><code>on_close</code> </td>
			<td> This is invoked when the channel that was assigned to process this forwarded connection has been closed. The callback takes one parameter: the channel itself. </td>
		</tr>
		<tr>
			<td style="vertical-align:top;text-align:center;"><code>on_eof</code> </td>
			<td> This is invoked when the remote end of the connection has promised not to send any more data. The local end of the channel may continue to send data, however. This callback takes on parameter: the channel itself.</td>
		</tr>
		<tr>
			<td style="vertical-align:top;text-align:center;"><code>on_open</code> </td>
			<td> This is invoked when a new connection is received over the forwarded channel. It accepts five parameters: the channel object, the connected address, the connected port, the originator address, and the originator port. </td>
		</tr>
		<tr>
			<td style="vertical-align:top;text-align:center;"><code>on_receive</code> </td>
			<td> This is invoked when data is received over the channel from the remote connection. It accepts two parameters: the channel object, and the data that was received. </td>
		</tr>
		<tr>
			<td style="vertical-align:top;text-align:center;"><code>setup</code> </td>
			<td> This is invoked immediately after the forward request has been acknowledged as successful. It accepts a single parameter, which is the port that was assigned to this forward. If the port parameter to <code>#remote</code> was not 0, then that same value will be passed to the callback. Otherwise, the newly allocated port number will be passed to the callback. </td>
		</tr>
	</table>




	<p>Note that the <code>on_receive</code> handler is required&#8212;all other callbacks may remain unimplemented by the handler.</p>
   </div>



<div class="bottom"><div class="prevnext">
  
    <a href="chapter-5.html">Previous (5. User Shells)</a> |
  
  <a href="index.html">Up</a>
  
    | <a href="chapter-7.html">Next (7. Using Proxies)</a>
  
</div></div>


        </div>

      </td></tr>
    </table>
  </body>
</html>