sshの活用法まとめ

#概要
去年書いた[前に書いた多段SSHの投稿](http://qiita.com/ik-fib/items/12e4fab4478e360a82a1)が予想以上にすごいスタックされた(ありがとうございます)うえに、400スタック超でQiita公式twitterに通知された後また伸びたので、調子に乗って自分がよくssh(通信)を利用している例をまとめます。

#多段SSH
~/.ssh/configに設定を書くことで、踏み台サーバを経由したアクセスが可能です。
例: HostA経由でしかアクセス出来ないHostBに対して、以下の様な.ssh/configを書くとssh hostB-outのようにHostAを経由して直接HostBにアクセス可能

```
Host HostB-out
  HostName HostB
  User fuga
  ProxyCommand ssh -W %h:%p HostA
```
詳しくは以下を参照してください。
- [多段SSHの設定を.ssh/configにまとめる - Qiita](http://qiita.com/ik-fib/items/12e4fab4478e360a82a1)

以下の使用例は、内部的にシステムのsshコマンドを利用するものであれば、configに書けば基本的にどれでも使用可能です。

```shell-session:例
sftp HostB-out
```

# SSHクライアント
代表的なOSでのおすすめのSSHクライアントです。
## windows
Windowsであまりsshを使うことが無いのですが、使用する際にはPuTTY(ポートフォワーディングが可能)をクライアントとして利用しています。コマンドとして利用する場合は、Cygwin等をいれればできると思いますが、試していないので不明です。
## Mac/Linux
基本的に標準のsshコマンドで十分ですが、上記の多段SSHの設定で使っている-WオプションはOpenSSH 5.4からの追加なので、それ以下のバージョンの場合は、最新のバージョンのOpenSSHを別途インストールする必要があります。(CentOS6などはデフォルトのバージョンが5.3、もしnc等が踏み台サーバで利用可能であればそちらを利用することもおそらく可能)
## Android
Androidでは[JuiceSSH](https://play.google.com/store/apps/details?id=com.sonelli.juicessh&hl=ja)を利用しています。
このクライアントでは主に以下のことが可能です。(他もありますが省略)

- ポートフォワーディング
- 多段踏み台アクセス
 
AndroidでのSSHクライアントはいくつかありますが、当初SSHクライアントを探していた時に上記のようなことができるクライアントがこれぐらいしか見つからなかったので、重宝しています。

#ファイル転送
## scp
scpを使用することでネットワーク越しに行なうファイル転送をsshでの暗号化された経路で行なうことが出来ます。

利用するには、ホスト側とリモート側、両方にscpが利用できる環境が必要です。しかし、一般的なLinuxマシンであれば、明示的に禁止している場合を除き、sshが利用できてscpが使えないということは少ないと思います。

```shell-session:ホストからクライアントへ
scp remote-host:/path/to/target-filedir/file.txt /path/to/localsave
```

```shell-session:クライアントからホストへ
scp /path/to/target-filedir/file.txt remote-host:/path/to/remotesave
```
## sftp
sftpもscpと同じくファイル転送を行なう事ができます。
こちらは一旦stfpのコネクションを貼ったら、明示的に切断するまでコネクションを維持して、ユーザからのファイル転送のコマンドを実行することができます。

たとえば、一度サーバに接続した後は、自由にディレクトリの移動や、lsでの中身確認等が出来ます。

```shell-session
% sftp remote-host
Connected to remote-host.
sftp> ls
file1
file2
sftp> pwd
Remote working directory: /home/user
sftp> mkdir dir1
sftp> cd dir1
sftp> pwd
Remote working directory: /home/user/dir1
sftp> cd ..
sftp> get file1
Fetching /home/user/file1 to file1
/home/user/file1                               100%   13KB  12.9KB/s   00:00
```
また、各コマンドの頭にlを付けて実行するとローカル側の操作も可能です。(lcd,lls,lpwd等)

個人のマシンではsftpサーバの実行/停止は自由にできますが、企業で利用しているサーバ等であれば明示的に止めている場合もありえるので、その状況に合わせて、利用できるものを利用してください。

scpとsftpの内部的な差は、他の方がまとめられているので詳しくはそちらを参照してください。[SSH,Linux - SCP,SFTP,FTPSの違い - Qiita](http://qiita.com/cyberblack28/items/275c5df386a50b224765
)
## sshfs
sshfsを利用すれば、ssh経由で他のマシンのディレクトリをマウントすることも可能です。

マウントされるNAS側にNFS等、ネットワークマウントの用意がされていなくてもsshでログインできるものであれば、基本的にマウントできます。
sshfsを利用するには、クライアント側に別途インストールが必要ですが、Macならばbrew(別途osxfuseが必要)、linuxならばaptやyumで入ります。

```shell-session:Mac_install
brew install osxfuse
sudo /bin/cp -RfX /usr/local/opt/osxfuse/Library/Filesystems/osxfusefs.fs /Library/Filesystems/
sudo chmod +s /Library/Filesystems/osxfusefs.fs/Support/load_osxfusefs
brew install sshfs
```
```shell-session:Linux(apt)_install 
sudo apt install sshfs
```
```shell-session:Linux(yum)_install 
sudo yum install sshfs
```

インストールが終われば、後は以下のようにマウントしたいディレクトリとそのマウントポイント指定して実行すればそのディレクトリにssh経由でディレクトリがマウントされます。

```shell-session
sshfs remote-host:/target-dir ~/mnt
```

サーバにNFS,samba等が入っていない、または入れるほどではないがマウントしたい時などに利用しています。

# リモート操作
## X転送
Xサーバの入っているサーバに対して-X,または-Yオプションを付けてssh接続すると、リモートホストのx11アプリケーションのウィンドウをローカルホストに表示してくれるようになります。

```shell-session
ssh -Y remote-host
```
オプションを付けた上で、x11アプリケーションをリモートホストで実行すると、その画面はクライアント側で表示されます。

```shell-session:X転送例
user@MacBook% ssh -Y remote-host
user@remote-host% xeyes
```
![xeyes実行例](https://qiita-image-store.s3.amazonaws.com/0/39736/4871649b-c4a1-330a-fb72-808313e661f0.png)

## ポートフォワーディング
sshで接続できるリモートホストから通信できる特定のポートを、ローカルホストの特定のポートに紐付けることが出来ます。

```shell-session
ssh -L ローカルホストのポート:対象のIPアドレス:リモートホストのポート remote-host
```
これを利用することで、LAN以外に送信できない通信をssh経由でWANから取得するなどが可能([後述のリモートデスクトップ](http://qiita.com/ik-fib/items/0af46a19e3083bb0325e#windows-%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97)等)

また、独自のssh設定で動作しているツール(GUIのファイル転送ツール等)を無理矢理多段SSHで動作させることも可能です。
以下のように、対象リモートホストの22番ポートをローカルホストの22番ポートと紐付けて、ローカルホストの22番ポートに向かって通信することで、GUIツールでも多段SSH対応っぽく動作させることが出来ます。

```shell-session
ssh -L 22:localhost:22 remote-host
```

### 逆ポートフォワーディング
[前述のポートフォワーディング](http://qiita.com/ik-fib/items/0af46a19e3083bb0325e#%E3%83%9D%E3%83%BC%E3%83%88%E3%83%95%E3%82%A9%E3%83%AF%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0)では、リモートホストの特定のポートをローカルホストに紐づけていましたが、逆にローカルホストの特定のポートをリモートホストに紐付けることも可能です。

```shell-session
ssh -R リモートホストのポート:対象のIPアドレス:ローカルホストのポート remote-host
```
例えば、以下のようにすると接続しているクライアントにサーバ側からsshでログインできる様になります。

```shell-session:逆ポートフォワーディングの例
user@MacBook% ssh -R 10022:localhost:22 remote-host
user@remote-host% ssh user@localhost -p 10022
user@MacBook%
```

これを利用すれば、外部からアクセスできないマシン(グローバルIPを持たない自宅PC等)のポートを外からアクセスできるマシンのポートに割り付けて外部からアクセスすることも可能です。

ただし、そのマシンにアクセスできる人はそのポートにもアクセス出来てしまうので、間違えると外部からアクセスし放題な状況にもなりかねないので注意してください。

## Windows リモートデスクトップ
Windows (Professional以上)にはリモートデスクトップで操作する機能が標準で搭載されています。(クライアントは全バージョン可)

これの標準のリモートツールでは、TeamViewerなどのリモートデスクトップソフトと違い、リモート操作しつつ、その画面を送信するのではなく、リモート接続しているソフトがディスプレイとなります。すなわち、この方法でリモートログインすると実画面には表示されず(実画面でログインしてもそちらは画面ロックされる)、リモート操作している方のみに画面が表示されます。

どちらの方式がいいかは一長一短だと思いますが、私はリモート操作するときに元画面が操作可能である必要のある場面は少ないので、こちらの方法を重宝しています。

WindowsからWindowsマシンへのリモート操作はもちろん可能ですが、Mac,Linuxからも操作可能です。

Macでは[Microsoft Remote Desktop](https://itunes.apple.com/jp/app/microsoft-remote-desktop/id715768417?mt=12)を利用、Linuxではrdesktop等のRemote Desktop Protocol（RDP）対応のツールを使うことでリモート操作が可能です。

これに、[前述のポートフォワーディング](http://qiita.com/ik-fib/items/0af46a19e3083bb0325e#%E3%83%9D%E3%83%BC%E3%83%88%E3%83%95%E3%82%A9%E3%83%AF%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0)と組み合わせることで、SSH以外をLANの外から利用できる状態にしなくても、このリモートデスクトップを利用することが出来ます。このリモートデスクトップで利用されているポートは3389なので、対象マシンのそのポートをポートフォワーディングでローカルのポートと紐付けます。

```shell-session
ssh -C -L 3389:WindowsマシンのIP:3389 remote-host
```
そして、localhostに対して、各種リモートクライアントで接続することでremote-hostネットワーク上のwindowsマシンにリモート操作できるようになります。

## SOCKSプロキシ
http://qiita.com/kiida/items/37557a1029788afec98a#comment-6cd3ac44f9bd414a89f6 にも書かれていますが、以下のように実行するとlocalhost:1080にremote-hostが出口のSOCKSサーバが作成されます。

```shell-session
ssh -D 1080 remote-host
```
これを利用することでssh経由のプロキシとして利用することが出来ます。

上記のコマンドでSOCKSを作成した後、localhost:1080をプロキシとして利用するように各ブラウザで設定します。
通常のHTTP通信が行われるのは、ブラウザとlocalhost間のみで、localhostとremote-host間はsshで通信されるので、その間の経路は基本的に暗号化されます。

私は、公共無線LANなど経路上の安全が不明確な場所で、ブラウザを利用した作業をする際には、よくこの形式で通信の暗号化をしています。

## SSH-VPN
上記のようなSOCKSプロキシが設定できない類のプログラム等を利用する際には、sshuttleを利用することでSSH経由のVPNを構築することが可能です。
sshuttleもクライアント側に別途インストールが必要ですが、Macならばbrew、linuxならばaptやyumで入ります。

```shell-session:Mac_install
brew install sshuttle
```
```shell-session:Linux(apt)_install 
sudo apt install sshuttle
```
```shell-session:Linux(yum)_install 
sudo yum install sshuttle
```

インストールが完了すれば、以下のコマンドで全ての通信をremote-host経由、かつremote-hostが属しているLAN内に端末があるのと同様に通信することが出来ます。

```shell-session:全ての通信をVPN経由に
sshuttle -r remote-host 0.0.0.0/0
```
また、特定のホストに対する通信だけをVPN経由にすることも可能です。
例えば、以下のように指定して実行すると、192.168.100.0/24のアドレスに対しての通信だけVPN経由になり、それ以外の通信は通常通りに通信が行われます。

```shell-session:特定のホストに対しての通信だけをVPN経由に
sshuttle -r remote-host 192.168.100.0/24
```