ブラウザからターミナル操作ができるWeTTY構築手順

こんばんは。torippy1024です。

本日は、SSH外部アクセスができず、外部アクセスがHTTPSしか許可されていないような環境下で、HTTPSアクセスによってターミナル操作を許可するための環境構築手順について書いてみます。
(HTTPS/443以外の別ポートを指定してアクセスすることも可能です)

### 【1】構成図

![スクリーンショット 2025-03-26 0.42.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684500/8918d600-f315-4f73-b64a-012cce8381ae.png)

構成図は上記の通りです。
踏み台サーバー(Jump Server)にDockerをインストールし、Docker上のコンテナとしてWeTTYを実行させます。
WeTTYは、ブラウザ上でターミナルを実行するアプリケーションです。
バックエンドではNode.jsが動作しており、ブラウザ上でターミナルコマンドを実行すると、WebSocketを通じてリアルタイムでやり取りします。
ローカルホストだけでなく、リモートホストに接続することも可能です。
(今回は、Docker上のWeTTYからローカルホストのシェルを表示させ、そこからリモートホストにSSH接続させる構成にしています)


### 【2】EC2払い出し

今回使用するサーバーはAWS EC2 * 2サーバーです。
どちらもサイズは小さくて問題ありません。私が検証した時はt2.microでも動作しました。
(ただ、多数のユーザーで同時ログインして負荷の高い作業などの使い方をすると問題が発生するかもしれません)

踏み台サーバー側のみ、パブリックIPを割り当てておく必要があります。
またセキュリティグループについても、それぞれ適切な方向の適切なポートを解放しておく必要があります。わざわざ表にするまでもないかもしれませんが以下の通りです。

|セキュリティグループ名|適用先|通信方向|接続許可ポート|接続元|
|---|---|---|---|---|
|sg-jumpserver|踏み台サーバー|インバウンド|443(HTTPS)|0.0.0.0(自分の端末のみからアクセスする時など、IPアドレスを明確にできる場合は限定させることも可)|
|(上と同じ)|(上と同じ)|インバウンド|22(SSH)|xx.xx.xx.xx(wettyの接続先ローカルホストを、自分自身のIPアドレスで指定する必要があるため、踏み台サーバーのIPアドレスから自分自身への接続を許可しておく。踏み台サーバーの中にプライベートアドレスがあれば、それを指定することで設定は不要)|
|sg-remoteserver|リモートサーバー|インバウンド|22(SSH)|xx.xx.xx.xx(踏み台サーバーのIPアドレス)|

### 【3】踏み台サーバーへのWeTTY構築

#### dockerとWeTTYのインストール

dockerとwettyをインストールします。
検証環境なので、あまり深く考えずrootで実行してしまっています。
```
sudo yum -y install docker
sudo systemctl start docker
sudo docker pull wettyoss/wetty
```

#### 自己証明書の作成

WeTTYは、デフォルトではHTTP接続になります。インターネットから操作する際、さすがに平文はまずいので、HTTPS化するための自己署名証明書も作成しておきます。
作成した鍵(mykey.pem)と証明書(mycert.pem)は/etc/ssl/配下に移動させておきます。CSRは特に使用しないので放置してしまいました。
```
sudo yum -y install openssl
openssl genrsa -out mykey.pem 2048
openssl req -new -key mykey.pem -out mycsr.pem -subj '/C=JP/ST=Tokyo/L=Chiyoda/O=Example Corp/OU=IT/CN=localhost/emailAddress=admin@example.com'
openssl x509 -req -days 365 -in mycsr.pem -signkey mykey.pem -out mycert.pem
sudo mv mykey.pem /etc/ssl/
sudo mv mycert.pem /etc/ssl/
```

#### dockerの実行

自己署名証明書の作成が終わったらdockerを実行します。
またまたrootで実行してしまっていますが、まあ使い捨ての環境なので気にしないことにします。

```
sudo docker run -d -p 443:3000 -v /etc/ssl/mycert.pem:/ssl/mycert.pem -v /etc/ssl/mykey.pem:/ssl/mykey.pem wettyoss/wetty --ssl-cert=/ssl/mycert.pem --ssl-key=/ssl/mykey.pem --ssh-host=xx.xx.xx.xx
```

ちなみに、接続先をローカルホストにする場合でも、--ssh-hostオプションの値にlocalhostと入れてはいけません。IPアドレスを指定します。その理由は、dockerコンテナにとっての接続先を--ssh-hostオプションで指定するため、localhostと入れてしまうとdockerコンテナがローカルホストでなく自分自身を宛先にしてしまい、ターミナルコマンドを転送することができなくなるためです。

作成したコンテナを削除する時は以下のコマンドを使用します。
```
sudo docker ps -a
(表示されたコンテナIDを確認)
sudo docker stop <コンテナID>
```

### (EC2へのパスワード認証ログインを許可していない場合の作業)
AWS上でEC2を作成する際にパスワード認証ログインを許可しておらず、キーペアによる認証のみを許可した場合、少なくとも踏み台サーバーに対してはec2-userにパスワード認証を許可するよう設定変更を行う必要があります。

ec2-userのパスワードを変更
```
sudo passwd ec2-user
(passwordを入力)
```

PasswordAuthenticationの有効化
```
sudo vi /etc/ssh/sshd_config
PasswordAuthenticationをyesに変更
—
PasswordAuthentication yes
—
```

sshdの再起動
```
sudo systemctl restart sshd
```

### SSHログイン確認
ブラウザにて、以下URLにアクセスしてログインプロンプトが表示されれば成功です。(自己署名証明書なので、アクセス時警告が表示されます)
実際にユーザー名とパスワードを入力し、踏み台サーバーにログインできることまで確認しましょう。
```
https://xx.xx.xx.xx/wetty
```

![スクリーンショット 2025-03-26 11.20.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684500/bb9ee4e6-2243-4a77-828d-5be8c7b71e4d.png)

その後、踏み台サーバーからリモートサーバーにSSHできることを確認すれば成功です。
```
ssh ec2-user@yy.yy.yy.yy
```

### 参考(というか本家サイト)

WeTTY = Web + TTY
https://butlerx.github.io/wetty/#/

wettyoss/wetty
https://hub.docker.com/r/wettyoss/wetty

最初はDocker版でなくWeTTYを使用しようとしたのですが、導入に時間がかかったのでDocker版を試してみたところすぐインストールできました。
使うのであればDocker版をお勧めします。

以上です。