OpenSSHを活用する

はじめに

Linuxにとっては基本的なツールであるOpenSSH。 しかしながらサーバーマシンを運用することは少なく、あまり馴染みはないかもしれません。 しかし非常に強力なツールであり、複数のマシンを利用している場合、強力な連携が可能です。

1台だけで使っている場合はあまり有用ではありません。 しかし、LAN内であってもSSHが使えることによってコンピュータを連携してより便利な使い方ができますし、インターネットサーバーがある場合は使い方次第で非常に有用になります。

基礎

単純なログイン

OpenSSHを使ってリモートホストのシェルにログインすることができます。

$ ssh user@serverhost

秘密公開鍵を使ったログイン

パスフレーズ認証を使った認証よりも高い安全性を確保できます。

まずは準備します。

$ ssh-keygen -f ~/.ssh/serverkey_rsa     # SSH鍵を作ります。
$ ssh user@serverhost 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/serverkey_rsa.pub   # 公開鍵をサーバーのユーザーディレクトリ以下 ~/.ssh/authorized_keys に追記します

そして鍵を指定してログインします。

$ ssh -i ~/.ssh/serverkey_rsa user@serverhost

ポートを指定したログイン

sshdが22番ポート以外で待ち受けている場合は、ポートを指定します。

$ ssh -p 2222 user@serverhosr

設定ファイルを使ったログイン

~/.ssh/config ファイルに設定を書くことで、オプションを省略することができます。

Host serverhost
    User user
    Port 2222
    IdentityFile ~/.ssh/serverkey_rsa

これで次のようにログインできます。

$ ssh serverhost

Hostの値は名前解決可能なホスト以外を指定できます。

Hostの値は、「sshコマンドで指定されたホストとしてHostの値に一致する場合にその設定が適用される」という形になります。 リモートホストアドレスを示すHostNameオプションがあるため、これを使ってHostの値は仮想の名前にすることができます。

Host myserver
    User user
    HostName serverhost
    Port 2222
    IdentityFile ~/.ssh/serverkey_rsa
$ ssh myserver

コマンドを実行する

sshコマンドの引数はリモートで実行されるコマンドになります。

先程登場した

$ ssh user@serverhost 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/serverkey_rsa.pub

もそのひとつです。

コマンドを実行するときにはそのユーザーのログインシェルによって実行されます。 これは、bash -czsh -cで実行されることを意味します。

$ ssh user@serverhost 'date'

シェルで解釈されるため、シェルが解釈する文字列であることに注意が必要です。 その意味で、シングルクォートすることが推奨されます。

$ ssh user@serverhost 'echo $(basename $SHELL)'

ファイルをコピーする

scpを使ってファイルを転送することができます。

$ scp somefile user@serverhost:folder/

サーバーにもrsyncがあるのであれば、rsyncも利用できます。

$ rsync somefile user@serverhost:folder/

SFTPを使う

SSHでログイン可能な状態であれば、SFTPでのアクセスも可能です。

SFTPアクセスといえばFilezillaなどのソフトウェアでアクセスすることを想定するでしょうが、Nautilus, Nemo, Dolphin, Thunarなどでもアクセスすることができます。 また、sftpコマンドや、SSHFSによってアクセスすることもできます。

ローカルマシンの通信を他のホストへ転送する

-Lオプションを使うことで、ポートをOpenSSHにlistenさせ、その通信をSSHで接続したホストに転送することができます。

次の例では、ローカルマシンの8080番ポートへの通信をserverhostの80番ポートへ転送します。

$ ssh -L 8080:localhost:80 user@serverhost

ここにおけるlocalhostserverhostによって解釈されます。 つまり、serverhost上の127.0.0.1あるいは::1を意味します。結果的にserverhostのことになりますが、serverhostloインターフェイスのアクセスになることに注意が必要です。

同様に別のホストを指定すれば、接続されたホストはパケットを中継して指定されたホストの指定されたポートへ届けます。 例えば次のようにすれば、serverhostを経由してwww.example.comの80番ポートに到達します。

$ ssh -L 8080:www.example.com:80 user@serverhost

接続先ホストのローカルネットワーク上のホストも指定できます。 次のように192.168.16.10を指定した場合、そのアドレスは接続元ホストのローカルネットワーク上のホストではなく、接続先ホストのローカルネットワーク上のホストを意味します。

$ ssh -L 8080:192.168.16.10:80 user@serverhost

これは例えば、厳しいポリシーを採用したファイアウォールを越えてHTTPプロキシにアクセスする場合などに有効です。

例えばserverhost:8080においてSquidがHTTPプロキシを提供していると仮定します。 しかしserverhost:22へのアクセスは可能なものの、serverhost:8080への接続ができないファイアウォール上にいるとします。

この場合、次のようにします。

$ ssh -L 8000:localhost:8080 user@serverhost

これで、HTTPプロキシとしてlocalhost:8000を指定すればserverhost:8080のプロキシに転送されます。 この方法は検閲を回避するためにも使えます。

リモートホストの通信を自ホストへ中継する

-Lオプションとは逆に、接続先ホスト上で待ち受け、接続元ホストで中継します。

次の例では、接続先ホストの2222番ポートへの接続を、接続元ホストの22番ポートへ転送します。

$ ssh -R 2222:localhost:22 user@serverhost

この方法を使うことで、インターネットに直接公開されていないホストへのアクセスを可能にします。 例えば、家の中にあるデスクトップマシンでこのようにインターネットに公開されたserverhostへ接続しておき、serverhostからデスクトップへ転送するようにしておき、外出中ラップトップからserverhostにログインしたあと、serverhost上からデスクトップへとログインします。

serverhostで直接公開するには、

$ ssh -g -R 2222:localhost:22 user@serverhost

-gオプションを使うことでloインターフェイス以外に公開することができます。 また特定のインターフェイスにおいて公開するようにするには

$ ssh -R 192.168.3.1:2222:localhost:22 user@serverhost

のようにしてバインドアドレスを指定します。

踏み台ホストを利用してログインする

前述の-Rによってインターネットからログインできるようにし、かつセキュリティ的理由でloインターフェイスのみに公開する場合、serverhostからログインできるようにしても良いですが、この場合serverhostが鍵を持つのはセキュリティリスクにもなります。

また、ラップトップとしても、手軽にサーバーを経由する(インターネット上にいる)か、サーバーを経由しない(ローカルネットワーク上にいる)かを切り替えられたほうが良いでしょう。

この場合、ProxyCommandオプションを使うことで、ssh接続を行う前に通信経路を確立してからその通信経路を通じてアクセスすることができるようになります。 この通信経路へのアクセスは標準入出力を使った双方向通信を使います。

この通信経路の確立にsshを使い、そして-Wオプションを組み合わせることでSSHで通信経路を確立し、そのSSH接続先ホストからアクセスすることができるようになります。

この場合、上述の中継例でラップトップから次のようにします。

$ ssh -oProxyCommand="ssh -W %h:%p user@serverhost" user@localhost

この設定を設定ファイルに書いておくことで、簡単に切り替えられるようにできます。

Host desktop
    User user
    Host 192.168.3.10
    IdentityFIle ~/.ssh/desktop_rsa

Host desktop-proxy
    User user
    Host localhost
    Port 2222
    ProxyCommand ssh -W %h:%p myserver
    IdentityFIle ~/.ssh/desktop_rsa

Host myserver
    User user
    Host serverhost
    IdentityFile ~/.ssh/server_rsa

X11転送を行う

X11転送を行うことで、SSH経由でアクセスしたXサーバーが稼働するホスト上でXアプリケーションを起動し、その描画を転送することができます。

これには次のようにします。

$ ssh -X user@serverhost

前提として、OpenSSHサーバーがX転送を許可している必要があります。 セキュリティ上の問題があるため、ユーザーあたりで許可したほうが良いでしょう。

Match User jrh
    X11Forwarding yes

サーバーが信頼できる場合、全てのX11転送を行う-Yオプションもあります。

$ ssh -Y user@serverhost

X11転送は効率が全くよくありません。 VLCやRDPとは比べ物にならないほどです。 ですから、使うのであれば高速なLAN上のホストにしておいたほうが無難でしょう。

なお、注意点として、この方法は~/.xprofileが読まれません。 これによって日本語入力ができなかったりします。

ダイナミックフォワーディング

-Dオプションを使うと、OpenSSHは接続元ホストの指定ポートで SOCKS4/5で 接続を持ち受け、この接続を接続先ホストに転送します。

こうすることでウェブブラウザやメールクライアントなどで利用できるプロキシサーバーを簡単に用意することができます。

$ ssh -D 8080 user@serverhost

なお、このプロキシは匿名化の効果があるわけではないことに注意してください。 パケットの発信元は接続先ホストであるように見えますが、普通SSHログイン可能なホストは匿名性を確保されているわけではありません。 特に司法捜査を回避するような機能は提供しません。

ただし、なんらかの理由で

PPP over SSH

あまり知られていないネットワークhackとして、pppデーモン同士の通信をSSHで接続することでセキュアにネットワークを越えることができ、これを使った簡易VPNを実現することができます。

# pppd updetach noauth silent nodeflate pty "ssh root@serverhost pppd nodetach notty noauth" ipparam vpn 192.168.32.1:192.168.32.2

あとは、pppデバイスはIPアドレスが割り振られ、PPPリンクされた状態になります。 ルートを設定してください。また、ファイアウォールの設定にも注意してください。

VPN over SSH

OpenSSHにはTUN/TAPサポートが組み込まれており、これを用いたVPNが構築可能です。

まず、TUNデバイスをセットアップします。 systemd-networkdを使うには、まず/etc/systemd/network/vpn.netdevのようなファイルに

のように記述し、/etc/systemd/network/vpn.networkファイルを

と記述し、systemd-networkdを再起動します。 サーバー側も同様に(IPアドレスをかえて)設定します。

サーバー側は/etc/ssh/sshd_configにおいてPermitTunnel point-to-pointとします。 クライアント側は-oTunnel="point-to-point"を指定します。 これによってTUNが使われます。

そして、SSHで-wオプションを使ってログインすることで接続を確立します。 次の例ではクライアント、サーバーともに/dev/tun5を使用します。

# ssh -w5:5 root@serverhost

この状態では単純に接続だけが確立され、インターフェイスはセットアップされません。 また、こうして接続するとシェルにログインしますが、ログアウトしてSSHセッションを終了しても接続は維持されます。

インターフェイスをセットアップしていきます1

# ip link set tun5 up
# ip addr add 192.168.32.2 peer 192.168.32.1 dev tun5

クライアント側でも同様に行います。

# ip link set tun5 up
# ip addr add 192.168.32.1 peer 192.168.32.2 dev tun5

あとはルーティングを設定します。 また、iptablesの設定にも注意してください。


  1. net-tools(ifconfig)を使った例は検索すると出てきますが、ここではiproute2を使った方法を示します。