使用 SSH 端口转发在远程位置打印

作者:Rory Krause

1997 年,我与一位专业投资者交谈,他认为城市高层办公空间的价值即将大幅下跌。他的理由是远程办公即将兴起。好吧,现在五年过去了,我认为远程办公并没有真正爆发。我做过几次。我们 SSC 的一些人每周远程办公几天。但在西雅图市中心,高层建筑随处可见。在任何一天,天际线上都有 10-20 个建筑起重机。

我想知道我的专业投资者朋友是否也在出售纸浆和造纸公司的权益。明天的办公室将是无纸化的,对吗?

无论您是否远程办公,当您不在办公室时,您可能都会使用某种形式的电子连接到办公室。您可以在家查看您的工作电子邮件吗?机器会向您的手机发送电子邮件吗?您可以从网络访问您公司的内网吗?或者,也许您从未去过公司总部,您漫游全球,携带一台笔记本电脑,通过虚拟专用网络 (VPN) 连接到您公司的总部。

如果您的 IT 部门还没有用他们无限的预算设置好 VPN,您可能会对 ssh 感兴趣。

ssh——哦,是的,那是一个安全的 Telnet 程序,对吗?是的,它是,而且它远不止于此。您还在使用 Telnet 吗?Linux Journal 之前的期刊已经讨论过 ssh 的“远不止于此”(参见资源)。在本文中,我展示了一个使用 ssh 进行“远不止于此”的具体示例。我还演示了如何使用 ssh 的端口转发功能来连接跨 Internet 的不同网络上的打印系统,同时保护传输中的数据安全。

假设您在 Example Company 工作。Example Company 有一个传统的办公室,办公室里有一个计算机网络,其中包含您和公司用于生产小部件的所有数据和程序。您在家中使用 ssh 通过被称为 Internet 的充满敌意的蠕虫感染的丛林连接到 Example 的网络。ssh 允许您登录、阅读邮件和启动 X11 程序。您还可以使用 scp 安全地来回传递文件。如果您与 Internet 以及与您公司网络的连接速度很快,那么事情可能非常类似于在传统办公室内的办公桌上工作——直到您想要打印一份硬拷贝。您能做什么?好吧,您可以打印到文件,将文件 scp 到您的家用计算机,然后使用 lpr 将作业提交到本地打印机。这种方法有效,但需要三个步骤,并且如果您无法打印到文件,则无法工作。

嗯...好吧,您可以将所有三个步骤变成一个大的命令行重击。在您的家用计算机上,键入

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

启动一个到 example.com 的 ssh 会话,并在您的远程主目录中连接名为 secretdata 的文件。f 选项使 ssh 在密码验证后但在 cat 命令运行之前进入后台。管道传输到 lpr 将 ssh 的标准输出定向到本地计算机上 lpr 的标准输入。只要您的家用 lpr 系统工作正常并且知道如何处理 secretdata 的文件格式,硬拷贝就会在您的家用打印机上弹出。现在,您把那叠纸放在哪里了?

如果只是在 Example Company 的 shell 中工作并键入 lpr secretdata 就好了。这将节省 30 个键入字符,并且更容易记住。从邮件阅读器打印或从数据库应用程序打印报告怎么样?集成打印系统对于这些活动将更加有用。

使打印系统无缝的一种方法是设置一个中继系统,该系统从 example.com 的 lpr 系统获取打印作业,并将其传递到家中的 lpr 系统。

让我们通过使用 ssh 的端口转发功能来做到这一点。这允许您将本地系统上的任意端口连接到远程系统上的端口,反之亦然。然后,您可以使用与端口通信的程序连接到远程计算机。让我们看一个例子。假设您想在本地计算机上运行浏览器,但要查看您公司的内网,该内网托管在 example.com 的公司服务器上,但公众无法访问。使用 ssh,您可以使用以下命令将本地端口 8080 转发到 example.com 的端口 80

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

身份验证后,您将在 example.com 上获得一个 shell。然后,在家用计算机上打开您最喜欢的浏览器,并输入 URL https://:8080/。

您的浏览器将其请求发送到本地端口 8080,该端口被传递到 example.com 的端口 80,后者处理请求并将答案通过同一通道发送回来,以在您的浏览器中显示。类似地,您可以通过将本地端口转发到远程主机上的相应端口来执行 MySQL 查询或与 SMTP 服务器通信。

现在我们掌握了转发端口的方法,让我们来谈谈打印。首先,我们需要一个中继程序,该程序在两个不同的 lpr 系统之间运行。

让我们使用客户端/服务器系统。想法是,当我们 ssh 到 example.com 时,我们启动一个本地客户端程序,该程序使用转发的端口连接到 example.com 上的服务器。如果服务器有等待的打印作业,它会将其发回客户端,客户端将其传递给本地 lpr。

清单 1 和清单 2 中显示了简单服务器和客户端的示例[清单 2 可在 ftp.linuxjournal.com/pub/lj/listings/issue94/5462.tgz 获得]。

清单 1. rlserver

服务器将由远程系统上的 lpr 启动,并且仅当有等待从远程计算机发送到家用计算机的打印作业时才会运行。远程 lpr 系统主机设置为使用 /etc/printcap 中的此条目将打印作业传递给 rlserver 程序

# 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 条目在 lpr 系统上略有不同;这个是用于 LPRng 的。8888 是 rlserver 的一个参数,告诉它应该为 Rory 使用哪个端口。可以使用不同的端口设置其他用户——只需确保端口未被其他程序使用即可。端口 1-1024 通常需要特殊权限。

客户端所做的是每五秒轮询一次服务器。它连接到已转发的本地端口。如果有等待的作业,则有一个服务器要连接。否则,连接将被拒绝,客户端将在五秒钟后重试。建立连接后,服务器会将打印作业数据发送到客户端,客户端将其复制到临时文件中。客户端收到所有数据后,临时文件将发送到本地 lpr。现在,我们需要做一些其他事情来设置它以使其顺利运行。

如果您实际上有一部分时间在公司办公室工作,则希望在办公室时使用办公室打印机。但是,当您从家登录时,您希望选择 lpr 转发打印机。这可以通过使用 ssh 功能和 shell 初始化文件自动设置。在 $HOME/.ssh/enviroment 中,添加行

REMOTE=yes

一旦您 ssh 到远程主机,此变量将在您的远程环境中设置。

接下来,在远程主机上的 .bashrc 中添加此节

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

当 ssh 启动 bash 会话时,这将您的打印机设置为 printername。确保 printername 与 printcap 文件中设置的相同。如果您不使用 bash,请在 shell 的启动文件中执行 shell 需要的任何操作。

接下来,让我们确保端口转发在后台进行。这样,我们就可以简单地键入 ssh example.com,而无需记住大量选项和端口号。编辑 $HOME/.ssh/config 文件,并添加

Host example.com
    LocalForward 8888 example.com:8888

这将把本地端口 8888 转发到 example.com 的端口 8888。

如果您的互联网连接速度较慢,您可能需要将压缩级别从默认值 6 提高。在 $HOME/.ssh/config 的特定于主机的部分之前添加这两行

Compression yes
CompressionLevel 9

将程序 rlclient(清单 2)复制到您的家用计算机。确保第一行具有正确的 Python 路径。在 shell 中执行 rlclient。在单独的 shell 中 ssh 到 example.com。您的端口 8888 应该已转发,压缩已打开,并且您的打印机变量都应该已设置好。使用以下命令检查打印机变量

echo $PRINTER
它应该说您设置为 printername 的任何内容。

现在确保您的本地(家用)lpr 系统已启动并正在运行,并在远程系统 (example.com) 上发送文件进行打印

lpr mytestfile.txt

使用 lpq 检查打印作业的状态。另外,观察 rlclient 正在运行的 shell。它将显示正在发生的事情的输出。

我遇到了一些新版本的 ssh 的问题,这些版本使用协议 2 不转发端口或在 rlclient 尝试连接时每次都抱怨。错误消息是这样的

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

在这些情况下,有必要通过在命令行上使用 -1 或将 Protocol 1 添加到 $HOME/.ssh/config 文件中 example.com 的其他条目下来强制协议级别为 1。

除了 lpr 客户端和服务器之外,我发现两个非常简单的程序在调试端口转发方面很有用。这些程序分别称为 time.client.py 和 time.server.py(清单 3 和 4)。这两个程序都接受一个参数,即您希望它们使用的端口号。服务器等待连接,在收到连接时发送一天中的时间,客户端只是打印出时间。它们可以通过 ssh 或在同一台机器上使用。

清单 3. time.client.py

清单 4. time.server.py

一旦一切都调试完毕,就可以更容易地使用脚本在 ssh 到 example.com 时在后台启动 rlclient。然后使用脚本(或脚本的别名)进行 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)

在本例中,我们研究了如何通过 ssh 保护的端口将打印作业从一个位置中继到另一个位置。此端口转发功能的用途仅受您的想象力限制。前进并 ssh 吧。

资源

Using ssh Port Forwarding to Print at Remote Locations
电子邮件:rory@ssc.com

Rory Krause 是 Specialized Systems Consultants 的系统管理员。他拥有华盛顿大学机械工程学位。爱好包括射箭和园艺。

加载 Disqus 评论