この文章では、Emacs 上の様々なプログラムから SSH を経由してネットワークにアクセスする方法を述べています。基本的に無保証ですが、現状に似わない点を発見されたら連絡を頂けるとありがたいです。
最初に、以下の関数を考える。
(defun open-ssh-stream-internal (name buffer relay-host host service)
(let ((service (if (stringp service)
service
(int-to-string service)))
(process-connection-type nil))
(start-process-shell-command
name buffer "ssh" "-C" "-a" "-x" "-q" relay-host
"nc" host service)))
この関数を利用するためには、relay-host にパスフレーズなしでログイン可能であり、relay-host 上に netcat がインストールされている必要がある。
もし特定の relay-host へのトンネルを頻繁に確立するのであれば、ssh のかわりに fsh を用いるのが効果的である。
open-network-stream の置き換え前述の関数 open-network-stream-internal から、open-network-stream と同じ API を持つ関数 open-ssh-stream を作る。
(defun open-ssh-stream (name buffer host service) (open-ssh-stream-internal name buffer "relay-host" host service))
少々強引ではあるが、この関数により open-network-stream の定義を上書きすれば、ほとんどのアプリケーションから SSH ("relay-host") 経由でネットワークにアクセスできるようになる。しかしながら、以降の節で述べるように、トンネル機構を自前でもつアプリケーションも数多くあるため、この形態での利用には十分に注意すべきである。
(defalias 'open-network-stream 'open-ssh-stream)
後藤さん の relay.el を用いれば、ここまでの作業を自動化することができるうえに、アクセス先のホスト毎にコマンド行を変更することができる。
(setq relay-command-alist
'(("^news\.example\.com$"
"ssh" "-C" "-a" "-x" "-q" "relay-host1" "nc" host service)
(t
"ssh" "-C" "-a" "-x" "-q" "relay-host2" "nc" host service)))
(autoload 'relay-open-network-stream "relay")
(defalias 'open-ssh-stream 'relay-open-network-stream)
SSH は、パスフレーズの入力を促すために外部コマンド ssh-askpass(1)を利用する。この振舞いを用いて、gnuserv 経由で Emacs からパスフレーズを取得することができる。
例えば、ssh-askpass という名前で以下のスクリプトを用意しておく。
#! /bin/sh gnuclient -batch -eval '(read-passwd "SSH passphrase: ")'
しかしながら、現在の SSH2 と、少し古い OpenSSH では以下のように挙動が異なる。
このような状況をふまえると、ソフトウェア環境の異なる複数台の計算機で設定を共有するのであれば、ssh-agent(1) を利用するほうが良いだろう。特に Windows 環境で ssh-agent(1) の機能を利用するには、後藤さん の OpenSSH for Win32 が参考になる。
SSH を利用するか否かを、より小さな粒度で切り換えたいという要求があるかも知れない。以下では、代替手段を用意している主なアプリケーションの設定について述べる。
nntp-open-connection-function を設定する。
(defun nntp-open-ssh-stream (buffer)
(let (selective-display
(coding-system-for-read 'binary)
(coding-system-for-write 'binary))
(open-ssh-stream "nntpd" buffer nntp-address nntp-port-number)))
次のようにサーバ毎に設定すると良い。
(nntp "ssh-news-server"
(nntp-address "news-server")
(nntp-open-connection-function nntp-open-ssh-stream))
imapd をコマンドとして利用できるなら、以下のように設定する。
(setq gnus-select-method '(nnimap "" (nnimap-stream shell))
imap-shell-host "relay-host")
接続方式は変数 imap-shell-program を順番に試しつつ決定される。
mail-sources の :prescript キーワードでポートフォワーディングする。
(setq mail-sources
'((pop :server localhost :port 1110 :prescript
"ssh -C -a -x -q -f relay-host -L 1110:pop-server:110 sleep 30 && sleep 1")))
elmo-imap4-stream-type-alist に SSH 用の設定を加える。
(setq elmo-imap4-stream-type-alist
(cons '("!ssh" ssh nil open-ssh-stream)
elmo-imap4-stream-type-alist))
Gnus/IMAP と同様に、imapd をコマンドとして利用する場合には以下のように設定すると良い。
(setq elmo-imap4-stream-type-alist
(cons '("!shell" shell nil elmo-imap4-open-shell-stream)
elmo-imap4-stream-type-alist))
(defun elmo-imap4-open-shell-stream (name buffer host service)
(start-process-shell-command
name buffer (format "ssh %s imapd 2> /dev/null" host)))
他のバックエンド (NNTP や POP3) に関しても同様。
mew-config-alist にて、pop-ssh-server または smtp-ssh-server を指定する。
(setq mew-config-alist
'(("ssh"
("smtp-ssh-server" . "relay-host")
("pop-ssh-server" . "relay-host")
...)
("default"
...)))
Summary モードで C ssh (または Draft モードで C-c C-o) とタイプすることにより relay-host を SSH で経由できる。無条件で SSH 経由でアクセスする場合には mew-pop-ssh-server または mew-smtp-ssh-server を設定しても良い。
変数 smtp-open-connection-function を設定する。
(setq smtp-open-connection-function (function open-ssh-stream))
QMTP を利用したい場合には、同様に qmtp-open-connection-function を設定する。
(setq qmtp-open-connection-function (function open-ssh-stream))
file-name-handler-alist を利用して自前で SSH を呼び出すパッケージ TRAMP と
補助コマンド (nftp.pl) を利用した Ange ftp over ssh のふたつの方法がある。
relay-host を経由して外部の anonymous FTP にアクセスする際、relay-host までを暗号化したいという要求があるかもしれないが、これは現状では不可能である。
関数 skk-open-network-stream を上書きする。
(eval-after-load "skk-server"
'(progn
(defun skk-open-network-stream ()
(condition-case nil
(progn
(setq skkserv-process
(start-process
"skkservd" skkserv-working-buffer
"ssh" skk-server-host "/usr/sbin/dbskkd-cdb"))
(process-kill-without-query skkserv-process))
(error nil)))
(setq skk-network-open-status 'run)))
この関数を用いるためには skk-server-host に パスフレーズなしでログイン可能であり、skk-server-host 上で dbskkd-cdb がコマンドとして実行可能である必要がある。
本来は skk/main/experimental 以下に含まれる、skk-exsearch.el の枠組を利用し、変数 skk-search-prog-list を適切に設定するほうが良いだろう。
変数 liece-server に接続形式 rlogin を指定する。relay-host には、あらかじめ socket(1) がインストールされている必要がある。
(setq liece-server '(:host "irc-server" :service 6667
:type rlogin :relay "relay-host"))
いくつかの設定は変更可能である。
(setq liece-tcp-rlogin-user-name "ueno"
liece-tcp-rlogin-program "ssh"
liece-tcp-rlogin-parameters '("socket")) ;or "nc"