SORACOM AirでPPP接続しているRaspberry PiをインターネットからSSHアクセスする

# はじめに
SORACOM Air使ってますか？私は使っています。ただ、ラズパイ使いの方々に話を聞くと**「SORACOM AirでPPP接続したラズパイにグローバルIPアドレスが付与されないためリモートでのメンテができないのでちょっと困る」**というチラホラ聞きます [^1] 。
SORACOMの安川さんが以下のブログ記事でヒントを書かれていますが、安川さんによると現在（2015年12月現在）もリモートアクセスについて問い合わせが多いそうです（とSORACOM User Group #0で聞きました）。

+ [SORACOM AirとBeamと時々NAT越え](https://blog.soracom.jp/blog/2015/10/15/air-beam-and-nat/)

今回は上記URLのヒントをヘチらせていただいて（=パクらせていただいて）中継サーバのポートフォワードによるSSHトンネリングを行う手順を示したいと思います。
![00.PNG](https://qiita-image-store.s3.amazonaws.com/0/4092/1511cba9-21d9-1ee0-ed61-8ce98643c8bf.png)



当記事は長めで申し訳ないのですが :sweat: 枯れたテクニックですので仕込むのはさほど難しくありません :+1: 

---
# 概要

インターネット上でssh接続できるLinuxサーバを**中継サーバ**として、あらかじめラズパイからのSSH接続をポートフォワードを行いSSHリモートアクセスを実現する。中継サーバは、今回IDCFクラウドの仮想マシンを使います。お好みによりAWS EC2など別のIaaSサーバやVPSでも構いません。

+ 準備で使うコマンド
 + SORACOM AirでPPP接続したラズパイでは以下の`autossh`コマンドで中継サーバに接続しておきます。PPPPはSSHフォワードを行うポート番号、AAA.BBB.CCC.DDDは中継サーバのグローバルIPアドレスです。


```bash
$ autossh -M 0 -q -f -N -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3"  -R PPPP:localhost:22 AAA.BBB.CCC.DDD
```
![10.PNG](https://qiita-image-store.s3.amazonaws.com/0/4092/74cc9795-f905-4739-adfe-c1939c78053a.png)


+ 接続で使うコマンド
 + 中継サーバにSSHログインしておきます。
  ![20.PNG](https://qiita-image-store.s3.amazonaws.com/0/4092/c796d8ee-4734-427a-a7ee-6a52171e338f.png)
 + 以下のsshコマンドでラズパイにトンネリングSSH接続を行います。

```bash
$ ssh pi@localhost -p PPPP
```
![30.PNG](https://qiita-image-store.s3.amazonaws.com/0/4092/4b694127-3951-898c-57cf-4abca20c6248.png)


以上のコマンドを使って、実際の手順を紹介していきます。

##準備 概要
1. 中継サーバのIPアドレスを確認しSSHポートを開いておく [:link:](http://qiita.com/dietposter/items/6780a9c6df02ca6ae22c#%E4%B8%AD%E7%B6%99%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AEip%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%AE%E7%A2%BA%E8%AA%8Didcf%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E4%BB%AE%E6%83%B3%E3%83%9E%E3%82%B7%E3%83%B3%E3%81%AE%E5%A0%B4%E5%90%88) 
1. SORACOM Airをつないだラズパイと中継サーバとが`~/.ssh/config`を使ってrootユーザで接続できるようにしておく [:link:](http://qiita.com/dietposter/items/6780a9c6df02ca6ae22c#soracom-air%E3%82%92%E3%81%A4%E3%81%AA%E3%81%84%E3%81%A0%E3%83%A9%E3%82%BA%E3%83%91%E3%82%A4%E3%81%A8idcf%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E4%BB%AE%E6%83%B3%E3%83%9E%E3%82%B7%E3%83%B3%E3%81%A8%E3%81%8Csshconfig%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6root%E3%83%A6%E3%83%BC%E3%82%B6%E3%81%A7%E6%8E%A5%E7%B6%9A%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%97%E3%81%A6%E3%81%8A%E3%81%8F)
1. ラズパイ側で`autossh`を用いて中継サーバに向けて自動接続＆接続維持を行うようにしておく [:link:](http://qiita.com/dietposter/items/6780a9c6df02ca6ae22c#%E3%83%A9%E3%82%BA%E3%83%91%E3%82%A4%E5%81%B4%E3%81%A7autossh%E3%82%92%E7%94%A8%E3%81%84%E3%81%A6%E4%B8%AD%E7%B6%99%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AB%E5%90%91%E3%81%91%E3%81%A6%E8%87%AA%E5%8B%95%E6%8E%A5%E7%B6%9A%E6%8E%A5%E7%B6%9A%E7%B6%AD%E6%8C%81%E3%82%92%E8%A1%8C%E3%81%86%E3%82%88%E3%81%86%E3%81%AB%E3%81%97%E3%81%A6%E3%81%8A%E3%81%8F)
1. 中継サーバ側で、ラズパイからのSSH接続＆ポートマッピングを確認する。 [:link:](http://qiita.com/dietposter/items/6780a9c6df02ca6ae22c#idcf%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E4%BB%AE%E6%83%B3%E3%83%9E%E3%82%B7%E3%83%B3%E5%81%B4%E3%81%A7%E3%83%A9%E3%82%BA%E3%83%91%E3%82%A4%E3%81%8B%E3%82%89%E3%81%AEssh%E6%8E%A5%E7%B6%9A%E3%83%9D%E3%83%BC%E3%83%88%E3%83%9E%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B)

##接続手順 概要
1. 中継サーバにSSH接続を行う [:link:](http://qiita.com/dietposter/items/6780a9c6df02ca6ae22c#%E4%B8%AD%E7%B6%99%E3%82%B5%E3%83%BC%E3%83%90%E3%81%ABssh%E6%8E%A5%E7%B6%9A%E3%82%92%E8%A1%8C%E3%81%86)
1. SSH接続を行った中継サーバで、SSHフォワードしているポートにSSH接続する [:link:](http://qiita.com/dietposter/items/6780a9c6df02ca6ae22c#ssh%E6%8E%A5%E7%B6%9A%E3%82%92%E8%A1%8C%E3%81%A3%E3%81%9F%E4%B8%AD%E7%B6%99%E3%82%B5%E3%83%BC%E3%83%90%E3%81%A7ssh%E3%83%95%E3%82%A9%E3%83%AF%E3%83%BC%E3%83%89%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%83%9D%E3%83%BC%E3%83%88%E3%81%AB%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%ABssh%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B)
1. その結果、SSHトンネリングによりラズパイにSSHリモートアクセスが行われる [:link:](http://qiita.com/dietposter/items/6780a9c6df02ca6ae22c#%E3%81%9D%E3%81%AE%E7%B5%90%E6%9E%9Cssh%E3%83%88%E3%83%B3%E3%83%8D%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E3%82%88%E3%82%8A%E3%83%A9%E3%82%BA%E3%83%91%E3%82%A4%E3%81%ABssh%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%8C%E8%A1%8C%E3%82%8F%E3%82%8C%E3%82%8B)

___
# 詳細
##準備の詳細
**【前提：IDCFクラウド仮想マシンの場合】IDCFクラウドで「めちゃ楽ガイド」などを使ってUbuntuなどのLinuxサーバーが立ち上がっている状態を前提とします。**「めちゃ楽ガイド」の手順で示されている仮想マシン、IPアドレス、SSH Keyのテキストファイルの情報が必要になります。
また、ご自身のPCでSSH KeyによるSSHアクセスができる状態にしておいてください。

###中継サーバのIPアドレスの確認（IDCFクラウド仮想マシンの場合）

ご自身のPCなどからブラウザを起動し、IDCFのクラウドコンソールから「IPアドレス」をクリックします。ログインしていない場合は、[IDCFクラウドにアクセス](http://idcfcloud.com/)してログインIDとパスワードを入力してログインします。
![idcf01.png](https://qiita-image-store.s3.amazonaws.com/0/4092/97d870fc-b61c-9091-31db-70835e84c070.png)
該当のIPアドレス名を確認し、IPアドレスをコピーしておきます。
IPアドレス名をクリックし、ファイヤーウォールの設定でSSHの22番ポートを設定します。
![idcfFW.png](https://qiita-image-store.s3.amazonaws.com/0/4092/fd7f158e-1677-a759-aacd-3b387367307d.png)
あわせて、ポートフォワードの設定でSSHの22番ポートを設定します。中継サーバとして使う仮想マシンを指定してください。ここでは「yoshiken0830」を指定しています。
![idcfPFwd.png](https://qiita-image-store.s3.amazonaws.com/0/4092/8c506c59-ea1e-6bea-36fe-cdabb44efcc4.png)

###SORACOM AirをつないだラズパイとIDCFクラウド仮想マシンとが~/.ssh/configを使ってrootユーザで接続できるようにしておく
SSH Keyのテキストファイル「raspi-sora.txt」をラズパイ側にアップロードします。ホームディレクトリ下の.sshディレクトリにアップロードします。SCPでファイル転送したりUSBメモリでコピーしたりもできますし、ラズパイにSSHでつないでいるので`vi`エディタでファイルを作ってペーストしたりします。

```bash
pi@raspi-air:~$ vi ~/.ssh/raspi-sora.txt
```
ご自身のPCにあるメモ帳やダウンロードした「raspi-sora.txt」を開き、全てを選択してコピーし、`vi`で開いている`~/.ssh/raspi-sora.txt`ファイルに貼り付け、保存します。
次に、ホームディレクトリ下の.sshディレクトリにconfigファイルを作成して、rootユーザでSSH keyを使ってアクセスできるようにします。

```bash
pi@raspi-air:~$ vi ~/.ssh/config
```
AAA.BBB.CCC.DDDはご自身のIDCFクラウド仮想マシンにアクセスするIPアドレスを入れてください。

```bash:~/.ssh/config
Host AAA.BBB.CCC.DDD
  HostName AAA.BBB.CCC.DDD
  IdentityFile ~/.ssh/raspi-sora.txt
  User root
```
`vi`エディタを保存・終了したら、動作確認のため`ssh`でアクセスしてみましょう。

```bash
pi@raspi-air:~$ ssh AAA.BBB.CCC.DDD
```
以下の様なプロンプトがでればログインできています。ログインが確認できたら`exit`コマンドでログアウトしておきます。

```
root@yoshiken0830:~# 
```
###ラズパイ側でautosshを用いて中継サーバに向けて自動接続＆接続維持を行うようにしておく

あらかじめautosshコマンドをインストールしておきます。

```bash
pi@raspi-air:~$ sudo apt-get install autossh
```
次に`/etc/init.d`ディレクトリに自動起動スクリプト`soracomair_autossh`を作成します。

```bash
pi@raspi-air:~$ sudo vi /etc/init.d/soracomair_autossh
```
`autossh`コマンドを使って中継サーバのIPアドレスAAA.BBB.CCC.DDDに接続を行う様に設定します。`AAA.BBB.CCC.DDD`の部分をご自身のIDCFクラウド仮想マシンのIPアドレスに置き換えてください。
**中継サーバとなるIDCFクラウド仮想マシンのポート番号8022番をラズパイ側のSSHサーバのポート22番にマッピングする指定を行っています。**

```bash:/etc/init.d/soracomair_autossh
#!/bin/sh
### BEGIN INIT INFO
# Provides:             soracomair_autossh
# Required-Start:       $local_fs
# Required-Stop:        $local_fs
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    autossh tunnel
### END INIT INFO

start(){
        echo -n "starting autossh...\n"
        su -c 'autossh -M 0 -q -f -N -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3"  -R 8022:localhost:22 AAA.BBB.CCC.DDD'
        return 0
}

stop(){
        echo -n "stopping autossh...\n"
        killall autossh
        return 0
}
case $1 in
        start)
                start
                        ;;
        stop)
                stop
                        ;;
esac
```

起動スクリプトを作成・保存できたら、`insserv`コマンドで各ランレベルの起動リンクを設定します。

```bash
pi@raspi-air:~$ sudo insserv -d /etc/init.d/soracomair_autossh
pi@raspi-air:~$ ls -l /etc/rc*.d/*autossh*
lrwxrwxrwx 1 root root (…中略…) /etc/rc0.d/K02soracomair_autossh -> ../init.d/soracomair_autossh
lrwxrwxrwx 1 root root (…中略…) /etc/rc1.d/K02soracomair_autossh -> ../init.d/soracomair_autossh
lrwxrwxrwx 1 root root (…中略…) /etc/rc2.d/S01soracomair_autossh -> ../init.d/soracomair_autossh
lrwxrwxrwx 1 root root (…中略…) /etc/rc3.d/S01soracomair_autossh -> ../init.d/soracomair_autossh
lrwxrwxrwx 1 root root (…中略…) /etc/rc4.d/S01soracomair_autossh -> ../init.d/soracomair_autossh
lrwxrwxrwx 1 root root (…中略…) /etc/rc5.d/S01soracomair_autossh -> ../init.d/soracomair_autossh
lrwxrwxrwx 1 root root (…中略…) /etc/rc6.d/K02soracomair_autossh -> ../init.d/soracomair_autossh
```
うまく設定できているようなら再起動します。

```bash
pi@raspi-air:~$ sudo reboot
```
再起動後、中継サーバとなるIDCFクラウド仮想マシン側で接続＆ポートマッピングされているか確認してみましょう。

###IDCFクラウド仮想マシン側で、ラズパイからのSSH接続＆ポートマッピングを確認する。
ご自身のPCからIDCFクラウド仮想マシンにSSHアクセスを行います。`netstat`コマンドで22番、8022番ポートの状況を確認します。

```bash
root@yoshiken0830:~# netstat -lt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address     State
tcp        0      0 localhost:smtp          *:*                 LISTEN
tcp        0      0 *:1883                  *:*                 LISTEN
tcp        0      0 localhost:8022          *:*                 LISTEN ←コレ！
tcp        0      0 *:ssh                   *:*                 LISTEN
tcp6       0      0 localhost:smtp          [::]:*              LISTEN
tcp6       0      0 [::]:1883               [::]:*              LISTEN
tcp6       0      0 localhost:8022          [::]:*              LISTEN
tcp6       0      0 [::]:ssh                [::]:*              LISTEN
root@yoshiken0830:~# 
```
localhost:8022がLISTENであれば、ポートマッピングがうまく設定できているはずです。
8022番ポートにSSHで接続すれば、マッピングされたポートにフォワードされて、ラズパイにSSH接続ができるようになります。`exit`コマンドで中継サーバからログアウトしておくか、そのまま以下の接続手順を行います。

##接続手順の詳細
###中継サーバにSSH接続を行う
ご自身のPCから中継サーバにSSHアクセスを行います。Macだとターミナルからsshコマンドで。WinだとTera Termなどで。

###SSH接続を行った中継サーバで、SSHフォワードしているポートにローカルSSH接続する。
以下の`ssh`コマンドで、ラズパイにSSHアクセスを行う。

```bash
root@yoshiken0830:~# ssh pi@localhost -p 8022
pi@localhost's password: ←ラズパイのpiユーザのパスワード

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Dec 18 12:01:40 2015 from ...
pi@raspi-air:~$ 
```

###その結果、SSHトンネリングによりラズパイにSSHリモートアクセスが行われる
上記の様に、ラズパイのpiユーザのコマンドプロンプトが表示されればOKです。インターネットからSORACOM AirでPPP接続しているRaspberry PiをSSHアクセスすることができました！
お疲れ様です。

##注釈
[^1]: SSHでリモートメンテする運用自体アカンのちゃう？とか、IoT時代のデバイスはSSHアクセスするようなモンではないんだよ〜とかのハナシもある訳ですが、現状ではそうせざるを得ない状況も少なからずあります。