Using ssh Port Forwarding to Print at Remote Locations

Rory shows you how to connect the printing systems on different networks across the Internet in a secure manner.

In 1997, I was talking to a professional investor who thought that the value of office space in urban high rises was about to take a big dive. His rationale was that telecommuting was going to get big real soon. Well, here we are five years down the road, and I don't think telecommuting really has exploded. I've done it a couple of times. Some people here at SSC telecommute a couple of days a week. But in downtown Seattle, high rises are going up all over the place. On any given day there are 10-20 construction cranes on the skyline.

I wonder if my professional investor friend also was selling interests in pulp and paper companies. Tomorrow's office will be paperless, right?

Whether you telecommute or not, you probably use some form of electronic connectivity to the office when you are not there. Can you check your work e-mail at home? Do machines send e-mail to your cell phone? Can you access your company's intranet from the Web? Or, maybe you have never even been to the corporate headquarters, and you rove the globe packing a laptop that connects to your company's headquarters via a virtual private network (VPN).

If you don't have your VPN set up yet by your IT staff with its unlimited budget, you might be interested in ssh.

ssh--oh yeah, that's a secure Telnet program, right? Yes, it is, and it's much, much more. You're not still using Telnet, are you? Previous issues of Linux Journal have talked about the “much, much more” of ssh (see Resources). In this article I show a specific example of using ssh to do “much, much more”. I also demonstrate how to use ssh's port-forwarding feature to connect the printing systems on different networks across the Internet, at the same time securing the data while in transit.

Imagine that you work at Example Company. Example Company has a traditional office with a network of computers that contain all the data and programs that you and the company use to produce widgets. You are at home and use ssh to connect to Example's network over the hostile-worm-infested-jungle known as the Internet. ssh allows you to log in, read mail and start X11 programs. You also can use scp to pass files back and forth securely. If you have a fast connection to the Internet and through to your company's network, things can be very similar to working at your desk inside the traditional office—up until the time you want to burn a hard copy. What can you do? Well you can print to a file, scp the file to your home computer and submit the job to the local printer with lpr. This method works, but it takes three steps and does not work if you cannot print to file.

Hmmm...well you could turn all three steps into one big command-line juggernaut. On your home computer, typing

ssh -f rory@example.com cat secretdata | lpr

fires up an ssh session over to example.com and concatenates the file called secretdata in your remote home directory. The f option makes ssh go into the background after password authentication but before the cat command is run. Piping to lpr takes the standard out of ssh and directs it to standard in for lpr on the local computer. As long as your home lpr system is working and knows how to handle the file format of secretdata, out pops a hard copy on your home printer. Now, where did you put that ream of paper?

It would be nice just to be working away in your shell at Example Company and type lpr secretdata. That would save 30 typed characters and be easier to remember. What about printing from a mail reader or printing a report from a database application? An integrated print system would be even more useful for these activities.

One way to make the printing system seamless is to set up a relay system that gets the print job from the lpr system at example.com and passes it over to the lpr system at home.

Let's do this by using the port-forwarding features of ssh. What this does is allow you to connect an arbitrary port on your local system to a port on the remote system or vice versa. Then you can use programs that talk to a port to connect to the remote machine. Let's look at an example. Say you wanted to run your browser on your local machine but to look at your company's intranet, which is hosted on the company server at example.com but is not available to the public. Using ssh you forward the local port 8080 to example.com's port 80 with the command:

ssh -L 8080:example.com:80 example.com

After authentication you get a shell on example.com. Then, on your home computer open up your favorite browser, and enter the URL http://localhost:8080/.

Your browser sends its requests to the local port 8080, which gets passed over to port 80 at example.com, which processes the request and sends the answer back over the same channel to be displayed in your browser. Similarly, you could do a MySQL query or talk to an SMTP server by forwarding a local port to the appropriate port on a remote host.

Now that we have a handle on forwarding ports, let's talk about printing. First, we need a relay program that runs between the two different lpr systems.

Let's use a client/server system. The idea is that when we ssh to example.com, we fire up a local client program that connects to a server over at example.com using a forwarded port. If the server has a print job waiting, it sends it back to the client, which passes it off to the local lpr.

Examples of a simple server and client are shown in Listing 1 and Listing 2 [Listing 2 is available at ftp.linuxjournal.com/pub/lj/listings/issue94/5462.tgz].

Listing 1. rlserver

The server will be started by lpr on the remote system and will run only if there is a print job waiting to be sent from the remote machine over to the home machine. The remote lpr system host is set up to pass the print job off to the rlserver program using this entry in /etc/printcap:

# Remote Printer for Rory
rory
        :lp=|/usr/local/scripts/rlserver 8888
        :sd=/var/spool/lpd/rory
        :lf=/var/spool/lpd/rory/log
        :mx#0
        :sh

Printcap entries vary slightly on lpr systems; this one is for LPRng. The 8888 is an argument to rlserver telling it which port should be used for Rory. Other users can be set up with different ports—just make sure the ports aren't in use by some other program. Ports 1-1024 usually require special privileges.

What the client does is poll the server once every five seconds. It connects to the local port that has been forwarded. If there is a job waiting, then there is a server to connect to. Otherwise the connection is refused and the client tries again in five seconds. When a connection is made, the server sends the print job data over to the client, which copies it down into a temporary file. After the client receives all the data, the temporary file is sent to the local lpr. Now there are a few other things we need to do to set this up to run smoothly.

If you actually work in the corporate office part of the time, you want to use the office printer while you are in the office. But when you log in from home, you want the lpr-forwarding printer to be selected. This can be set up automatically by using an ssh feature and the shell initialization files. In $HOME/.ssh/enviroment, add the line:

REMOTE=yes

Once you ssh to a remote host, this variable will be set in your remote environment.

Next, add this stanza to your .bashrc on the remote host:

if [ "$REMOTE" = "yes" ]; then
    PRINTER=printername
fi

This will set your printer to printername when ssh starts a bash session. Make sure printername is the same as what is set up in the printcap file. If you don't use bash, do whatever your shell needs in its startup file.

Next, let's make sure the port forwarding takes place behind the scenes. That way we can simply type ssh example.com without remembering a lot of options and port numbers. Edit the $HOME/.ssh/config file, and add

Host example.com
    LocalForward 8888 example.com:8888

This will forward the local port 8888 to example.com's port 8888.

If you have a slow internet connection you may want to bump up the compression level from the default of six. Add these two lines before the host-specific sections of $HOME/.ssh/config:

Compression yes
CompressionLevel 9

Copy the program rlclient (Listing 2) to your home computer. Make sure the first line has the correct Python path in it. Execute rlclient in a shell. In a separate shell ssh to example.com. Your port 8888 should be forwarded, compression turned on, and your printer variable all should be set up. Check the printer variable with:

echo $PRINTER
It should say whatever you set up as your printername.

Now make sure your local (home) lpr system is up and running, and send a file to print on the remote system (example.com):

lpr mytestfile.txt

Check on the status of the print job with lpq. Also, watch the shell where rlclient is running. It will display output of what is going on.

I had some problems with new versions of ssh that use Protocol 2 not forwarding ports or complaining each time rlclient tried to connect. The error messages were of this sort:

channel_request_forwarding: cannot listen to port: 8888
channel_open_failure: 3: reason 2 Connection refused

In these cases, it was necessary to force the protocol level to 1 by using -1 on the command line or adding Protocol 1 to the $HOME/.ssh/config file under the other entries for example.com.

In addition to the lpr client and server, I found two very simple programs useful in debugging port forwarding. These are called time.client.py and time.server.py (Listings 3 and 4, respectively). Both programs take one argument, which is the port number you want them to use. The server waits for connections, sends out the time of day when it receives a connection, and the client simply prints out the time. They can be used over ssh or on the same machine.

Listing 3. time.client.py

Listing 4. time.server.py

Once everything is debugged, it is much easier to use a script to start the rlclient in the background when sshing to example.com. Then use the script (or an alias to the script) to ssh:

#!/bin/sh
# Start up the rlclient and ssh to example.com.
$HOME/rlpr/rlclient > $HOME/rlpr/log &
echo "$!" > $HOME/rlpr/pid
ssh example.com
kill -9 $(cat $HOME/rlpr/pid)

In this example, we have looked at how to relay print jobs from one location to another over a port secured by ssh. Uses for this port-forwarding feature are limited only by your imagination. Go forth and ssh.

Resources

email: rory@ssc.com

Rory Krause is a system administrator at Specialized Systems Consultants. He holds a degree in Mechanical Engineering from the University of Washington. Hobbies include archery and gardening.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Good article

Anonymous's picture

Nice :)

Re: Using ssh Port Forwarding to Print at Remote Locations

seldterre's picture

I am looking for info on using ssh port forwarding to print between to win2k boxes. I have the ssh server running, and can connect, but cant seem to setup the printing side of the arrangement. I have forwarded 9100:win2khost:9100 and get an error that it could not open the channel when I try to print. I have also used 9100:win2khost:515, however, this seems to send the print job into the ether never to be seen again. I have lpdsvc running on the win2khost box, with printers setup tcp/ip 127.0.0.1 port 9100; lpr 127.0.0.1 and various other configurations. Any help would be appreciated.

Re: Using ssh Port Forwarding to Print at Remote Locations

Anonymous's picture

What do you do if you don't have direct access from your home computer to the relevant company computer, requiring the

connection to be initiated from the company computer while

somehow opeing up the home computer? How to avoid

opening up the home compuiter and stay below the threshold

of running a full IPSEC network?

TIA!

Re: Using ssh Port Forwarding to Print at Remote Locations

Anonymous's picture

This article helped me make our office more secure. We had multiple database ports that were accessible through our firewall. Now I have all our people using ssh (putty) from home doing port forwarding to their local host through the ssh session to get access to the databases.

Now if I could only get Samba to do this as well so they could access their home directories and shares!!!

Thanks,
Shawn

You CAN port-forward CFS to Remote Samba servers

Anonymous's picture

Samba can do this, get the latest version and run Teraterm on your Windows PeeCees for the port forwarding... you lose the local network, tho, when you redirect your nbios and dgram ports to the remote server.

Thank you samba team! Thank you OpenSSH!

--Charlie

Re: Using ssh Port Forwarding to Print at Remote Locations

Anonymous's picture

You used Putty? I didn't know putty could do port forwarding. Could you explain how you setup your users?

Thanks,

Greg

Re: Using ssh Port Forwarding to Print at Remote Locations

Anonymous's picture

1. Must have putty .52 or later

2. Configure a saved session with ssh, and the machine

3. Under the configuration/ connection/ ssh/ tunnels

Oracle: forwarded 1521; destination 192.168.x.x:1521 (server behind the firewall)

MySQL: forwarded 3306; destination 192.168.x.x:3306 (server behind the firewall)

4. Resave configuration... unless you like typing it in over and over.

Now that is it... they can connect to the databases through their machine to the server using ssh (i.e. localhost:1521), but they do have to connect with that ssh session first.

Shawn

Re: Using ssh Port Forwarding to Print at Remote Locations

Anonymous's picture

How can you print a file on your local machine to a remote printer using ssh?

Is it possible to use ssh to allow someone else to print a file on his local machine using your account on the remote computer without giving them you password.

Re: Using ssh Port Forwarding to Print at Remote Locations

Anonymous's picture

It is also possible with port-forwarding, by just remotely executing lpr. Just give 'ssh username@somehost lpr' as the print-command.

Works fine under Gnome and also KDE IIRC.

It is more convient if another authentication is used instead of a password.

But at least in Gnome I remember one occasion being surprised when a dialog popped up asking for a password. I was using password authentication.

Printing to Win2K?

Anonymous's picture

Is there a sneaky way to print from a linux machine to a Win2k machine using this method? Or should I just use cups?

Re: Printing to Win2K?

rory's picture

I don't know. ssh is payware for windows. There is no lpr on windows. Back in the DOS days there was the "print" command available. Is there a print command in Win2K?

You can also use samba to print from linux to windows.

Somebody with a windows machine should try it.

Re: Printing to Win2K?

Anonymous's picture

Not true. You can use PuTTY, which handles ssh just fine.

Re: Printing to Win2K?

rory's picture

Can you set up PuTTY as an ssh daemon so that you can ssh

to the windows box? Or does PuTTY supply only the ssh client to ssh to Linux from Windows?

Re: Printing to Win2K?

Anonymous's picture

Putty is just a client. However, Cygwin has a daemon that can be setup on winblows ;)

--

Kevin White

Re: Printing to Win2K?

Anonymous's picture

openssh is also distributed for windows (sorry i dont remember where i got it from exactly, probably openssh.org) Buti it only works in win2k/XP and i have had problems with it in XP (mainly i think due to its provided shell, cmd should work fine)

Re: Printing to Win2K?

Anonymous's picture

The OpenSSH daemon is included in Cygwin, I think. see http://sources.redhat.com/cygwin/

Re: Printing to Win2K?

Anonymous's picture

You need to checkout the ssh.com client. It's a free download for personal use and it has all the command line tools. The latest versions of putty is completeley free and also has all the command line tools. I think you may have missed a simpler way of getting the ip of the connecting host when you ssh to a remote host, i.e. (echo $SSH_CLIENT |awk '{print $1}'). And you could have stopped at the port forwarding and lprng config setup because you can have inetd handle passing the redirect to lpr. All though you may want to at least have a tcpwapper statement and potentially a netfilter setup that limits access to the redirected port to avoid printing any old junk that gets sent to your inetd port.

As for all those Windows 2000 you can take the path of least resistance by adding the unix printing services windows component that is availble on all versions of 2000. You can add it under the Advanced menu of the Network and Dialup Connections folder.

Re: Printing to Win2K?

Anonymous's picture

In Win NT you can add lpr as: Start -> Settings -> Control Panel -> Network -> Services -> Add -> Microsoft TCP/IP printing

You add a lpd printer port as follows: Start -> Settings -> Printers -> Add Printer -> Add Port -> LPR Port -> New Port -> (lpd server and queue)

You add a printer using the above port: Start -> Settings -> Printers -> select printer port -> Next -> select manufacturer and type -> Next -> Next -> etc. etc.

Re: Using ssh Port Forwarding to Print at Remote Locations

Anonymous's picture

Just give 'ssh username@somehost lpr'

Yes, that is what I use. The system described in the article is needlessly complicated.

There is no need to do port forwarding, edit printcap, write a client program for the other end, modify shell initialization scripts, and so on when the data can simply be passed on STDIN and the printer name can be passed on the command line. Welcome to UNIX, land of pipes and command lines.

Did you consider dialup or dynamic IP's?

rory's picture

I like Keep It Simple Stupid solutions. But sometimes you can buy some convenience with complication. The setup in the article is really for dialup users. If you are lucky enough to have left the world of dynamic IP's in the past, then stick to simplicity. However, if you are using dialup your host name gets changed every time you connect and gets really long and cumbersome to type.

Compare the following:
ssh rory@somehost lpr
ssh rory@levrtwa1-ar1-182-035.evrtwa1.dsl.dialupsucks.net lpr

After I have dialed up in the morning, ssh'ed over to work and typed my print command into each application I am going to use for the day, I will be on the my second pot of coffee and about ready to go to lunch. Then I'll get disconnected and have to redial. Oh what fun :-).
The described system is only for where the simplest solution does not pay off. Set it up once and then let ssh figure out how to route your print data back to your location.
Welcome to Unix where pipes and command lines take care of the grunt work and I can get some work done.

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState