Ubuntu Server 20.04.3 でDDNSによる変動IPでも外部アクセス可能なSSH環境構築

# Ubuntu ServerでのSSH環境構築

自宅サーバ構築時、回線契約の関係で変動IPアドレスとなっている場合でも、外部からアクセス可能な環境を構築する方法のメモ

流れとしてはGoogle domainからddns（ダイナミックDNS）を利用し、IPアドレスを固定することで環境を構築する。IPv4 over IPv6等の契約ではルータにより使用できるポートに制約がある為、よく確認してポートを選択することが推奨されます。

注）本構築方法は、Googleでのドメインが必要となるため、環境構築に最低限の料金が発生します。

## 構築手順

### OSインストール (Ubuntu Server 20.04.3)

```
Use UP, DOWN and ENTER keys to select your language.
   [ Asturianu        > ]
   [ ...              > ]
   [ ...              > ]
   [ English          > ]
   [ English (UK)     > ]
   [ ...              > ]
   [ ...              > ]
```

`[ English          >]` を選択する。
バージョンやJA版で日本語を選択すると表示がバグることがある。

```
Please select your keyboard layout below, or select "Identify keyboard" to detect your layout automatically.

      Layout:  [ Japanese                ▼ ]

     Variant:  [ Japanese         ▼ ]

                            [ Identify keyboard ]  
```

`Japanese`キーボードのレイアウト設定する。

```
Configure at least one interface this server can use to talk to other machines, and which preferably provides sufficient access for updates.

   NAME    TYPE  NOTES
 [ enp2s0  eth   -              ▼ ]
   DHCPv4  192.0.2.2/24
   00:00:5e:00:53:00 / xxxxxxxx xxxxxxx / xxxxxxx xxxx Gigabit Ethernet Controller

 [ Create bond > ]
```

IP固定に関してはルータで行う場合DHCPでネットワーク接続を行う。

固定で設定したい場合はここで設定しておく。

```
If this system requires a proxy to connect to the internet, enter its details here.

Proxy adderss:  ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                If you need to use a HTTP proxy to access the outside world, enter the proxy information here. Otherwise, leave this bland.

                The proxy information should be given in the standard form of "http://[[user][:pass]@]host[:port]/".
```

`Enter`でそのまま進める。

```
If you use an alternative mirror for Ubuntu, enter its details here.

Mirror address:  http://jp.archive.ubuntu.com/ubuntu
                 You may provide anarchive mirror thatwill be used instead of the default.
```

jpサーバからミラーを行う。

```
Configure a guided storage layout, or create a custom one:
(X)  Use an entire disk
     [ md126                                        xxxxx  500.0G ▼ ]
     ( )  Set up this disk as an LVM group
          [ ]  Encrypt the LVM group with LUKS
                       Passphrase:

               Confirm passphrase:

     (X)  Custom storage layout
```

カスタムストレージを選択する。

特にメモリ周りをいじる場合、以下を参考にカスタムしてください。

使用したSSDはSamsung 850 EVO 500GBとなります。

```
FILE SYSTEM SUMMARY
  MOUNT POINT   SIZE      TYPE      DEVICE TYPE
[ /              393.89G  new ext4  new partition xxxxx > ]
[ /boot          32.000G  new ext4  new partition xxxxx > ]
[ /boot/efi     512.000M  new fat32 new partition xxxxx > ]
[ swap           32.000G  new swap  new partition xxxxx > ]

AVAILABLE DEVICES
...

USED DEVICES
...


                            [ Done      ]
                            [ Reset     ]
                            [ Back      ] 

```

パーティション設定が完了したら`Done`を選択。

```
                     Confirm destruction action

 Selecting Continue below will begin the installation process and
 result in the loss of data on the disks selected to be formatted.

 You will not be able to return to this or a previous screen once the
 installation has started.

 Are you sure you want to continue?

                            [ No        ]
                            [ Continue  ]
```

本当にディスクに書き込んでいいのかを確認されるので、`Continue`を選択する。

```
Profile setup                                                        [ Help ]

Enter the username and password you will use to log in to the system. You can
configure SSH access on the next screen but a password is still needed for
sudo.

             Your name: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

    Your server's name: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                        The name it uses when it talk to other computers.

       Pick a username: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

     Choose a password: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

 Confirm your password: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■



                            [ Done      ]
```

各項目を入力して`Done`を選択する。設定したユーザはsudoユーザとなります。

```
SSH Setup                                                           [ Help ]

You can choose to install the OpenSSH server package to enable secure remote
access to your server.

                 [X]  Install OpenSSH server

Import SSH identity:   [ No           ▼ ]
                       You can import your SSH keys from GitHub or Launchpad.

    Import Username:
                 [ ]  Allow password authentication over SSH



                            [ Done      ]
                            [ Back      ] 
```

※`Import SSH identity`を`yes`とすることで、githabのアカウント等で登録されている公開鍵を読み込ませることができます。

この後は必要に合わせて、インストールするスナップを選択することができる。後からでも入れれるため、サーバ自体のセットアップを優先する場合、特に選択せずに`Done`すればよい。

`Installing system`でログが表示されるため、完了するまで待つ。

```bash
Please remove the installation medium, then press ENTER:
```

以上の表示がされたらインストール用のUSBを外し、`ENTERキー`を押す。

これで再起動されて、サーバが立ち上がる。

ここからはOpenSSHの設定がなされている場合、ローカル環境のssh接続でのヘッドレスサーバ扱いが可能です。

注）これ以降の設定でポート設定にて間違えるとサーバへのアクセスができなくなることがあります。

### SSH鍵の生成と登録

SSHによるサーバへのアクセスは鍵認証により行います。

ローカルのパソコンにてSSHの鍵を生成する。

```
$ ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/<local_username>/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase): 
Enter same passphrase again:
Your identification has been saved in /home/<local_username>/.ssh/id_ed25519
Your public key has been saved in /home/<local_username>/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa <local_username>@<servername>
The key's randomart image is:
+--[ED25519 256]--+
|    . ...        |
|   ... ..        |
|  .. .. .        |
| .. .. . .       |
|. . . . . .      |
|.  . . . .       |
| .  . .          |
|  . ..           |
|  .. .           |
+----[SHA256]-----+
```

生成された鍵が`/home/<local_username>/.ssh/id_ed25519.pub`にできるので中身を、サーバの`/home/<username>/.ssh/authorized_keys`に入力します。

```bash
$ nano .ssh/id_ed25519.pub

ssh-ed25519 AAAAbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb <local_username>@<servername>
```

これにより鍵認証でのアクセスができるようになります。

### サーバサイドのSSH設定・ポート開放設定

初期セットアップが完了したサーバへログインする。

サーバに設定したusernameとローカルIPアドレスを入力する。

```bash
$ ssh <username>@192.0.2.2
```

```bash
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-136-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of San 01 Jan 2023 00:00:00 PM UTC        

  System load:             0.0
  Usage of /:              2.7% of 393.89GB
  Memory usage:            1%
  Swap usage:              0%
  Temperature:             99.0 C
  Processes:               99
  Users logged in:         0
  IPv4 address for enp2s0: 192.0.2.2
  IPv6 address for enp2s0: 2001:0db8:0000:0000:0000:0000:0000:0002


0 updates can be applied immediately.

New release '22.04.1 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
```

ログイン後にはアップデートを行っておく。

```bash
$ sudo apt update 
$ sudo apt upgrade
```

SSHポート番号を変更する場合、設定ファイルを変更する。

```bash
$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.old     # 設定ファイルのバックアップする。
$ sudo nano /etc/ssh/sshd_config                            # 設定ファイルを編集する。

Port XXXXX ← 22から任意のポートに変更（例:30022）

$ sudo sshd -t                                              # 設定ファイルの構文を確認する。
$ sudo service sshd restart                                 # 設定を反映する。
```

必要なSSHポート以外をクローズドし、必要なポートを開放する。

```bash
$ sudo ufw default deny                                     # 他のポートをクローズドする。
$ sudo ufw allow <ssh port default 22>                      # SSHのポートを開放する。
$ sudo ufw enable
$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
22                         ALLOW       Anywhere
22 (v6)                    ALLOW       Anywhere (v6)
```

`<ssh's port default 22>`はデフォルトでは22番となる為、22を指定すればよい。

セキュリティ的に他のポートを指定した場合は`<ssh's port default 22>`に任意の数字を入れてください。

### ダイナミックDNSの設定

[Google domain](https://domains.google/intl/ja_jp/)によるサービスを利用して、DDNS（ダイナミックDNS）を設定し、変動IPアドレスとドメイン名を紐づけする。

マイドメインから`DNS`を選択する。

ページの一番下の`詳細設定を表示`から`ダイナミック DNSの管理`を選択する。

左下の`新しいレコードを作成`をクリックして追加する。必要なホストネーム等を追加しておく（例：www、mailなど）。

設定が完了したら`保存`し、`ご利用のドメインではダイナミック DNS が設定されています`を確認します。

設定がうまく完了すると以下のようにリストがサイト上で表示されます。（リストは空白、wwwを登録したものの例です。）

|ホスト名|タイプ|TTL|データ||
|:---|:---:|:---:|:---:|:---:|
|[sample.com]()|A|1分|0.0.0.0|[認証情報を表示]()|
|[www.sample.com]()|A|1分|0.0.0.0|[認証情報を表示]()|

表示すると`認証情報を表示`をクリックすると、ダイナミック DNS の認証情報が表示されるため、各ホスト名の`ユーザー名`、`パスワード`を記録しておく。

ここからサーバにログインして実行する。

ddclientをインストールする。

```bash
$ sudo apt install -y ddclient
```

インストール中は設定ウィザードが表示されるが、Google Domain用の設定ができないため、後から必要な設定ファイルを直接編集する。

```
                                      Configuring ddclient

Please select the dynamic DNS service you ar using. if the servuce you use is not listed, choose "other"
and you will be asked for the protocol and the server name.

Dynamic DNS service provider:

                                       www.dyndns.com
                                       www.easydns.com
                                       www.dslreports.com
                                       www.zoneedit.com
                                       other

                                             <Ok>
```

`other`を選択する。

```
                                      Configuring ddclient

Please enter the name of the server which is providing you with dynamic DNS service (example:
member.dyndns.org).

Dynamic DNS server:

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

                                             <Ok>
```

何も入れずに`<Ok>`を選択する。

```
                                      Configuring ddclient

Please select the dynamic DNS update protocol used by your dynamic DNS service provider.

Dynamic DNS update provider:

                                           dyndns2
                                           dslreports1
                                           easydns
                                           hammernode1
                                           zoneedit1
                                           dyndns1

                                             <Ok>
```

`dyndns2`を選択する。

```
                                      Configuring ddclient

Please enter the username to use with the dynamic DNS service.

Username for dynamic DNS service:

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

                                             <Ok>
```

何も入れずに`<Ok>`を選択する。

```
                                      Configuring ddclient

Please enter the password to use with the dynamic DNS service.

Password for dynamic DNS service:

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

                                             <Ok>
```

何も入れずに`<Ok>`を選択する。

```
                                      Configuring ddclient

Please enter your dynamic DNS service password again to make sure you
typed it correctly.

Re-enter password to verify:

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

                                             <Ok>
```

何も入れずに`<Ok>`を選択する。

```
                                      Configuring ddclient

Please enter the name of the network interface (eth0/wlan0/ppp0/...) to
use for dynamic DNS service.

Network interface used for dynamic DNS service:

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

                                             <Ok>
```

何も入れずに`<Ok>`を選択する。

```
                                      Configuring ddclient

Please enter the list of fully qualified domain names for the local
host(s) (for instance, "myname.dyndns.org" with only one host or
"myname1.dyndns.org,myname2.dyndns.org" for two hosts).

DynDNS fully qualified domain names:

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

                                             <Ok>
```

何も入れずに`<Ok>`を選択する。

ウィザードが終了したら、ddclientの設定ファイルを修正する。

```bash
$ ln -s /etc/ddclient.conf ddclient.conf                # ホームディレクトリにリンクを置いておく場合に実行する
$ sudo name /etc/ddclient.conf
```

ddclient.confの中に以下の記述する。

Googleドメインのサイトでメモをしたユーザ名を`<generated_username1>`に、パスワードを`<generated_password1>`に入力する。最後に該当するドメイン名を記述する。

複数のホスト名を登録する際は列挙して記述すればよい。

60秒ごとにGoogleに通知させるため、IPがずれていても1分で修正される設定となっている。

```bash
daemon=60

ssl=yes
protocol=googledomains
login=<generated_username1>
password=<generated_password1>
sample.com

ssl=yes
protocol=googledomains
login=<generated_username2>
password=<generated_password2>
www.sample.com
```

デーモン（サーバ起動時のバックグラウンド実行）として動作させる設定を行う。

```bash
$ sudo nano /etc/default/ddclient
```

run_ipupをfalseに、run_daemonをtrueに変更する。

```bash
run_dhclient="false"
run_ipup="false"
run_daemon="true"
daemon_interval="60"
```

デーモンを起動させる。

```bash
$ sudo service ddclient restart
```

### ルータの設定

購入したルータの機種によって設定が異なる為、各メーカーそれぞれで調べることを推奨します。一部のルータではセットアップができない場合があります。

また自宅の回線契約によって細かな設定が必要となったり、外部からのアクセスが難しい場合があります。

IPv6が導入が進んでおり、多くの回線契約がIPv4 over IPv6となっていても可能です。

#### 主なルータの設定事項

* PPPoEブリッジ ON にする。

    インターネット通信での一部機能のサポート。

* ポートマッピング設定を行う。（対象のインターフェースはWAN）

    `LAN側ホスト`にサーバのローカルIPである192.168.1.xxxを入力する。

    `プロトコル`はTCP指定する。

    `変換対象ポート`は外部からのポートであるため、サーバのSSHで解放したポートか、任意のポートを指定する。

    `宛先ポート`はSSHで利用しているポートを入力する。デフォルトのままなら22を指定する。変更している場合はSSHで解放したポートを指定すること。
 
* DHCP固定割り当て設定を行う。（MACアドレスとローカルIPを固定する）

    サーバのMACアドレスを調べておく。（ipコマンド）

    `link/ether 00:00:5e:00:53:00 brd ff:ff:ff:ff:ff:ff`部分の`00:00:5e:00:53:00`がMACアドレスとなる。

    IPアドレスは任意のアドレスを入力する。（例：`192.0.2.2`）

```bash
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:00:5e:00:53:00 brd ff:ff:ff:ff:ff:ff
    inet 192.0.2.2/24 brd 192.0.0.255 scope global enp2s0
       valid_lft forever preferred_lft forever
    inet6 2001:0db8:0000:0000:0000:0000:0000:0002/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 100sec preferred_lft 100sec
    inet6 2001:db8::2/64 scope link
       valid_lft forever preferred_lft forever
```

## 接続テスト

### ddclientの動作確認

ddclientでうまくIP情報をGoogleに通知できているどうかを確認するには、[Google domain](https://domains.google/intl/ja_jp/)から現在のIPアドレスが一致しているかを確認する。

|ホスト名|タイプ|TTL|データ||
|:---|:---:|:---:|:---:|:---:|
|[sample.com]()|A|1分|203.0.113.2|[認証情報を表示]()|
|[www.sample.com]()|A|1分|203.0.113.2|[認証情報を表示]()|

もともと0.0.0.0であったものが、自身のIPアドレス（例：203.0.113.2）となっていればよい。なっていない場合、ddclient周りの設定に誤りがある可能性がある為、再確認が必要となる。

### ローカルIPでもセットアップ確認

ローカルIPのスキャンし、ルータで指定したIPが正常に通信可能であるかを確認する。

```bash
$ seq -f "192.168.1.%g" 254 | xargs -P256 -n1 ping -s1 -c1 -W1 2>/dev/null | grep ttl
9 bytes from 192.0.2.1: icmp_seq=1 ttl=64
9 bytes from 192.0.2.2: icmp_seq=1 ttl=128
9 bytes from 192.0.2.3: icmp_seq=1 ttl=128
```

ここで正常に通信できていない、指定したIPをうまく使用していない場合、ルータとサーバを再起動することで正常に復帰する場合があります。

### SSHでのアクセス

`<sshport>`はルーターで指定した外部からアクセスできるポートを指定する。（ルータとサーバが異なる場合注意してください）

`<username>`はサーバのユーザ名を指定する。

`sample.com`はgoogle domainの自身のドメイン名を使用する。

```bash
$ ssh -p <sshport> <username>@sample.com
```

これによりアクセスができたら完成です。お疲れ様でした。

## その他メモ

ダイナミックDNSを利用することで外部アクセスが可能となる為、利便性が高いですが、回線やルータ機能によりうまく利用できない場合があります。その場合は外部VPN（例：Hamach等）を利用してセットアップすることで、代替することができることがあります。

WindowsではWSLやTeraTerm等のアクセス環境を整えることで、コマンドラインによるSSHコマンドを実行できます。

## 参考

1. [Ubuntu Server 20.04 LTSをインストールする](https://zenn.dev/hatotk/articles/install-ubuntu-server-20-04-lts)
1. [SSH認証に最強の「Ed25519鍵」を使おう](https://linuxfan.info/ssh-ed25519)
1. [SSHのポート番号を変更 - SSHサーバーの設定](https://webkaru.net/linux/change-ssh-port/)
1. [DNSSEC と DNS のセキュリティを設定する](https://support.google.com/domains/answer/6147083?authuser=0&hl=ja
)
1. [ddclientでGoogle DomainsのDDNSを更新する方法](https://www.uchidigi.com/2020/01/ddclient-google-ddns.html)
1. [IPv4 over IPv6とは何か？IPoE接続、PPPoE接続についても解説](https://biz.nuro.jp/column/025/)
1. [Ubuntu20.04 LogMeIn Hamachiを使ってみる](https://rohhie.net/ubuntu20-04-try-using-logmein-hamachi/)
1. [ドキュメントで例に使えるIPアドレスまとめ【IPv4編】](https://linuxfan.info/document-ipv4-address)
1. [ドキュメントに利用できるIPv6アドレスの例](https://linuxfan.info/document-ipv6-address)
1. [ドキュメントで例に使えるユニキャストMACアドレスの一覧](https://linuxfan.info/document-mac-address)