【UserLAnd】AndroidスマホにWi-Fi経由でSSH接続する方法

## はじめに

この記事では**パソコンからSSH接続でAndroidスマートフォンにアクセスすること**を目的とします。

SSH接続するには「openssh」というアプリが入っていれば使えます。Windowsにもデフォルトで入るようになったので、今回はWindowsでSSH接続してみます。
ただし、WindowsからSSH接続するにはpowershellではだめで、**Git Bash** を起動しなければなりません。


スマートフォンではsshどころか**ターミナルが使えない**ため、ターミナルが使えるアプリをインストールします。

以前は「termux」というアプリが主流でしたが**現在はplayストアで更新できない**状態が続いているため、現在おすすめのアプリは **「[UserLAnd](https://play.google.com/store/apps/details?id=tech.ula)」** というアプリになります。

:::note info
以前Qiitaで同じような記事を書いていました[^1]。このときは「termux」を取り上げていましたが、今回はそれの「UserLAnd」版となります。

[^1]: <cite>[AndroidスマホにWifi経由でSSH接続する方法 #Android - Qiita](https://qiita.com/yusu79/items/acea3f7dc306ce83e7f1)</cite>

:::

https://qiita.com/yusu79/items/acea3f7dc306ce83e7f1



UserLAndは**root化しなくてもLinuxコマンドが扱える**、非常に軽いオープンソースアプリです。


普通のLinuxのように`sudo apt install`でアプリをインストールできるので、`iproute2`と`nmap`をインストールします。

UserLAndは**アプリ起動時にSSHデーモンが起動して自動でポートが開放される**ので、`ip -4 a`でIPアドレスを確認したあと、
`nmap localhost`でポートを確認してメモします。
その後、パソコン側で`ssh -p ポート番号 -i SSH秘密鍵 userland@IPアドレス`と打つとSSH接続ができます。


ところでSSH接続をするには鍵が必要です。
パソコン側で`ssh-keygen`コマンドで鍵を作成できます。鍵は「秘密鍵」と「公開鍵」がペアで作成されるので、秘密鍵は`PC:~/.ssh`に保管し、公開鍵は何らかの手段でスマートフォンに送り`userland@localhost:~/.ssh/authorized_keys`に追記します。こうすることで、公開鍵に対応する**秘密鍵を所有しているパソコンのみ**がAndroidスマートフォンにSSH接続できるようになります。

## 使うもの
- パソコン（今回はWindows）
- Andoroidスマートフォン

## SSH接続への手順
### 【前準備】
#### PC
##### 1．Git Bashをインストールする
WindowsにGit Bashをインストールする方法はいくつかありますが、一番簡単な方法は **Scoop** というパッケージ管理ツールを使う方法です。

まずはscoopをインストールします。
powershellを開き、以下のコマンドをそのままコピペして貼り付けてください。
```powershell:scoopのインストール
PS C:\Users\user> Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
PS C:\Users\user> irm get.scoop.sh | iex
```
これでGitがインストールできます。以下のコマンドを入力すると、`C:\Users\ユーザー名\scoop\apps`にGitがインストールされ、Git Bashが使えるようになっています。
```powershell:gitをインストールする
PS C:\Users\user> scoop install git
```


#### Androidスマートフォン
##### 1．「UserLAnd」をインストール

https://play.google.com/store/apps/details?id=tech.ula

###### UserLAndの名前の由来は？

少し話が逸れますが、「UserLAnd」の名前の由来はご存知でしょうか？

これは「OSが動作するのに必要な、カーネル以外の部分」[^2]を指す言葉です。

> ユーザーランド（userland）とは、実行中のオペレーティングシステム（OS）環境の中で、中核部であるカーネル以外の要素のこと。一般ユーザーの権限で操作できる領域であり、シェルやコマンド、アプリケーションなどが含まれる。
> 出典: <cite>[ユーザーランドとは - 意味をわかりやすく - IT用語辞典 e-Words](https://e-words.jp/w/%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%83%A9%E3%83%B3%E3%83%89.html)</cite>

OSは二種類の構造で出来ています。それが「カーネル」と「ユーザーランド」です。
- OS
  - カーネル
  - ユーザーランド

カーネルとはOSのコアで、最も有名なカーネルが「Linux」です。Linuxは **「オープンソース」** のカーネルであったことが画期的であり、爆発的に広まりました。
一方、それ以外の部分である「ユーザーランド」と Linux に直接的な関わりはありません。そのため、Linux  は一般的に **Linux Distribution（Linux配布物）** と呼ばれます。

> Linuxディストリビューションは，Linuxカーネル，Cライブラリ「glibc」などのGNUソフトウエア，各種フリーソフトを組み合わせて，デスクトップやサーバーなどの環境を快適に使えるようにしたOS（オペレーティング・システム）です。
> 出典: <cite>[Linuxディストリビューション | 日経クロステック（xTECH）](https://xtech.nikkei.com/it/article/COLUMN/20060512/237755/#:~:text=Linux%E3%83%87%E3%82%A3%E3%82%B9%E3%83%88%E3%83%AA%E3%83%93%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AF%EF%BC%8CLinux,%EF%BC%88%E3%82%AA%E3%83%9A%E3%83%AC%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%83%BB%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%EF%BC%89%E3%81%A7%E3%81%99%E3%80%82)</cite>

つまり、Linux Distribution とは **「Linuxカーネルと独自のユーザーランドを一纏めにしたもの」** です。

[^2]: <cite>[UserLandとは何？ わかりやすく解説 Weblio辞書](https://www.weblio.jp/content/UserLand)</cite>



スマートフォンアプリ「UserLAnd」は、どの Linux Distribution（ユーザーランド）を使うかユーザーが判断できるアプリです。

有名な Ubuntu や Debian 以外にも、Arch・Alpine・Kali を使うことができます。

##### 2．Ubuntuを選択

アプリを起動すると、以下のような画面になります。

<img width="300" alt="userland-android-wifi-ssh-connection_userland-start_01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395294/ea62cd17-107f-d4cd-5c2a-a824ef38e872.png">


「Session」と「Filesystems」タブを開くと、初期画面では何も写っていません。



<img width="300" alt="userland-android-wifi-ssh-connection_userland-start_02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395294/8eab52ec-7d48-291e-dc24-4b39dc9e49f9.png">



<img width="300" alt="userland-android-wifi-ssh-connection_userland-start_03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395294/c6b97244-cf3c-1954-1a26-61b530429c60.png">

「Ubuntu」を選択します。



<img width="300" alt="userland-android-wifi-ssh-connection_userland-start_04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395294/15e30fdd-358f-963f-66f7-dc5f2027a682.png">

すると、「`Please select a desktop enviroment:`」と聞かれますので、一番上を選んでください。



<img width="300" alt="userland-android-wifi-ssh-connection_userland-start_05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395294/4212ac20-3c52-8527-4dbd-cf3ab03f2ae7.png">

次に、「`Please select a connection type:`」と聞かれますので、「Terminal」を選んでください。
「Always use this setting」チェックはどちらでも構いません。



<img width="300" alt="userland-android-wifi-ssh-connection_userland-start_06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395294/e9dab052-54f9-6134-a98b-7ec5d9533349.png">


すると、以下のような「Setting up」画面となるので、しばらくお待ちください。


<img width="300" alt="userland-android-wifi-ssh-connection_userland-start_07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395294/205a0161-fc62-6997-df49-979df66a380b.png">

しばらく待っていると、以下のような画面が表示されます。
これが「**ターミナル**」です。
ここで、Androidの設定をしていきます。




<img width="300" alt="userland-android-wifi-ssh-connection_userland-start_08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395294/7bc3cb0c-dc7d-0355-b32b-7280a2531189.png">


ちなみに、画面を戻すと、先程何も表示されていなかった「Sessions」と「Filesystems」にubuntuが表示されています。


<img width="300" alt="userland-android-wifi-ssh-connection_userland-start_09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395294/35cd0dac-f148-a567-fcd3-1897f5512fa0.png">


<img width="300" alt="userland-android-wifi-ssh-connection_userland-start_10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395294/319f9e2c-635e-87a4-b21d-8168e3618967.png">

##### 3．必要なパッケージをインストールする
まず最初にupdateとupgradeを済ませます。
```bash:updateとupgrade
userland@localhost:~$ sudo apt update
userland@localhost:~$ sudo apt upgrade
```
更新が済んだら、必要なアプリをインストールします。
```bash:必要なアプリをインストール
userland@localhost:~$ sudo apt install iproute2 # IPアドレスの確認
userland@localhost:~$ sudo apt install nmap # ポート番号の確認
```
##### 4．現在ディレクトリを確認する
`pwd`と入力して、現在ディレクトリを確認しておきます。
UserLAndのターミナル上では、`/home/userland/`にいることが分かります。
```bash:現在ディレクトリの確認
userland@localhost:~$ pwd
/home/userland
```


### 【SSH接続の準備】
#### PC
##### 1．秘密鍵と公開鍵を作る
`ssh-keygen`と入力すると、現在ディレクトリ以下に、秘密鍵と公開鍵を作ることが出来ます。
秘密鍵とは、その名の通り**誰にも見せてはいけない鍵**で、通常`~/.ssh`フォルダに置くことが多いです。
公開鍵とは、**通信したい相手に渡す鍵**で、今回はDropboxを経由して渡します。

今回使う暗号化方式は「[エドワーズ曲線デジタル署名アルゴリズム - Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%89%E3%83%AF%E3%83%BC%E3%82%BA%E6%9B%B2%E7%B7%9A%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E7%BD%B2%E5%90%8D%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0)」というもので、 **「ed25519」** と指定します。


以下は、オプションの説明です。
- -tオプション: 暗号化方式を指定に使います。`ed25519`と指定します。
- -fオプション: 鍵に名前を付けます。今回はAndroidスマートフォンとの暗号化接続なので「id_ed25519_android」と名付けます。

まずは、`.ssh`フォルダを作成して、移動します。
```powershell:.sshフォルダを作成して、移動
PowerShell 7.4.1
PS C:\Users\user> mkdir .ssh

    Directory: C:\Users\user

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----   2024/02/04 日曜日    20:45                .ssh

PS C:\Users\user> cd .ssh
```
次に鍵を作成します。
今回はテストなので、パスフレーズの入力は省略します（何も入力せずEnter）。
```powershell:秘密鍵と公開鍵を作成する
PS C:\Users\user\.ssh> ssh-keygen -t ed25519 -f id_ed25519_android
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in id_ed25519_android
Your public key has been saved in id_ed25519_android.pub
The key fingerprint is:
SHA256:フィンガープリント ユーザー名@ホスト名
The key's randomart image is:
+--[ED25519 256]--+
|       イ        |
|       メ        |
|       ｜        |
|       ジ        |
|                 |
|                 |
|                 |
|                 |
|                 |
+----[SHA256]-----+
```



生成した鍵を確認します。
無事生成できた事がわかったら、
`.pub`という拡張子がついている方が公開鍵です。
```powershell:秘密鍵と公開鍵の確認
PS C:\Users\user\.ssh> ls
id_ed25519_android
id_ed25519_android.pub
```

##### 2．公開鍵をスマホに送る
送る手段は何でもいいです。今回はDropboxを使いました。Dropboxを通じて、スマートフォンのどこかに`id_ed25519_android.pub`を保存します。
今回はスマートフォンの「ダウンロードディレクトリ」に保存しておきます。

#### Androidスマートフォン
##### 1．authorized_keysに公開鍵を登録する
他のクライアントから受け取った公開鍵は全て、中身をauthorized_keysファイルにコピーして運用します。
そのため、まずはauthorized_keysとそれを保管する.sshフォルダを作成します。

ホームディレクトリ下に~/.sshを作って、パーミッションを700にします。
```bash:「/home/userland」に「.ssh」を作る
userland@localhost:~$ mkdir .ssh
userland@localhost:~$ chmod 700 .ssh
```
次に、.sshフォルダ内にauthorized_keysを作って、パーミッションは600にします。
```bash:「/home/userland/.ssh」にauthorized_keysを作る
userland@localhost:~$ touch .ssh/authorized_keys
userland@localhost:~$ chmod 600 .ssh/authorized_keys
```
Dropboxを経由して、ダウンロードフォルダに「id_ed25519_android.pub」に置いたことを確認した後、中身をauthorized_keysファイルに追記します。
`>`はリダイレクトを意味しており、二個重ねると追記となります。

```bash:authorized_keysに公開鍵を追記する
userland@localhost:~$ cat /Downloads/id_ed25519_android.pub >> ~/.ssh/authorized_keys
```

##### 2．IPアドレスを確認する
ip -4 aと入力するとIPアドレスが分かる。
- -4はIPv4のこと。
- aはaddress（住所）の略。

```bash:IPアドレス（ipv4）の確認
userland@localhost:~$ ip -4 a
```
コマンドを打つと、loとwlan0が出るので、**wlan0**のIPアドレスを確認する。
- loは「ローカルループバック」と呼ばれる自分自身を指すIPアドレス。常に127.0.0.1となる。
- wlan0は無線LANアダプタ.。inetと書かれている欄がIPアドレスとなる。

:::note warn
Android13から`cannot bind netlink socket: permission denied`と表示され、IPアドレスを確認することが出来ないそうです。
https://github.com/termux/termux-app/issues/2993
:::

##### 3．ポート番号を確認する
UserLAndは起動しただけでsshdが起動しているため、開いているポート番号を確認する。
```bash:ポート番号の確認
userland@localhost:~$ nmap localhost
Starting Nmap 7.80 ( https://nmap.org ) at 2024-02-08 07:31 UTC
Nmap scan report for localhost (127.0.0.1)
Host is up (0.0018s latency).
Not shown: 998 closed ports
PORT      STATE SERVICE
22/tcp    open  ssh
2022/tcp  open  down

Nmap done: 1 IP address (1 host up) scanned in 1.62 seconds
```

ポートは全部で1000個あるが、`Not shown: 998 closed ports`となり2つだけ閉じていないことが分かる。
開いているポート番号は`22`と`2022`であることが分かったので、メモをする。このうち、**2022を使います**。

IPアドレスが島の住所なら、ポートは島にたくさんある港であり、 **「このデバイスにSSH接続をしたいのであればこの2022番のポートを使ってください」** という意味になります。

###### SERVICEとは？

ちなみに、ポートの各項目の説明は以下の通り。
- PORT: 開いているポート番号
- STATE: ポートが開いているか、閉じているかの状態
- SEVICE: nmapがサービスの名前を自動で判断している

上記はSEVICEが「down」となっているが、この名前は[IANAが登録したサービス名](https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml)を参照している。

https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=down

上記のサイトを見ると、ポート番号が「2022」でプロトコルが「tcp」のサービス名を「down」と名付けている事がわかる。nmapをこれを元にSEVICEを決定している。

ちなみに、IANAとは「Internet Assigned Numbers Authority」の略[^4]です。

>  IANAは、南カリフォルニア大学情報科学研究所（ISI）のJon Postel教授が中心となって始めたプロジェクトグループで、 ドメイン名、 IPアドレス、 プロトコル番号など、 インターネット資源のグローバルな管理を行っていました。 
>
> （中略）
>
> その後、 1998年10月に国際的な非営利法人 ICANN が設立されてインターネットの管理体制が変化し、 2000年2月にはICANN、南カリフォルニア大学、 及びアメリカ政府の三者の合意により、 IANAが行っていた各種資源のグローバルな管理の役割は ICANNに引き継がれることになりました。 2002年現在IANAは、ICANNにおける機能の名称として使われています。
> 出典: [インターネット用語1分解説～IANAとは～ - JPNIC](https://www.nic.ad.jp/ja/basics/terms/iana.html) 


[^4]: [インターネット用語1分解説～IANAとは～ - JPNIC](https://www.nic.ad.jp/ja/basics/terms/iana.html) 

参考サイト
- [TCP22番ポートとは？SSH通信の基本概念を分かりやすく解説する | THE SIMPLE](https://the-simple.jp/what-is-tcp-port-22-an-easy-to-understand-explanation-of-the-basic-concepts-of-ssh-communication)
- [openssh - After I switch default SSH ports, why does NMAP display port service as "down" - Super User](https://superuser.com/questions/722622/after-i-switch-default-ssh-ports-why-does-nmap-display-port-service-as-down)
- [Service Name and Transport Protocol Port Number Registry](https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=ssh)



### 【SSH接続開始】

#### PC
UserLAndを起動したことでポートが開放され、さらに公開鍵をスマートフォンに送りauthorized_keysへの登録も完了したので、いよいよSSH接続を開始できます。

SSH接続をする書式は以下の通りです。IPアドレスには、`ip -4 a`で調べたIPアドレスを入力してください。
```powershell:SSH接続開始の書式
PS C:\Users\user\.ssh> ssh -p ポート番号 -i 使用する秘密鍵 userland@IPアドレス
```

しかし、ここで一つ注意点があります。上記のコマンドのようにPowershellでSSH接続しようとすると、以下のような表記が出てタイムアウトになります。

```powershell:スマートフォンにSSH接続をしようとするが、タイムアウトになる
PS C:\Users\user\.ssh> ssh -p 2022 -i id_ed25519_android userland@IPアドレス
ssh: connect to host IPアドレス port 2022: Connection timed out
```

ここで、**Git Bash**を使うことになります。
powershell上で`bash`と入力すると、`ユーザー名@PC名 MINGW64 ~$`に移行します。
```powershell:Git Bashに移行
PS C:\Users\user> bash

user@PC名 MINGW64 ~
$
```
ここで同じようにコマンドを入力すると、以下のように接続できます。
また、初めて接続すると以下のようにフィンガープリントが提示され、本当に接続していいかと聞かれるので、「yes」と入力したください。

```bash:スマートフォンにSSH接続をする
user@PC名 MINGW64 ~
$ ssh -p 2022 -i id_ed25519_android IPアドレス
The authenticity of host '[IPアドレス]:2022 ([IPアドレス]:2022)' can't be established.
ECDSA key fingerprint is フィンガープリント.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[IPアドレス]:2022' (ECDSA) to the list of known hosts.
userland@localhost:~$ 
```

一度接続すると、フィンガープリントは`~/.ssh/known_hosts`ファイルに保存され、次回移行の接続からは何も聞かれなくなります。


接続するとパソコンのターミナル上でAndroidを操作出来るようになります。
SSH接続をやめるには`exit`コマンドを打ちます。
試しに、dowloadsディレクトリに「test.txt」というファイルを作成します。


```shell:パソコンからAndroidを操作する
$  ssh -p 2022 -i id_ed25519_android userland@IPアドレス
userland@localhost:~$ whoami
userland
userland@localhost:~$ pwd
/home/userland
userland@localhost:~$ cd /Downloads
userland@localhost:/Downloads$ touch test.txt
userland@localhost:/Downloads$ exit
logout
Connection to IPアドレス closed.
```


#### Androidスマートフォン

パソコンから作成した「test.txt」があるかをUserLAndで調べます。

```bash:「test.txt」があるかをUserLAndで調べる
userland@localhost:~$ pwd
/home/userland
userland@localhost:~$ find /Downloads/test.txt
/Downloads/test.txt
```

きちんと「ダウンロード」フォルダ以下に作られていることが分かります。




## まとめ

これでパソコンからAndroidスマートフォンにSSH接続することができます。以前は「[Termux](https://play.google.com/store/apps/details?id=com.termux&hl=ja&gl=US)」を使用していましたが、Playストアで更新できなくなって久しいため、「[UserLAnd](https://play.google.com/store/apps/details?id=tech.ula)」を使ってSSH接続する方法をあらためてまとめました。

以前の記事は以下からご覧ください。

https://qiita.com/yusu79/items/acea3f7dc306ce83e7f1

今回は手間を省く為に鍵のパスフレーズを作りませんでしたが、実際の運用では作った方が良いです。

SSH接続が出来たことでscpやsftpもスマホとパソコン間で行えるようになります。