Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
Emacs with SSH
[go: Go Back, main page]

Emacs with SSH

この文章では、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 を用いた設定

後藤さん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)
    

Emacs からのパスフレーズの取得

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 を利用するか否かを、より小さな粒度で切り換えたいという要求があるかも知れない。以下では、代替手段を用意している主なアプリケーションの設定について述べる。

Gnus

NNTP

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))

IMAP

imapd をコマンドとして利用できるなら、以下のように設定する。

(setq gnus-select-method '(nnimap "" (nnimap-stream shell))
      imap-shell-host "relay-host")

接続方式は変数 imap-shell-program を順番に試しつつ決定される。

POP

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")))

Wanderlust

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

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 を設定しても良い。

FLIM

変数 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))

ange-ftp / EFS

file-name-handler-alist を利用して自前で SSH を呼び出すパッケージ TRAMP と 補助コマンド (nftp.pl) を利用した Ange ftp over ssh のふたつの方法がある。

relay-host を経由して外部の anonymous FTP にアクセスする際、relay-host までを暗号化したいという要求があるかもしれないが、これは現状では不可能である。

SKK

関数 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

変数 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"

関連研究


Daiki Ueno
Last modified: Tue May 8 22:39:39 JST 2001