WindowsにVPNクライアントを入れずにVPN先のサーバーにRemoteSSHする

Windowsにクライアントソフト(exe)を入れずにVPNの対向サーバーにSSHする方法を解説します
※Windows側に不要なNICは一切作成されません

## 前提条件

- Windowsのバージョン
  - x64 システムの場合: バージョン 1903 以降 (ビルド 18362.1049 以降)

- WSL2のセットアップ
  - Windowsの機能の有効化
    WSLと仮想マシンプラットフォームを有効にする

    ```ps1
        dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
        dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
    ```

  - Linux カーネル更新プログラム パッケージをダウンロードする

    [x64 マシン用 WSL2 Linux カーネル更新プログラム パッケージ](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi)

  - ディストリビューションをインストールする
    - Ubuntu22.04のインストール

    ```ps1
        wsl.exe --install -D Ubuntu-22.04
    ```

    - インストールが完了するとユーザー名とパスワードを聞かれるので設定する

## SoftEther VPN Clientのインストール

- クライアントのダウンロード
  - 以下のダウンロードページから対応するOS、アーキテクチャを選択してリンクをコピーする

    [SoftEther VPN ダウンロード](https://ja.softether.org/5-download)

  - wgetコマンドでWSL上にダウンロードする
    - 以下は例として示す（リンクは適宜変更してください）

      ```sh
      wget https://jp.softether-download.com/files/softether/v4.43-9799-beta-2023.08.31-tree/Linux/SoftEther_VPN_Client/64bit_-_Intel_x64_or_AMD64/softether-vpnclient-v4.43-9799-beta-2023.08.31-linux-x64-64bit.tar.gz
      ```

  - ダウンロードしたファイルを展開する
    - tarコマンドで展開する（ファイル名は適宜変更してください）

      ```sh
      tar -zxvf ./softether-vpnclient-v4.43-9799-beta-2023.08.31-linux-x64-64bit.tar.gz
      ```

- クライアントのビルド
  - 事前準備
    - 最新リポジトリへ更新、および必要なパッケージを入手する

    ```sh
    sudo apt update
    sudo apt upgrade
    sudo apt install make gcc
    ```

  - ビルド

    ```sh
    cd ./vpnclient
    make
    ```

- クライアントのインストール
  - ビルドした成果物を適切な場所へ展開、および権限付与をする

    ```sh
    sudo mv ./vpnclient /usr/local
    sudo chown root:root /usr/local/vpnclient
    cd /usr/local/vpnclient
    sudo chmod 600 *
    sudo chmod 700 vpncmd
    sudo chmod 700 vpnclient
    ```

- クライアントサービスの作成
  - systemdユニットファイルを作成してクライアントを常駐させる

    ```sh
      sudo vim /etc/systemd/system/vpnclient.service
    ```

  - ユニットファイルの構成

    ```conf:vpnclient.service
    [Unit]
    Description=SoftEther VPN Client
    After=network.target network-online.target

    [Service]
    ExecStart=/usr/local/vpnclient/vpnclient start
    ExecStop=/usr/local/vpnclient/vpnclient stop
    Type=forking
    RestartSec=3s

    [Install]
    WantedBy=multi-user.target
    ```

  - サービスデーモン登録＆起動

    ```sh
    sudo systemctl daemon-reload
    sudo systemctl enable vpnclient.service
    sudo systemctl start vpnclient.service
    ```

### クライアントの設定

- `/usr/local/vpnclient/vpncmd`を使用してクライアントの設定を行う

  ```sh
  cd /usr/local/vpnclient
  sudo ./vpncmd
  ```

  > By using vpncmd program, the following can be achieved.
  >
  > 1. Management of VPN Server or VPN Bridge
  > 2. Management of VPN Client
  > 3. Use of VPN Tools (certificate creation and Network Traffic Speed Test Tool)
  >
  > Select 1, 2 or 3:

  クライアントの設定を行うため2を入力

  > Specify the host name or IP address of the computer that the destination VPN Client is operating on.
  > If nothing is input and Enter is pressed, connection will be made to localhost (this computer).
  > Hostname of IP Address of Destination:

  自身のホスト上のクライアントの設定のためそのままEnterで続行

  仮想HUBに接続するための仮想NICを作成します。

  ```sh
  VPN Client> NicCreate <仮想NIC名>
  ```

  接続用のアカウントを登録します

  ```sh
  VPN Client> AccountCreate <接続名>

  AccountCreate command - Create New VPN Connection Setting
  Destination VPN Server Host Name and Port Number: <サーバーのホスト名:ポート>

  Destination Virtual Hub Name: <サーバーの仮想HUB名>

  Connecting User Name: <サーバーで発行したユーザー名>

  Used Virtual Network Adapter Name: <仮想NIC名>
  ```

  接続用アカウントにパスワードを設定します。認証方式はstandardを指定。

  ```sh
  VPN Client> AccountPasswordSet <接続設定名>

  AccountPasswordSet command - Set User Authentication Type of VPN Connection Setting to Password Authentication
  Please enter the password. To cancel press the Ctrl+D key.

  Password:　<サーバーで設定したパスワード>
  Confirm input: <確認でもう一度入力>

  Specify standard or radius: standard
  ```

  作成したアカウント設定をスタートアップに設定します。

  ```sh
  VPN Client> AccountStartUpSet <接続名>
  ```

  vpncmdから抜けます。

  ```sh
  VPN Client> exit
  ```

- 仮想NICが作成されていることを確認します

  ```sh
  networkctl
  ```

  > IDX LINK            TYPE     OPERATIONAL SETUP
  > 1 lo              loopback carrier     unmanaged
  > 2 ens18           ether    routable    configured
  > 4 vpn_vpn         ether   no-carrier   unmanaged
  
  ※仮想NIC名のLinux上のNIC名はLowerCaseになります

- netplanを使用して仮想NICのネットワーク設定をします

  - コンフィグファイルの作成
    
    1. /etc/netplan/10_vpn.yamlを作成して以下のように編集
    
        ```conf:10_vpn.yaml
        network:
          ethernets:
            vpn_vpn: # 仮想NIC名
              dhcp4: true
          version: 2
        ```
    
    1. パーミッションを設定
    
        ```sh
        sudo chmod 600 /etc/netplan/10_vpn.yaml
        ```
    
    1. 設定の反映を行う
    
        ```sh
        sudo netplan apply
        ```

  - サービスデーモン登録＆起動

    ```sh
    sudo systemctl daemon-reload
    sudo systemctl enable vpnclient.service
    sudo systemctl start vpnclient.service
    ```

- オプション：ルート設定
  - 割り当てられたIPアドレスのセグメント以外にも対向側にセグメントが存在する場合はWSLのルートテーブルを編集する必要があります
  ※netplanのコンフィグファイルのroute設定を利用

## Remote SSH の設定

### Remote SSH について

- Windows上にインストールしたVSCodeの拡張機能「Remote SSH」から対向ネットワーク上のサーバー等に対してSSHができるように設定する
- Remote SSHの挙動としてはWindowsがSSHクライアントとなって接続するためそのままでは対向ネットワークに対してのアクセスができない。そのためWSLをSSHの踏み台サーバーとして利用して対向ネットワークのサーバーにSSHをする

### Windows側の設定

- SSHキーペアを作成していない場合は`ssh-keygen`でキーペアを作成する
  - 公開鍵はあらかじめ控えておく
- SSHコンフィグファイルを作成して踏み台サーバー経由の接続設定をする
  - `~/.ssh/config`ファイルを以下のように編集する

    ```conf:~/.ssh/config
    Host wsl-server
        HostName localhost
        Port 22
        User <WSLのユーザー名>
        IdentityFile ~\.ssh\id_rsa
        ForwardAgent yes

    Host dev-server
        HostName <対向サーバーのアドレス>
        Port 22
        User <対向サーバーのユーザー名>
        IdentityFile ~\.ssh\id_rsa
        ProxyCommand ssh -W %h:%p wsl-server
    ```

### WSL側の設定

- OpenSSHサーバーをインストールする

  ```sh
  sudo apt install openssh-server
  ```

- 認証情報を設定する

  ```sh
  mkdir ~/.ssh
  echo <Windowsで控えた公開鍵> >> ~/.ssh/authorized_keys
  chmod 700 ~/.ssh
  chmod 600 ~/.ssh/authorized_keys
  ```

- WSL上のSSHサーバーは明示的にWindows側でポート転送およびファイアウォール通過設定をしない限り外部には公開されないためルートログインやパスワード認証は許可のまま設定する
  - セキュリティをより高めたい場合は以下の設定を行ってください
    - `/etc/ssh/sshd.config`でルートログインおよびパスワード認証の禁止
    - `iptables`を用いたファイアウォールの設定

### 対向サーバーの設定

- 前提条件
  - SSHサーバーが設定済み

- 認証情報の設定
  - 対向サーバーの`~/.ssh/authorized_keys`にWindowsの公開鍵を登録します
    - ※WSLは踏み台として使うため登録するのはWindowsの公開鍵となります。

    ```sh
    echo <Windowsで控えた公開鍵> >> ~/.ssh/authorized_keys
    ```

## 接続

- VSCodeのRemote SSH拡張機能よりdev-serverを選択してSSH接続します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1738478/217f4c88-409b-9ca7-c369-17528a5148dd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1738478/fc91ecfb-75ff-629a-e846-aa72df456d71.png)


## 応用（RDP over SSH）

- SSHのローカルフォワード機能を利用して対向サーバーからみえる任意のサーバーをフォワーディングすることができます
- 以下はRDP（リモートデスクトップ）をSSH越しに使う例です

  ```conf:~/.ssh/config
  Host ssh-rdp
      HostName <対向サーバーのアドレス>
      Port 22
      User <対向サーバーのユーザー名>
      IdentityFile ~\.ssh\id_rsa
      ProxyJump wsl-server
      LocalForward <転送するポート> <RDPしたいサーバーのアドレス>:3389
  ```

接続する際はlocalhost:<転送するポート>でアクセスできます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1738478/8fe81ab6-1f42-cadc-bbfa-bc79b9deddf5.png)