ONLamp.com    
 Published on ONLamp.com (http://www.onlamp.com/)
 See this if you're having trouble printing code examples


O'Reilly Book Excerpts: SSH, The Secure Shell: The Definitive Guide

Case Studies: Connecting Through a Gateway

Related Reading

SSH, The Secure Shell: The Definitive Guide
By Daniel J. Barrett, Richard E. Silverman

by Daniel J. Barrett and Richard E. Silverman

Connecting Through a Gateway Host

All along we've assumed that your outgoing connectivity is unlimited: that you can establish any outgoing TCP connection you desire. Even our discussions of firewalls have assumed that they restrict only incoming traffic. In more secure (or simply more regimented) environments, this might not be the case: in fact, you might not have direct IP connectivity at all to the outside world.

In the corporate world, companies commonly require all outgoing connections to pass through a proxy server or gateway host : a machine connected to both the company network and the outside. Although connected to both networks, a gateway host doesn't act as a router, and the networks remain separated. Rather, it allows limited, application-level access between the two networks.

In this case study, we discuss issues of SSH in this environment:

Making Transparent SSH Connections

Suppose your company has a gateway host, G, which is your only gateway to the Internet. You are logged into a client host C and want to reach a server host S outside the company network, as shown in Figure 11-14. We assume that all three machines have SSH installed.

Diagram.
Figure 11-14. Proxy gateway.

To make a connection from client C to server S now requires two steps:

  1. Connect from C to gateway G:

    # Execute on client C
    $ ssh G
  2. Connect from G to server S:

    # Execute on gateway G
    $ ssh S

This works, of course, but it requires an extra manual step on the gateway, a machine you don't care about. Using agent forwarding and public-key authentication, you can avoid entering a passphrase on gateway G, but even so, the additional hop ideally should be transparent.

Worse, you can't transparently execute remote commands on server S from client C. Instead of the usual:

# Execute on client C
$ ssh S /bin/ls

you must run a remote ssh on gateway G that in turn contacts server S:

# Execute on client C
$ ssh G "ssh S /bin/ls"

This isn't only annoying but also can complicate automation. Imagine rewriting all your SSH-based scripts to accommodate this environment.

Fortunately, SSH configuration is flexible enough to afford a neat solution, which we now present using SSH1 features and syntax. We use public-key authentication to take advantage of the options of the authorized_keys file, and ssh-agent with agent forwarding so that authentication passes on transparently to the second SSH connection (see Figure 11-15).

Diagram.
Figure 11-15. Chained SSH connections through a proxy gateway.

Suppose your account on gateway G is gilligan, and on server S it is skipper. First, set up your SSH client configuration file so the name S is a nickname for accessing your account on gateway G:

# ~/.ssh/config on client C
host S
  hostname G
  user gilligan

Next, on gateway G, associate a forced command with your chosen key to invoke an SSH connection to server S: See Forced Commands

 # ~/.ssh/authorized_keys on gateway G
command="ssh -l skipper S" ...key..

Note that if you want to use this setup for an interactive connection, you need to use the -t option to ssh, to force it to allocate a tty on G. It doesn't normally do that, because it doesn't have any way to know that the remote command -- in this case, another instance of ssh -- needs one.

Now, when you invoke the command ssh S on client C, it connects to gateway G, runs the forced command automatically, and establishes a second SSH session to server S. And thanks to agent forwarding, authentication from G to S happens automatically, assuming you've loaded the appropriate key. This can be the same key you used to access gilligan@G or a different one.

This trick not only provides a transparent connection from client C to server S, it also sidesteps the fact that the name S might not have any meaning on client C. Often in this kind of network situation, your internal network naming scheme is cut off from the outside world (e.g., split DNS with internal roots). After all, what's the point of allowing you to name hosts you can't reach? Thanks to the Host configuration keyword for SSH clients, you can create a nickname S that instructs SSH to reach that host transparently via G.

Daniel J. Barrett has been immersed in Internet technology since 1985. Currently, he is working as a software engineer. He is the author of O'Reilly's Linux Pocket Guide, and the coauthor of two more O'Reilly books: Linux Security Cookbook, and SSH, The Secure Shell: The Definitive Guide.

Richard E. Silverman first touched a computer as a college junior in 1986, when he logged into a DEC-20, typed "MM" to send some mail, and was promptly lost to the world.


View catalog information for SSH, The Secure Shell: The Definitive Guide

Return to ONLamp.com.

Copyright © 2009 O'Reilly Media, Inc.